From e4a29ecec318700b3dfce8ce2a7883bfc9782e97 Mon Sep 17 00:00:00 2001 From: GitStart <1501599+gitstart@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:02:40 +0100 Subject: [PATCH 001/131] [Fleet] Replace deprecated component EuiLoadingContent (#152157) [Fleet] Replace deprecated component EuiLoadingContent Resolves https://github.com/elastic/kibana/issues/152112 Co-authored-by: LuisChiej <54555805+LuisChiej@users.noreply.github.com> Co-authored-by: gitstart_bot Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/fleet_server_instructions/advanced_tab.tsx | 4 ++-- .../components/confirm_incoming_data_with_preview.tsx | 4 ++-- .../components/agent_details/agent_details_overview.tsx | 8 ++++---- .../components/agent_diagnostics/index.tsx | 4 ++-- .../applications/integrations/sections/epm/index.tsx | 4 ++-- .../sections/epm/screens/detail/overview/notice_modal.tsx | 6 +++--- .../sections/epm/screens/detail/overview/readme.tsx | 8 ++++---- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/advanced_tab.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/advanced_tab.tsx index 79582e94a6226..b9135b3dc716b 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/advanced_tab.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/advanced_tab.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React from 'react'; -import { EuiLoadingContent, EuiSteps } from '@elastic/eui'; +import { EuiSkeletonText, EuiSteps } from '@elastic/eui'; import { useAdvancedForm } from './hooks'; import { useLatestFleetServers } from './hooks/use_latest_fleet_servers'; @@ -83,7 +83,7 @@ export const AdvancedTab: React.FunctionComponent = ({ ]; return isSelectFleetServerPolicyLoading ? ( - + ) : ( ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/confirm_incoming_data_with_preview.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/confirm_incoming_data_with_preview.tsx index 772d90ada7dc1..5e6443986c7c6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/confirm_incoming_data_with_preview.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/multi_page_layout/components/confirm_incoming_data_with_preview.tsx @@ -11,13 +11,13 @@ import { EuiText, EuiSpacer, EuiLink, - EuiLoadingContent, EuiLoadingSpinner, EuiHorizontalRule, EuiFlexGroup, EuiFlexItem, formatDate, EuiDescriptionList, + EuiSkeletonText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; @@ -188,7 +188,7 @@ export const ConfirmIncomingDataWithPreview: React.FunctionComponent = ({ )} - + ); } diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx index 5f0b64051f26f..7fba954a9ca19 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx @@ -15,8 +15,8 @@ import { EuiFlexItem, EuiPanel, EuiIcon, + EuiSkeletonText, EuiToolTip, - EuiLoadingContent, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage, FormattedRelative } from '@kbn/i18n-react'; @@ -128,7 +128,7 @@ export const AgentDetailsOverviewSection: React.FunctionComponent<{ description: agentPolicy ? ( ) : ( - + ), }, { @@ -213,7 +213,7 @@ export const AgentDetailsOverviewSection: React.FunctionComponent<{ /> ) ) : ( - + ), }, { @@ -233,7 +233,7 @@ export const AgentDetailsOverviewSection: React.FunctionComponent<{ /> ) ) : ( - + ), }, { 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 180a1b894ca13..7ec0de9023e32 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 @@ -15,9 +15,9 @@ import { EuiFlexItem, EuiIcon, EuiLink, - EuiLoadingContent, EuiLoadingSpinner, EuiText, + EuiSkeletonText, formatDate, } from '@elastic/eui'; import React, { useCallback, useEffect, useState } from 'react'; @@ -272,7 +272,7 @@ export const AgentDiagnosticsTab: React.FunctionComponent {isLoading ? ( - + ) : ( items={diagnosticsEntries} columns={columns} /> )} diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/index.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/index.tsx index 67ea0781bafc2..ffbc34ab2c55e 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/index.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/index.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { Switch } from 'react-router-dom'; import { Route } from '@kbn/shared-ux-router'; -import { EuiLoadingContent } from '@elastic/eui'; +import { EuiSkeletonText } from '@elastic/eui'; import { INTEGRATIONS_ROUTING_PATHS } from '../../constants'; import { IntegrationsStateContextProvider, useBreadcrumbs } from '../../hooks'; @@ -34,7 +34,7 @@ export const EPMApp: React.FunctionComponent = () => { - }> + }> diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/notice_modal.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/notice_modal.tsx index 4ef6dde3fb2f6..a4ab3c19200bc 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/notice_modal.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/notice_modal.tsx @@ -8,13 +8,13 @@ import React, { useEffect, useState } from 'react'; import { EuiCodeBlock, - EuiLoadingContent, EuiModal, EuiModalBody, EuiModalHeader, EuiModalFooter, EuiModalHeaderTitle, EuiButton, + EuiSkeletonText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -58,10 +58,10 @@ export const NoticeModal: React.FunctionComponent = ({ noticePath, onClos // Simulate a long notice while loading <>

- +

- +

)} diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/readme.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/readme.tsx index 582bbb6dfd31e..52b4f8fbe4fdc 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/readme.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/overview/readme.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiLoadingContent, EuiText } from '@elastic/eui'; +import { EuiText, EuiSkeletonText } from '@elastic/eui'; import React, { Fragment, useEffect, useState } from 'react'; import ReactMarkdown from 'react-markdown'; import remarkGfm from 'remark-gfm'; @@ -57,13 +57,13 @@ export function Readme({ {/* simulates a long page of text loading */}

- +

- +

- +

)} From 68d58bf5c10479f82a9f6bdcf140597e897778d6 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Mon, 27 Feb 2023 08:15:40 -0700 Subject: [PATCH 002/131] Adding KQL autocomplete to Metric Threshold's custom equation editor (#150212) ## Summary This PR closes #149941 by reusing the KQL autocomplete component used for the rule filter. image --- .../custom_equation_editor.stories.tsx | 19 ++++++++++++++ .../custom_equation_editor.tsx | 4 +++ .../custom_equation/metric_row_with_count.tsx | 26 +++++++++++-------- .../components/expression.tsx | 1 + .../components/expression_row.test.tsx | 1 + .../components/expression_row.tsx | 16 ++++++++++-- .../components/validation.tsx | 12 +++++++-- .../autocomplete_field/autocomplete_field.tsx | 3 +++ .../metrics_explorer/components/kuery_bar.tsx | 3 +++ 9 files changed, 70 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.stories.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.stories.tsx index ce30172a74f15..d2fd0639859a6 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.stories.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.stories.tsx @@ -34,6 +34,24 @@ export default { }, } as Meta; +const fakeDataView = { + title: 'metricbeat-*', + fields: [ + { + name: 'system.cpu.user.pct', + type: 'number', + }, + { + name: 'system.cpu.system.pct', + type: 'number', + }, + { + name: 'system.cpu.cores', + type: 'number', + }, + ], +}; + const CustomEquationEditorTemplate: Story = (args) => { const [expression, setExpression] = useState(args.expression); const [errors, setErrors] = useState(args.errors); @@ -60,6 +78,7 @@ const CustomEquationEditorTemplate: Story = (args) => errors={errors} expression={expression} onChange={handleExpressionChange} + dataView={fakeDataView} /> ); }; diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.tsx index 866e818688533..8632616866a7e 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/custom_equation_editor.tsx @@ -16,6 +16,7 @@ import React, { useState, useCallback, useMemo } from 'react'; import { omit, range, first, xor, debounce } from 'lodash'; import { IErrorObject } from '@kbn/triggers-actions-ui-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; +import { DataViewBase } from '@kbn/es-query'; import { OMITTED_AGGREGATIONS_FOR_CUSTOM_METRICS } from '../../../../../common/http_api'; import { Aggregators, @@ -39,6 +40,7 @@ export interface CustomEquationEditorProps { fields: NormalizedFields; aggregationTypes: AggregationTypes; errors: IErrorObject; + dataView: DataViewBase; } const NEW_METRIC = { name: 'A', aggType: Aggregators.AVERAGE as CustomMetricAggTypes }; @@ -53,6 +55,7 @@ export const CustomEquationEditor = ({ fields, aggregationTypes, errors, + dataView, }: CustomEquationEditorProps) => { const [customMetrics, setCustomMetrics] = useState( expression?.customMetrics ?? [NEW_METRIC] @@ -130,6 +133,7 @@ export const CustomEquationEditor = ({ disableDelete={disableDelete} onChange={handleChange} errors={errors} + dataView={dataView} /> ); } diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/metric_row_with_count.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/metric_row_with_count.tsx index 43ac682830bcd..78bc2bf265b4e 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/metric_row_with_count.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/custom_equation/metric_row_with_count.tsx @@ -4,16 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { - EuiFieldText, - EuiFormRow, - EuiHorizontalRule, - EuiFlexItem, - EuiFlexGroup, - EuiSelect, -} from '@elastic/eui'; +import { EuiFormRow, EuiHorizontalRule, EuiFlexItem, EuiFlexGroup, EuiSelect } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; +import { DataViewBase } from '@kbn/es-query'; +import { MetricsExplorerKueryBar } from '../../../../pages/metrics/metrics_explorer/components/kuery_bar'; import { Aggregators, CustomMetricAggTypes } from '../../../../../common/alerting/metrics'; import { MetricRowControls } from './metric_row_controls'; import { MetricRowBaseProps } from './types'; @@ -21,6 +16,7 @@ import { MetricRowBaseProps } from './types'; interface MetricRowWithCountProps extends MetricRowBaseProps { agg?: Aggregators; filter?: string; + dataView: DataViewBase; } export const MetricRowWithCount = ({ @@ -31,6 +27,7 @@ export const MetricRowWithCount = ({ disableDelete, onChange, aggregationTypes, + dataView, }: MetricRowWithCountProps) => { const aggOptions = useMemo( () => @@ -59,10 +56,10 @@ export const MetricRowWithCount = ({ ); const handleFilterChange = useCallback( - (el: React.ChangeEvent) => { + (filterString: string) => { onChange({ name, - filter: el.target.value, + filter: filterString, aggType: agg as CustomMetricAggTypes, }); }, @@ -89,7 +86,14 @@ export const MetricRowWithCount = ({ { defaultMessage: 'KQL Filter {name}', values: { name } } )} > - +
diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx index 5bc6cff8545e1..224bf8d1fb5d0 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression.tsx @@ -311,6 +311,7 @@ export const Expressions: React.FC = (props) => { setRuleParams={updateParams} errors={(errors[idx] as IErrorObject) || emptyError} expression={e || {}} + dataView={derivedIndexPattern} > { timeWindowSize: [], }} expression={expression} + dataView={{ fields: [], title: 'metricbeat-*' }} /> ); diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx index 14ff5b1e60eed..a353b954386c1 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_row.tsx @@ -27,6 +27,7 @@ import { ThresholdExpression, WhenExpression, } from '@kbn/triggers-actions-ui-plugin/public'; +import { DataViewBase } from '@kbn/es-query'; import { Aggregators, Comparator } from '../../../../common/alerting/metrics'; import { decimalToPct, pctToDecimal } from '../../../../common/utils/corrected_percent_convert'; import { DerivedIndexPattern } from '../../../containers/metrics_source'; @@ -54,6 +55,7 @@ interface ExpressionRowProps { addExpression(): void; remove(id: number): void; setRuleParams(id: number, params: MetricExpression): void; + dataView: DataViewBase; } const StyledExpressionRow = euiStyled(EuiFlexGroup)` @@ -74,8 +76,17 @@ const StyledHealth = euiStyled(EuiHealth)` export const ExpressionRow: React.FC = (props) => { const [isExpanded, setRowState] = useState(true); const toggleRowState = useCallback(() => setRowState(!isExpanded), [isExpanded]); - const { children, setRuleParams, expression, errors, expressionId, remove, fields, canDelete } = - props; + const { + dataView, + children, + setRuleParams, + expression, + errors, + expressionId, + remove, + fields, + canDelete, + } = props; const { aggType = AGGREGATION_TYPES.MAX, @@ -325,6 +336,7 @@ export const ExpressionRow: React.FC = (props) => { aggregationTypes={aggregationType} onChange={handleCustomMetricChange} errors={errors} + dataView={dataView} /> diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx index b3d4d423c58b5..83d3919ef6c01 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/validation.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { fromKueryExpression } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { ValidationResult } from '@kbn/triggers-actions-ui-plugin/public'; import { isEmpty } from 'lodash'; @@ -48,7 +49,7 @@ export function validateMetricThreshold({ }; metric: string[]; customMetricsError?: string; - customMetrics: Record; + customMetrics: Record; equation?: string; }; } & { filterQuery?: string[] } = {}; @@ -169,7 +170,7 @@ export function validateMetricThreshold({ ); } else { c.customMetrics.forEach((metric) => { - const customMetricErrors: { aggType?: string; field?: string } = {}; + const customMetricErrors: { aggType?: string; field?: string; filter?: string } = {}; if (!metric.aggType) { customMetricErrors.aggType = i18n.translate( 'xpack.infra.metrics.alertFlyout.error.customMetrics.aggTypeRequired', @@ -186,6 +187,13 @@ export function validateMetricThreshold({ } ); } + if (metric.aggType === 'count' && metric.filter) { + try { + fromKueryExpression(metric.filter); + } catch (e) { + customMetricErrors.filter = e.message; + } + } if (!isEmpty(customMetricErrors)) { errors[id].customMetrics[metric.name] = customMetricErrors; } diff --git a/x-pack/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx b/x-pack/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx index e264da646949c..657db92072275 100644 --- a/x-pack/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx +++ b/x-pack/plugins/infra/public/components/autocomplete_field/autocomplete_field.tsx @@ -24,6 +24,7 @@ interface AutocompleteFieldProps { disabled?: boolean; autoFocus?: boolean; 'aria-label'?: string; + compressed?: boolean; } interface AutocompleteFieldState { @@ -53,6 +54,7 @@ export class AutocompleteField extends React.Component< value, disabled, 'aria-label': ariaLabel, + compressed, } = this.props; const { areSuggestionsVisible, selectedIndex } = this.state; @@ -60,6 +62,7 @@ export class AutocompleteField extends React.Component< { const [draftQuery, setDraftQuery] = useState(value || ''); const [isValid, setValidation] = useState(true); @@ -81,6 +83,7 @@ export const MetricsExplorerKueryBar = ({ {({ isLoadingSuggestions, loadSuggestions, suggestions }) => ( Date: Mon, 27 Feb 2023 10:22:06 -0500 Subject: [PATCH 003/131] [Cloud Security Posture][bug] broken resource findings table with cis aws (#151950) ## Summary Problem: cis aws `resource.id` has `/` characters which break the page. When we use `useParams()`. We are getting an `\` as encoded `%2F`. Afterward, we pass param resourceId with the encoded `\` to `useResourceFindings` which returns no results Solution: We can fix the broken resource findings table by encoding the `resourceid` before navigating to resource findings. Once `ResourceFindingsContainer ` mounts then we need to decode resourceId and pass `resourceId` as another parameter to the `userResourceFindings` hook. image --- .../findings_by_resource_table.tsx | 6 ++++-- .../resource_findings_container.tsx | 14 ++++++++++++-- .../resource_findings/use_resource_findings.ts | 7 ++++++- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_table.tsx index f8ac3dc3ad53a..b25149208ce1a 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/findings_by_resource_table.tsx @@ -16,7 +16,7 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import numeral from '@elastic/numeral'; -import { Link, generatePath } from 'react-router-dom'; +import { generatePath, Link } from 'react-router-dom'; import { i18n } from '@kbn/i18n'; import { ColumnNameWithTooltip } from '../../../components/column_name_with_tooltip'; import { ComplianceScoreBar } from '../../../components/compliance_score_bar'; @@ -126,7 +126,9 @@ const baseColumns: Array> = width: '15%', render: (resourceId: FindingsByResourcePage['resource_id']) => ( diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx index 268ea6f393a99..a9598b228f3ae 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/resource_findings_container.tsx @@ -69,6 +69,7 @@ const getResourceFindingSharedValues = (sharedValues: { resourceSubType: string; resourceName: string; clusterId: string; + cloudAccountName: string; }): EuiDescriptionListProps['listItems'] => [ { title: i18n.translate('xpack.csp.findings.resourceFindingsSharedValues.resourceTypeTitle', { @@ -88,10 +89,18 @@ const getResourceFindingSharedValues = (sharedValues: { }), description: sharedValues.clusterId, }, + { + title: i18n.translate('xpack.csp.findings.resourceFindingsSharedValues.cloudAccountName', { + defaultMessage: 'Cloud Account Name', + }), + description: sharedValues.cloudAccountName, + }, ]; export const ResourceFindings = ({ dataView }: FindingsBaseProps) => { const params = useParams<{ resourceId: string }>(); + const decodedResourceId = decodeURIComponent(params.resourceId); + const getPersistedDefaultQuery = usePersistedQuery(getDefaultQuery); const { urlQuery, setUrlQuery } = useUrlQuery(getPersistedDefaultQuery); const { pageSize, setPageSize } = usePageSize(LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY); @@ -111,7 +120,7 @@ export const ResourceFindings = ({ dataView }: FindingsBaseProps) => { const resourceFindings = useResourceFindings({ sort: urlQuery.sort, query: baseEsQuery.query, - resourceId: params.resourceId, + resourceId: decodedResourceId, enabled: !baseEsQuery.error, }); @@ -213,10 +222,11 @@ export const ResourceFindings = ({ dataView }: FindingsBaseProps) => { resourceFindings.data && ( ) diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/use_resource_findings.ts b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/use_resource_findings.ts index a2314dc50b50d..17520e68bceb9 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/use_resource_findings.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/latest_findings_by_resource/resource_findings/use_resource_findings.ts @@ -35,7 +35,7 @@ type ResourceFindingsResponse = IKibanaSearchResponse< >; export type ResourceFindingsResponseAggs = Record< - 'count' | 'clusterId' | 'resourceSubType' | 'resourceName', + 'count' | 'clusterId' | 'resourceSubType' | 'resourceName' | 'cloudAccountName', estypes.AggregationsMultiBucketAggregateBase< estypes.AggregationsStringRareTermsBucketKeys | undefined > @@ -59,6 +59,9 @@ const getResourceFindingsQuery = ({ sort: [{ [sort.field]: sort.direction }], aggs: { ...getFindingsCountAggQuery(), + cloudAccountName: { + terms: { field: 'cloud.account.name' }, + }, clusterId: { terms: { field: 'cluster_id' }, }, @@ -98,6 +101,7 @@ export const useResourceFindings = (options: UseResourceFindingsOptions) => { assertNonBucketsArray(aggregations.clusterId?.buckets); assertNonBucketsArray(aggregations.resourceSubType?.buckets); assertNonBucketsArray(aggregations.resourceName?.buckets); + assertNonBucketsArray(aggregations.cloudAccountName?.buckets); return { page: hits.hits.map((hit) => hit._source!), @@ -106,6 +110,7 @@ export const useResourceFindings = (options: UseResourceFindingsOptions) => { clusterId: getFirstBucketKey(aggregations.clusterId?.buckets), resourceSubType: getFirstBucketKey(aggregations.resourceSubType?.buckets), resourceName: getFirstBucketKey(aggregations.resourceName?.buckets), + cloudAccountName: getFirstBucketKey(aggregations.cloudAccountName?.buckets), }; }, onError: (err: Error) => showErrorToast(toasts, err), From 74fa43e5e4b3d0fcdfc9b1178aea5f5c5dc6eb2e Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Mon, 27 Feb 2023 11:02:18 -0500 Subject: [PATCH 004/131] [Security Solution] Remove beta tag from process ancestry insight component (#152011) ## Summary PR just removes the beta badge from the ancestry insight part of the alert flyout component. No change in functionality. whatev image --- .../insights/related_alerts_by_process_ancestry.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx index 99c842cd48810..43807363dda1f 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/insights/related_alerts_by_process_ancestry.tsx @@ -6,7 +6,7 @@ */ import React, { useMemo, useCallback, useEffect, useState } from 'react'; -import { EuiBetaBadge, EuiSpacer, EuiLoadingSpinner } from '@elastic/eui'; +import { EuiSpacer, EuiLoadingSpinner } from '@elastic/eui'; import type { Filter } from '@kbn/es-query'; import { isActiveTimeline } from '../../../../helpers'; @@ -25,7 +25,6 @@ import { PROCESS_ANCESTRY_ERROR, PROCESS_ANCESTRY_FILTER, } from './translations'; -import { BETA } from '../../../translations'; interface Props { data: TimelineEventsDetailsItem; @@ -102,8 +101,6 @@ export const RelatedAlertsByProcessAncestry = React.memo( ); }, [showContent, cache.alertIds, data, index, originalDocumentId, eventId, scopeId]); - const betaBadge = useMemo(() => , []); - return ( ( } renderContent={renderContent} onToggle={onToggle} - extraAction={betaBadge} /> ); } From 83f50723988e9de288612f83eaaa4fe0432a8f10 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Mon, 27 Feb 2023 17:04:15 +0100 Subject: [PATCH 005/131] [Synthetics] Add key to avoid react log warning (#152132) --- .../components/settings/private_locations/locations_table.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx index b6996d4e6149b..d5246581b2176 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx @@ -129,6 +129,7 @@ export const PrivateLocationsTable = ({ const renderToolRight = () => { return [ Date: Mon, 27 Feb 2023 11:28:33 -0500 Subject: [PATCH 006/131] Allow appex-qa team to skip failed tests using automation (#151794) --- .github/workflows/skip-failed-test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/skip-failed-test.yml b/.github/workflows/skip-failed-test.yml index e892582951adc..a6535b106c728 100644 --- a/.github/workflows/skip-failed-test.yml +++ b/.github/workflows/skip-failed-test.yml @@ -26,6 +26,7 @@ jobs: uses: ./actions/permission-check with: permission: admin + teams: appex-qa token: ${{secrets.GITHUB_TOKEN}} - name: Checkout kibana-operations From 6e80cea86c1a25c2145142291561beda4256711d Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Mon, 27 Feb 2023 11:29:01 -0500 Subject: [PATCH 007/131] [Response Ops][Actions] Update json editor value for default body (#152133) ## Summary See https://github.com/elastic/kibana/pull/151851 for link to bug description and details about the fix. This PR adds a fix for behavior in the ES index connector params component that appeared as a result of the changes in the JSON editor. When the JSON editor is modified to re-render with `useEffect`, the ES index connector `onBlur` behavior would auto-populate the editor with `[object Object]`. This PR updates the component to work with the re-render. --------- Co-authored-by: semd Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../es_index/es_index_params.tsx | 43 ++++++++++++------- ...son_editor_with_message_variables.test.tsx | 14 ++++++ .../json_editor_with_message_variables.tsx | 9 +++- 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index_params.tsx b/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index_params.tsx index be34c715fb8d4..fc51ae0ba1ccf 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index_params.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index_params.tsx @@ -6,6 +6,7 @@ */ import React, { useEffect, useState } from 'react'; +import { isEmpty } from 'lodash'; import { EuiIcon, EuiText, @@ -45,10 +46,25 @@ export const IndexParamsFields = ({ ); const [isActionConnectorChanged, setIsActionConnectorChanged] = useState(false); - const getDocumentToIndex = (doc: Array> | undefined) => - doc && doc.length > 0 ? (doc[0] as unknown as string) : undefined; + const getDocumentToIndex = (docs: Array> | undefined) => { + // 'documents' param is stored as an array of objects but the JSON editor expects a single + // stringified object - const [documentToIndex, setDocumentToIndex] = useState( + // check that param is a non-empty array + return docs && docs.length > 0 + ? // if the array entry is a string, we can pass it directly to the JSON editor + typeof docs[0] === 'string' + ? docs[0] + : // otherwise check that the array entry is non-empty as sometimes we + // use an empty object to trigger validation but we don't want to auto-populate with an empty object + !isEmpty(docs[0]) + ? // if non-empty object, stringify it into format that JSON editor expects + JSON.stringify(docs[0], null, 2) + : null + : undefined; + }; + + const [documentToIndex, setDocumentToIndex] = useState( getDocumentToIndex(documents) ); const [alertHistoryIndexSuffix, setAlertHistoryIndexSuffix] = useState( @@ -58,9 +74,6 @@ export const IndexParamsFields = ({ useEffect(() => { setDocumentToIndex(getDocumentToIndex(documents)); - if (documents === null) { - setDocumentToIndex('{}'); - } }, [documents]); useEffect(() => { @@ -77,10 +90,14 @@ export const IndexParamsFields = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [actionConnector?.id]); - const onDocumentsChange = (updatedDocuments: string) => { + const onDocumentsChange = (updatedDocuments: string | null) => { try { - const documentsJSON = JSON.parse(updatedDocuments); - editAction('documents', [documentsJSON], index); + if (updatedDocuments != null) { + const documentsJSON = JSON.parse(updatedDocuments); + editAction('documents', [documentsJSON], index); + } else { + editAction('documents', updatedDocuments, index); + } setDocumentToIndex(updatedDocuments); } catch (e) { // set document as empty to turn on the validation for non empty valid JSON object @@ -180,11 +197,7 @@ export const IndexParamsFields = ({ messageVariables={messageVariables} paramsProperty={'documents'} data-test-subj="documentToIndex" - inputTargetValue={ - documentToIndex === null - ? '{}' // need this to trigger validation - : documentToIndex - } + inputTargetValue={documentToIndex} label={documentsFieldLabel} aria-label={i18n.translate('xpack.stackConnectors.components.index.jsonDocAriaLabel', { defaultMessage: 'Code editor', @@ -202,7 +215,7 @@ export const IndexParamsFields = ({ onBlur={() => { if (!documentToIndex) { // set document as empty to turn on the validation for non empty valid JSON object - onDocumentsChange('{}'); + onDocumentsChange(null); } }} /> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.test.tsx index 5349e60a60adb..0cac98f01f636 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.test.tsx @@ -69,4 +69,18 @@ describe('JsonEditorWithMessageVariables', () => { '{{{myVar}}}' ); }); + + test('renders correct value when the input value prop updates', () => { + const wrapper = mountWithIntl(); + + expect(wrapper.find('[data-test-subj="fooJsonEditor"]').first().prop('value')).toEqual(''); + + const inputTargetValue = '{"new": "value"}'; + wrapper.setProps({ inputTargetValue }); + wrapper.update(); + + expect(wrapper.find('[data-test-subj="fooJsonEditor"]').first().prop('value')).toEqual( + inputTargetValue + ); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx index 643e1b69a513d..3485a99c39456 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/json_editor_with_message_variables.tsx @@ -37,7 +37,7 @@ interface Props { buttonTitle?: string; messageVariables?: ActionVariable[]; paramsProperty: string; - inputTargetValue?: string; + inputTargetValue?: string | null; label: string; errors?: string[]; areaLabel?: string; @@ -75,6 +75,13 @@ export const JsonEditorWithMessageVariables: React.FunctionComponent = ({ const { convertToJson, setXJson, xJson } = useXJsonMode(inputTargetValue ?? null); + useEffect(() => { + if (!xJson && inputTargetValue) { + setXJson(inputTargetValue); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [inputTargetValue]); + const onSelectMessageVariable = (variable: ActionVariable) => { const editor = editorRef.current; if (!editor) { From 14a3da69086ea5b9059b925a54811735e804e28c Mon Sep 17 00:00:00 2001 From: Bree Hall <40739624+breehall@users.noreply.github.com> Date: Mon, 27 Feb 2023 11:31:51 -0500 Subject: [PATCH 008/131] Upgrade EUI to v75.1.2 (#152027) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary EUI `75.1.1` ➡️ `75.1.2` ## [`75.1.2`](https://github.com/elastic/eui/tree/v75.1.2) **Bug fixes** - Fixed bug in `EuiPopover` where multiple filter `drop-shadow()` were causing inner shadows in Safari ([#6604](https://github.com/elastic/eui/pull/6604)) --- package.json | 2 +- src/dev/license_checker/config.ts | 2 +- .../server/__snapshots__/prompt_page.test.tsx.snap | 4 ++-- .../__snapshots__/unauthenticated_page.test.tsx.snap | 4 ++-- .../__snapshots__/reset_session_page.test.tsx.snap | 4 ++-- yarn.lock | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 6c532d3af8dec..fd551a6571e62 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,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": "75.1.0", + "@elastic/eui": "75.1.2", "@elastic/filesaver": "1.1.2", "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index dd0600b71d2b2..e45c89bf69b7a 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -84,6 +84,6 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@8.4.0': ['Elastic License 2.0'], - '@elastic/eui@75.1.0': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@75.1.2': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/x-pack/plugins/security/server/__snapshots__/prompt_page.test.tsx.snap b/x-pack/plugins/security/server/__snapshots__/prompt_page.test.tsx.snap index 79709d6cc5573..49d0d83a5e8c6 100644 --- a/x-pack/plugins/security/server/__snapshots__/prompt_page.test.tsx.snap +++ b/x-pack/plugins/security/server/__snapshots__/prompt_page.test.tsx.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`PromptPage renders as expected with additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; +exports[`PromptPage renders as expected with additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; -exports[`PromptPage renders as expected without additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; +exports[`PromptPage renders as expected without additional scripts 1`] = `"ElasticMockedFonts

Some Title

Some Body
Action#1
Action#2
"`; diff --git a/x-pack/plugins/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap b/x-pack/plugins/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap index cd7cf4d96e698..3f01f0ca7c8bf 100644 --- a/x-pack/plugins/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap +++ b/x-pack/plugins/security/server/authentication/__snapshots__/unauthenticated_page.test.tsx.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`UnauthenticatedPage renders as expected 1`] = `"ElasticMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; +exports[`UnauthenticatedPage renders as expected 1`] = `"ElasticMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; -exports[`UnauthenticatedPage renders as expected with custom title 1`] = `"My Company NameMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; +exports[`UnauthenticatedPage renders as expected with custom title 1`] = `"My Company NameMockedFonts

We hit an authentication error

Try logging in again, and if the problem persists, contact your system administrator.

"`; diff --git a/x-pack/plugins/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap b/x-pack/plugins/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap index 060229539b9ad..b8ec6b35fe6b2 100644 --- a/x-pack/plugins/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap +++ b/x-pack/plugins/security/server/authorization/__snapshots__/reset_session_page.test.tsx.snap @@ -1,5 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ResetSessionPage renders as expected 1`] = `"ElasticMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; +exports[`ResetSessionPage renders as expected 1`] = `"ElasticMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; -exports[`ResetSessionPage renders as expected with custom page title 1`] = `"My Company NameMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; +exports[`ResetSessionPage renders as expected with custom page title 1`] = `"My Company NameMockedFonts

You do not have permission to access the requested page

Either go back to the previous page or log in as a different user.

"`; diff --git a/yarn.lock b/yarn.lock index 1fd92f43a8fdb..905ce3e6a3b5d 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@75.1.0": - version "75.1.0" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-75.1.0.tgz#6bdb2a12e5dd503258e74d5585803f52b826b83e" - integrity sha512-HJgoARNsXeYDIGO9sKV+wwfmFA2IKL9hjOMj8B0PZ4fA6Euprw7KPLkakUbwjTCm0rqYUf/6zmXRafvzvdKLmA== +"@elastic/eui@75.1.2": + version "75.1.2" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-75.1.2.tgz#c8ccb1728162b131e49a16833468ab2b0228f1bf" + integrity sha512-J6u16NR3BD5snje2CSWnk+JvEQ7y/8tzpmi2Ul+WWfzQwvf7DsKtouSIs91jdzC1QGSN26S1D3wKZvzaszXacg== dependencies: "@types/chroma-js" "^2.0.0" "@types/lodash" "^4.14.160" From 1a268118f4787812f69fb648bdef148e4bac4cf9 Mon Sep 17 00:00:00 2001 From: Rodney Norris Date: Mon, 27 Feb 2023 10:37:03 -0600 Subject: [PATCH 009/131] Enterprise Search: implement engine field caps in kibana (#152036) ## Summary migrated the fetching of engine field capabilities to be handled in Kibana server. This still required fetching the engine from the enterprise search server to fill out all the fields in the expected response. Which required writing a helper for fetching data from enterprise search without just doing a proxy request. I expect this helper will be removed and replaced with fetching the engine from the Elasticsearch once we migrate engines to the module. --- .../common/types/error_codes.ts | 1 + .../lib/engines/field_capabilities.test.ts | 52 +++++++ .../server/lib/engines/field_capabilities.ts | 34 +++++ .../routes/enterprise_search/engines.test.ts | 127 ++++++++++++++++++ .../routes/enterprise_search/engines.ts | 42 +++++- .../utils/fetch_enterprise_search.test.ts | 111 +++++++++++++++ .../server/utils/fetch_enterprise_search.ts | 54 ++++++++ 7 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.ts create mode 100644 x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.ts create mode 100644 x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.test.ts create mode 100644 x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.ts diff --git a/x-pack/plugins/enterprise_search/common/types/error_codes.ts b/x-pack/plugins/enterprise_search/common/types/error_codes.ts index 134fb7ebf395e..a2c37a2ba7264 100644 --- a/x-pack/plugins/enterprise_search/common/types/error_codes.ts +++ b/x-pack/plugins/enterprise_search/common/types/error_codes.ts @@ -19,4 +19,5 @@ export enum ErrorCode { RESOURCE_NOT_FOUND = 'resource_not_found', UNAUTHORIZED = 'unauthorized', UNCAUGHT_EXCEPTION = 'uncaught_exception', + ENGINE_NOT_FOUND = 'engine_not_found', } diff --git a/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.ts b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.ts new file mode 100644 index 0000000000000..3e250e4ec9109 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.test.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 { FieldCapsResponse } from '@elastic/elasticsearch/lib/api/types'; +import { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; + +import { EnterpriseSearchEngineDetails } from '../../../common/types/engines'; + +import { fetchEngineFieldCapabilities } from './field_capabilities'; + +describe('engines field_capabilities', () => { + const mockClient = { + asCurrentUser: { + fieldCaps: jest.fn(), + }, + asInternalUser: {}, + }; + const mockEngine: EnterpriseSearchEngineDetails = { + created: '1999-12-31T23:59:59.999Z', + indices: [], + name: 'unit-test-engine', + updated: '1999-12-31T23:59:59.999Z', + }; + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('gets engine alias field capabilities', async () => { + const fieldCapsResponse = {} as FieldCapsResponse; + + mockClient.asCurrentUser.fieldCaps.mockResolvedValueOnce(fieldCapsResponse); + await expect( + fetchEngineFieldCapabilities(mockClient as unknown as IScopedClusterClient, mockEngine) + ).resolves.toEqual({ + created: mockEngine.created, + field_capabilities: fieldCapsResponse, + name: mockEngine.name, + updated: mockEngine.updated, + }); + + expect(mockClient.asCurrentUser.fieldCaps).toHaveBeenCalledTimes(1); + expect(mockClient.asCurrentUser.fieldCaps).toHaveBeenCalledWith({ + fields: '*', + include_unmapped: true, + index: 'search-engine-unit-test-engine', + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.ts b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.ts new file mode 100644 index 0000000000000..ed42ab744621c --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/engines/field_capabilities.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; + +import { + EnterpriseSearchEngineDetails, + EnterpriseSearchEngineFieldCapabilities, +} from '../../../common/types/engines'; + +export const fetchEngineFieldCapabilities = async ( + client: IScopedClusterClient, + engine: EnterpriseSearchEngineDetails +): Promise => { + const { created, name, updated } = engine; + const fieldCapabilities = await client.asCurrentUser.fieldCaps({ + fields: '*', + include_unmapped: true, + index: getEngineIndexAliasName(name), + }); + return { + created, + field_capabilities: fieldCapabilities, + name, + updated, + }; +}; + +// Note: This will likely need to be modified when engines move to es module +const getEngineIndexAliasName = (engineName: string): string => `search-engine-${engineName}`; diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.test.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.test.ts index 83e31f1ddf03d..019cca3a7acc2 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.test.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.test.ts @@ -7,6 +7,19 @@ import { mockDependencies, mockRequestHandler, MockRouter } from '../../__mocks__'; +jest.mock('../../utils/fetch_enterprise_search', () => ({ + ...jest.requireActual('../../utils/fetch_enterprise_search'), + fetchEnterpriseSearch: jest.fn(), +})); +jest.mock('../../lib/engines/field_capabilities', () => ({ + fetchEngineFieldCapabilities: jest.fn(), +})); + +import { RequestHandlerContext } from '@kbn/core/server'; + +import { fetchEngineFieldCapabilities } from '../../lib/engines/field_capabilities'; +import { fetchEnterpriseSearch } from '../../utils/fetch_enterprise_search'; + import { registerEnginesRoutes } from './engines'; describe('engines routes', () => { @@ -298,4 +311,118 @@ describe('engines routes', () => { mockRouter.shouldThrow(request); }); }); + + describe('GET /internal/enterprise_search/engines/{engine_name}/field_capabilities', () => { + let mockRouter: MockRouter; + const mockClient = { + asCurrentUser: {}, + }; + const mockCore = { + elasticsearch: { client: mockClient }, + savedObjects: { client: {} }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + + const context = { + core: Promise.resolve(mockCore), + } as unknown as jest.Mocked; + + mockRouter = new MockRouter({ + context, + method: 'get', + path: '/internal/enterprise_search/engines/{engine_name}/field_capabilities', + }); + + registerEnginesRoutes({ + ...mockDependencies, + router: mockRouter.router, + }); + }); + + it('fetches engine fields', async () => { + const engineResult = { + created: '1999-12-31T23:59:59.999Z', + indices: [], + name: 'unit-test', + updated: '1999-12-31T23:59:59.999Z', + }; + const fieldCapabilitiesResult = { + name: 'unit-test', + }; + + (fetchEnterpriseSearch as jest.Mock).mockResolvedValueOnce(engineResult); + (fetchEngineFieldCapabilities as jest.Mock).mockResolvedValueOnce(fieldCapabilitiesResult); + + await mockRouter.callRoute({ + params: { engine_name: 'unit-test' }, + }); + + expect(fetchEnterpriseSearch).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + '/api/engines/unit-test' + ); + expect(fetchEngineFieldCapabilities).toHaveBeenCalledWith(mockClient, engineResult); + expect(mockRouter.response.ok).toHaveBeenCalledWith({ + body: fieldCapabilitiesResult, + headers: { 'content-type': 'application/json' }, + }); + }); + it('returns 404 when fetch engine is undefined', async () => { + (fetchEnterpriseSearch as jest.Mock).mockResolvedValueOnce(undefined); + await mockRouter.callRoute({ + params: { engine_name: 'unit-test' }, + }); + + expect(mockRouter.response.customError).toHaveBeenCalledWith({ + body: { + attributes: { + error_code: 'engine_not_found', + }, + message: 'Could not find engine', + }, + statusCode: 404, + }); + }); + it('returns 404 when fetch engine is returns 404', async () => { + (fetchEnterpriseSearch as jest.Mock).mockResolvedValueOnce({ + responseStatus: 404, + responseStatusText: 'NOT_FOUND', + }); + await mockRouter.callRoute({ + params: { engine_name: 'unit-test' }, + }); + + expect(mockRouter.response.customError).toHaveBeenCalledWith({ + body: { + attributes: { + error_code: 'engine_not_found', + }, + message: 'Could not find engine', + }, + statusCode: 404, + }); + }); + it('returns error when fetch engine returns an error', async () => { + (fetchEnterpriseSearch as jest.Mock).mockResolvedValueOnce({ + responseStatus: 500, + responseStatusText: 'INTERNAL_SERVER_ERROR', + }); + await mockRouter.callRoute({ + params: { engine_name: 'unit-test' }, + }); + + expect(mockRouter.response.customError).toHaveBeenCalledWith({ + body: { + attributes: { + error_code: 'uncaught_exception', + }, + message: 'Error fetching engine', + }, + statusCode: 500, + }); + }); + }); }); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.ts index 71b0061a7d1ba..111c04e6cd42e 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/engines.ts @@ -6,15 +6,22 @@ */ import { schema } from '@kbn/config-schema'; +import { EnterpriseSearchEngineDetails } from '../../../common/types/engines'; +import { ErrorCode } from '../../../common/types/error_codes'; import { createApiKey } from '../../lib/engines/create_api_key'; +import { fetchEngineFieldCapabilities } from '../../lib/engines/field_capabilities'; import { RouteDependencies } from '../../plugin'; + +import { createError } from '../../utils/create_error'; import { elasticsearchErrorHandler } from '../../utils/elasticsearch_error_handler'; +import { fetchEnterpriseSearch, isResponseError } from '../../utils/fetch_enterprise_search'; export function registerEnginesRoutes({ - router, + config, enterpriseSearchRequestHandler, log, + router, }: RouteDependencies) { router.get( { @@ -134,8 +141,37 @@ export function registerEnginesRoutes({ path: '/internal/enterprise_search/engines/{engine_name}/field_capabilities', validate: { params: schema.object({ engine_name: schema.string() }) }, }, - enterpriseSearchRequestHandler.createRequest({ - path: '/api/engines/:engine_name/field_capabilities', + elasticsearchErrorHandler(log, async (context, request, response) => { + const engineName = decodeURIComponent(request.params.engine_name); + const { client } = (await context.core).elasticsearch; + + const engine = await fetchEnterpriseSearch( + config, + request, + `/api/engines/${engineName}` + ); + if (!engine || (isResponseError(engine) && engine.responseStatus === 404)) { + return createError({ + errorCode: ErrorCode.ENGINE_NOT_FOUND, + message: 'Could not find engine', + response, + statusCode: 404, + }); + } + if (isResponseError(engine)) { + return createError({ + errorCode: ErrorCode.UNCAUGHT_EXCEPTION, + message: 'Error fetching engine', + response, + statusCode: engine.responseStatus, + }); + } + + const data = await fetchEngineFieldCapabilities(client, engine); + return response.ok({ + body: data, + headers: { 'content-type': 'application/json' }, + }); }) ); } diff --git a/x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.test.ts b/x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.test.ts new file mode 100644 index 0000000000000..20fe7b57350ee --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.test.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import '../__mocks__/http_agent.mock'; + +jest.mock('node-fetch'); +import fetch from 'node-fetch'; + +import { KibanaRequest } from '@kbn/core/server'; + +import { ConfigType } from '..'; + +import { fetchEnterpriseSearch, isResponseError } from './fetch_enterprise_search'; + +describe('fetchEnterpriseSearch', () => { + const mockConfig = { + accessCheckTimeout: 200, + accessCheckTimeoutWarning: 100, + host: 'http://localhost:3002', + }; + const mockRequest = { + headers: { authorization: '==someAuth' }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('returns json fetch response', async () => { + const response = { foo: 'bar' }; + (fetch as unknown as jest.Mock).mockResolvedValueOnce({ + json: jest.fn().mockResolvedValueOnce(response), + ok: true, + }); + await expect( + fetchEnterpriseSearch(mockConfig as ConfigType, mockRequest as KibanaRequest, '/api/v1/test') + ).resolves.toBe(response); + }); + it('calls expected endpoint', async () => { + (fetch as unknown as jest.Mock).mockResolvedValueOnce({ + json: jest.fn().mockResolvedValueOnce({}), + ok: true, + }); + await fetchEnterpriseSearch( + mockConfig as ConfigType, + mockRequest as KibanaRequest, + '/api/v1/test' + ); + + expect(fetch).toHaveBeenCalledTimes(1); + expect(fetch).toHaveBeenCalledWith('http://localhost:3002/api/v1/test', expect.anything()); + }); + it('uses request auth header & config custom headers', async () => { + (fetch as unknown as jest.Mock).mockResolvedValueOnce({ + json: jest.fn().mockResolvedValueOnce({}), + ok: true, + }); + const config = { + ...mockConfig, + customHeaders: { + foo: 'bar', + }, + }; + await fetchEnterpriseSearch( + config as unknown as ConfigType, + mockRequest as KibanaRequest, + '/api/v1/test' + ); + + expect(fetch).toHaveBeenCalledTimes(1); + expect(fetch).toHaveBeenCalledWith(expect.anything(), { + agent: expect.anything(), + headers: { + Authorization: mockRequest.headers.authorization, + foo: 'bar', + }, + }); + }); + it('returns undefined when config.host is unavailable', async () => { + await expect( + fetchEnterpriseSearch( + { host: '' } as ConfigType, + mockRequest as KibanaRequest, + '/api/v1/test' + ) + ).resolves.toBeUndefined(); + }); +}); + +describe('isResponseError', () => { + it('returns true for ResponseError object', () => { + expect(isResponseError({ responseStatus: 404, responseStatusText: 'NOT_FOUND' })).toBe(true); + }); + it('returns false for null/undefined', () => { + expect(isResponseError(null)).toBe(false); + expect(isResponseError(undefined)).toBe(false); + }); + it('returns false for object without expected keys', () => { + expect(isResponseError({})).toBe(false); + expect(isResponseError({ responseStatusText: 'NOT_FOUND' })).toBe(false); + expect(isResponseError({ responseStatus: 404 })).toBe(false); + expect(isResponseError([])).toBe(false); + }); + it('returns false for non-object', () => { + expect(isResponseError(100)).toBe(false); + expect(isResponseError('test')).toBe(false); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.ts b/x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.ts new file mode 100644 index 0000000000000..b1a2146a86ab9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/fetch_enterprise_search.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import fetch, { RequestInit } from 'node-fetch'; + +import { KibanaRequest } from '@kbn/core/server'; + +import { ConfigType } from '..'; + +import { entSearchHttpAgent } from '../lib/enterprise_search_http_agent'; + +export interface ResponseError { + responseStatus: number; + responseStatusText: string; +} + +export function isResponseError(resp: unknown): resp is ResponseError { + if (typeof resp !== 'object') return false; + if (resp === null) return false; + if ('responseStatus' in resp && 'responseStatusText' in resp) return true; + return false; +} + +export async function fetchEnterpriseSearch( + config: ConfigType, + request: KibanaRequest, + endpoint: string +): Promise { + if (!config.host) return undefined; + + const enterpriseSearchUrl = encodeURI(`${config.host}${endpoint}`); + const options: RequestInit = { + agent: entSearchHttpAgent.getHttpAgent(), + headers: { + Authorization: request.headers.authorization as string, + ...config.customHeaders, + }, + }; + + const response = await fetch(enterpriseSearchUrl, options); + + if (!response.ok) { + return { + responseStatus: response.status, + responseStatusText: response.statusText, + }; + } + + return await response.json(); +} From 17e41eb220909d8459c2601ad15d395459dfd5b4 Mon Sep 17 00:00:00 2001 From: Cristina Amico Date: Mon, 27 Feb 2023 17:50:08 +0100 Subject: [PATCH 010/131] [Fleet] Change agent reassign API from PUT to POST (#152236) Closes https://github.com/elastic/kibana/issues/136805 ## Summary Change `agents/{agentId}/reassign` API from `PUT` to `POST` to make it consistent with other APIs on agent actions As part of this task I'm marking as deprecated the PUT endpoint and updating the openApi docs ### Checklist - [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 --- .../plugins/fleet/common/openapi/bundled.json | 46 ++++++++++++++++++- .../plugins/fleet/common/openapi/bundled.yaml | 29 +++++++++++- .../paths/agents@{agent_id}@reassign.yaml | 29 +++++++++++- .../fleet/common/types/rest_spec/agent.ts | 12 ++++- .../agent_reassign_policy_modal/index.tsx | 4 +- .../fleet/public/hooks/use_request/agents.ts | 12 ++--- x-pack/plugins/fleet/public/types/index.ts | 4 +- .../fleet/server/routes/agent/handlers.ts | 33 +++++++++++-- .../fleet/server/routes/agent/index.ts | 22 +++++++-- .../fleet/server/types/rest_spec/agent.ts | 11 ++++- .../apis/agents/reassign.ts | 8 ++-- 11 files changed, 183 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index acb1360d39f83..eb7dcf0cad55c 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -2078,7 +2078,7 @@ "required": true } ], - "put": { + "post": { "summary": "Agent - Reassign", "tags": [], "responses": { @@ -2120,6 +2120,50 @@ } } } + }, + "put": { + "summary": "Agent - Reassign", + "tags": [], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + }, + "400": { + "$ref": "#/components/responses/error" + } + }, + "operationId": "reassign-agent-deprecated", + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "policy_id": { + "type": "string" + } + }, + "required": [ + "policy_id" + ] + } + } + } + }, + "deprecated": true } }, "/agents/{agentId}/unenroll": { diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 7127151e5c2c3..5f67c8630b0dc 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -1301,7 +1301,7 @@ paths: name: agentId in: path required: true - put: + post: summary: Agent - Reassign tags: [] responses: @@ -1327,6 +1327,33 @@ paths: type: string required: - policy_id + put: + summary: Agent - Reassign + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + '400': + $ref: '#/components/responses/error' + operationId: reassign-agent-deprecated + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + policy_id: + type: string + required: + - policy_id + deprecated: true /agents/{agentId}/unenroll: parameters: - schema: diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml index 4827cc77fc634..af00d1563854e 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml @@ -4,7 +4,7 @@ parameters: name: agentId in: path required: true -put: +post: summary: Agent - Reassign tags: [] responses: @@ -30,4 +30,31 @@ put: type: string required: - policy_id +put: + summary: Agent - Reassign + tags: [] + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + '400': + $ref: ../components/responses/error.yaml + operationId: reassign-agent-deprecated + parameters: + - $ref: ../components/headers/kbn_xsrf.yaml + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + policy_id: + type: string + required: + - policy_id + deprecated: true diff --git a/x-pack/plugins/fleet/common/types/rest_spec/agent.ts b/x-pack/plugins/fleet/common/types/rest_spec/agent.ts index 7a73829838d55..603eeed136059 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/agent.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/agent.ts @@ -119,15 +119,25 @@ export type PostBulkAgentUpgradeResponse = BulkAgentAction; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PostAgentUpgradeResponse {} +// deprecated export interface PutAgentReassignRequest { params: { agentId: string; }; body: { policy_id: string }; } - +// deprecated // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PutAgentReassignResponse {} +export interface PostAgentReassignRequest { + params: { + agentId: string; + }; + body: { policy_id: string }; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface PostAgentReassignResponse {} export interface PostBulkAgentReassignRequest { body: { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx index cb3f0d77eed34..5fd6183863fb6 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/components/agent_reassign_policy_modal/index.tsx @@ -19,7 +19,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { Agent } from '../../../../types'; import { - sendPutAgentReassign, + sendPostAgentReassign, sendPostBulkAgentReassign, useStartServices, useGetAgentPolicies, @@ -71,7 +71,7 @@ export const AgentReassignAgentPolicyModal: React.FunctionComponent = ({ throw new Error('No selected agent policy id'); } const res = isSingleAgent - ? await sendPutAgentReassign((agents[0] as Agent).id, { + ? await sendPostAgentReassign((agents[0] as Agent).id, { policy_id: selectedAgentPolicyId, }) : await sendPostBulkAgentReassign({ diff --git a/x-pack/plugins/fleet/public/hooks/use_request/agents.ts b/x-pack/plugins/fleet/public/hooks/use_request/agents.ts index ca53345bb5799..4a23950b0bf56 100644 --- a/x-pack/plugins/fleet/public/hooks/use_request/agents.ts +++ b/x-pack/plugins/fleet/public/hooks/use_request/agents.ts @@ -26,8 +26,8 @@ import type { PostBulkAgentUnenrollRequest, PostBulkAgentUnenrollResponse, PostAgentUnenrollResponse, - PutAgentReassignRequest, - PutAgentReassignResponse, + PostAgentReassignRequest, + PostAgentReassignResponse, PostBulkAgentReassignRequest, PostBulkAgentReassignResponse, GetAgentsRequest, @@ -126,13 +126,13 @@ export function sendGetAgentTags(query: GetAgentsRequest['query'], options?: Req }); } -export function sendPutAgentReassign( +export function sendPostAgentReassign( agentId: string, - body: PutAgentReassignRequest['body'], + body: PostAgentReassignRequest['body'], options?: RequestOptions ) { - return sendRequest({ - method: 'put', + return sendRequest({ + method: 'post', path: agentRouteService.getReassignPath(agentId), body, ...options, diff --git a/x-pack/plugins/fleet/public/types/index.ts b/x-pack/plugins/fleet/public/types/index.ts index 530b8701ab9f4..8ce5cc30cde9e 100644 --- a/x-pack/plugins/fleet/public/types/index.ts +++ b/x-pack/plugins/fleet/public/types/index.ts @@ -69,8 +69,8 @@ export type { GetAgentIncomingDataRequest, IncomingDataList, GetAgentIncomingDataResponse, - PutAgentReassignRequest, - PutAgentReassignResponse, + PostAgentReassignRequest, + PostAgentReassignResponse, PostBulkAgentReassignRequest, PostBulkAgentReassignResponse, PostNewAgentActionResponse, diff --git a/x-pack/plugins/fleet/server/routes/agent/handlers.ts b/x-pack/plugins/fleet/server/routes/agent/handlers.ts index 24dd0d355411d..b001b27d15b27 100644 --- a/x-pack/plugins/fleet/server/routes/agent/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/agent/handlers.ts @@ -29,6 +29,7 @@ import type { GetAvailableVersionsResponse, GetActionStatusResponse, GetAgentUploadsResponse, + PostAgentReassignResponse, } from '../../../common/types'; import type { GetAgentsRequestSchema, @@ -38,7 +39,8 @@ import type { DeleteAgentRequestSchema, GetAgentStatusRequestSchema, GetAgentDataRequestSchema, - PutAgentReassignRequestSchema, + PutAgentReassignRequestSchemaDeprecated, + PostAgentReassignRequestSchema, PostBulkAgentReassignRequestSchema, PostBulkUpdateAgentTagsRequestSchema, GetActionStatusRequestSchema, @@ -234,10 +236,10 @@ export const getAgentTagsHandler: RequestHandler< } }; -export const putAgentsReassignHandler: RequestHandler< - TypeOf, +export const putAgentsReassignHandlerDeprecated: RequestHandler< + TypeOf, undefined, - TypeOf + TypeOf > = async (context, request, response) => { const coreContext = await context.core; const soClient = coreContext.savedObjects.client; @@ -257,6 +259,29 @@ export const putAgentsReassignHandler: RequestHandler< } }; +export const postAgentsReassignHandler: RequestHandler< + TypeOf, + undefined, + TypeOf +> = async (context, request, response) => { + const coreContext = await context.core; + const soClient = coreContext.savedObjects.client; + const esClient = coreContext.elasticsearch.client.asInternalUser; + try { + await AgentService.reassignAgent( + soClient, + esClient, + request.params.agentId, + request.body.policy_id + ); + + const body: PostAgentReassignResponse = {}; + return response.ok({ body }); + } catch (error) { + return defaultFleetErrorHandler({ error, response }); + } +}; + export const postBulkAgentsReassignHandler: RequestHandler< undefined, undefined, diff --git a/x-pack/plugins/fleet/server/routes/agent/index.ts b/x-pack/plugins/fleet/server/routes/agent/index.ts index d7eb3657cbfd6..9e5204e64ac26 100644 --- a/x-pack/plugins/fleet/server/routes/agent/index.ts +++ b/x-pack/plugins/fleet/server/routes/agent/index.ts @@ -21,7 +21,8 @@ import { GetAgentStatusRequestSchema, GetAgentDataRequestSchema, PostNewAgentActionRequestSchema, - PutAgentReassignRequestSchema, + PutAgentReassignRequestSchemaDeprecated, + PostAgentReassignRequestSchema, PostBulkAgentReassignRequestSchema, PostAgentUpgradeRequestSchema, PostBulkAgentUpgradeRequestSchema, @@ -46,7 +47,7 @@ import { updateAgentHandler, deleteAgentHandler, getAgentStatusForAgentPolicyHandler, - putAgentsReassignHandler, + putAgentsReassignHandlerDeprecated, postBulkAgentsReassignHandler, getAgentDataHandler, bulkUpdateAgentTagsHandler, @@ -54,6 +55,7 @@ import { getActionStatusHandler, getAgentUploadsHandler, getAgentUploadFileHandler, + postAgentsReassignHandler, } from './handlers'; import { postNewAgentActionHandlerBuilder, @@ -178,15 +180,27 @@ export const registerAPIRoutes = (router: FleetAuthzRouter, config: FleetConfigT postAgentUnenrollHandler ); + // mark as deprecated router.put( { path: AGENT_API_ROUTES.REASSIGN_PATTERN, - validate: PutAgentReassignRequestSchema, + validate: PutAgentReassignRequestSchemaDeprecated, fleetAuthz: { fleet: { all: true }, }, }, - putAgentsReassignHandler + putAgentsReassignHandlerDeprecated + ); + + router.post( + { + path: AGENT_API_ROUTES.REASSIGN_PATTERN, + validate: PostAgentReassignRequestSchema, + fleetAuthz: { + fleet: { all: true }, + }, + }, + postAgentsReassignHandler ); router.post( diff --git a/x-pack/plugins/fleet/server/types/rest_spec/agent.ts b/x-pack/plugins/fleet/server/types/rest_spec/agent.ts index 92b0f098ae19d..598ea0fa67fe1 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/agent.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/agent.ts @@ -120,7 +120,16 @@ export const PostBulkAgentUpgradeRequestSchema = { }), }; -export const PutAgentReassignRequestSchema = { +export const PutAgentReassignRequestSchemaDeprecated = { + params: schema.object({ + agentId: schema.string(), + }), + body: schema.object({ + policy_id: schema.string(), + }), +}; + +export const PostAgentReassignRequestSchema = { params: schema.object({ agentId: schema.string(), }), diff --git a/x-pack/test/fleet_api_integration/apis/agents/reassign.ts b/x-pack/test/fleet_api_integration/apis/agents/reassign.ts index 2dd546511dd9a..571a0fee11f54 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/reassign.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/reassign.ts @@ -37,7 +37,7 @@ export default function (providerContext: FtrProviderContext) { describe('reassign single agent', () => { it('should allow to reassign single agent', async () => { await supertest - .put(`/api/fleet/agents/agent1/reassign`) + .post(`/api/fleet/agents/agent1/reassign`) .set('kbn-xsrf', 'xxx') .send({ policy_id: 'policy2', @@ -49,7 +49,7 @@ export default function (providerContext: FtrProviderContext) { it('should throw an error for invalid policy id for single reassign', async () => { await supertest - .put(`/api/fleet/agents/agent1/reassign`) + .post(`/api/fleet/agents/agent1/reassign`) .set('kbn-xsrf', 'xxx') .send({ policy_id: 'INVALID_ID', @@ -61,7 +61,7 @@ export default function (providerContext: FtrProviderContext) { // policy2 is not hosted // reassign succeeds await supertest - .put(`/api/fleet/agents/agent1/reassign`) + .post(`/api/fleet/agents/agent1/reassign`) .set('kbn-xsrf', 'xxx') .send({ policy_id: 'policy2', @@ -79,7 +79,7 @@ export default function (providerContext: FtrProviderContext) { // reassign fails await supertest - .put(`/api/fleet/agents/agent1/reassign`) + .post(`/api/fleet/agents/agent1/reassign`) .set('kbn-xsrf', 'xxx') .send({ policy_id: 'policy2', From b54b70b829416a67413580f7c8eec5aad9cb9faf Mon Sep 17 00:00:00 2001 From: Yngrid Coello Date: Mon, 27 Feb 2023 17:56:09 +0100 Subject: [PATCH 011/131] [APM] Prevent infinite loading state in Service overview and Transactions overview (#150337) ## Summary This closes a bug when we have no `transactionType` defined. When we have this case any of the requests that populates our tables and/or charts are fired resulting in a no status update from our `useFetcher` and ultimately a no change in the state of our charts/tables. ### Changes - `NoTransactionsPrompt` component was added. - Mentioned component is being used in service overview and transactions overview #### Before changes https://user-images.githubusercontent.com/1313018/217004253-4080a722-8f30-4143-9658-feeaf545d1ce.mov #### After this changes https://user-images.githubusercontent.com/1313018/217240199-5f143e32-89f3-4a03-ab15-f3af99d1aca2.mov relates to #145715 --- .../service_overview/instances_table.cy.ts | 2 +- .../components/app/service_overview/index.tsx | 22 +++++++++---------- .../service_overview.stories.tsx | 5 +++++ ...ice_overview_instances_chart_and_table.tsx | 13 +++++++---- .../service_overview_throughput_chart.tsx | 14 ++++++++---- .../app/transaction_overview/index.tsx | 2 +- .../transaction_overview.test.tsx | 5 ++++- .../analyze_data_button.stories.tsx | 1 + .../failed_transaction_rate_chart/index.tsx | 14 ++++++++---- .../components/shared/charts/helper/helper.ts | 1 + .../latency_chart/latency_chart.stories.tsx | 1 + .../use_transaction_breakdown.ts | 10 +++++++-- .../index.tsx | 14 ++++++++---- .../shared/search_bar/search_bar.test.tsx | 5 ++++- .../shared/transactions_table/index.tsx | 15 +++++-------- .../apm_service/apm_service_context.tsx | 14 +++++++----- .../use_service_transaction_types_fetcher.tsx | 4 ++-- .../use_transaction_latency_chart_fetcher.ts | 16 +++++++++----- 18 files changed, 104 insertions(+), 54 deletions(-) diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/instances_table.cy.ts b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/instances_table.cy.ts index 578b116a10592..bda4e78f56c48 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/instances_table.cy.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/e2e/read_only_user/service_overview/instances_table.cy.ts @@ -24,7 +24,7 @@ const serviceRumOverviewHref = url.format({ const testServiveHref = url.format({ pathname: '/app/apm/services/test-service/overview', - query: { rangeFrom: start, rangeTo: end }, + query: { rangeFrom: start, rangeTo: end, transactionType: 'type' }, }); const serviceNodeName = 'opbeans-java-prod-1'; diff --git a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx index 9c7a52dc5859d..3e2d178357a80 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/index.tsx @@ -5,37 +5,37 @@ * 2.0. */ -import React from 'react'; import { i18n } from '@kbn/i18n'; +import React from 'react'; import { - EuiFlexGroupProps, EuiFlexGroup, + EuiFlexGroupProps, EuiFlexItem, EuiLink, EuiPanel, } from '@elastic/eui'; +import { + isRumAgentName, + isServerlessAgent, +} from '../../../../common/agent_name'; import { AnnotationsContextProvider } from '../../../context/annotations/annotations_context'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context'; -import { useBreakpoints } from '../../../hooks/use_breakpoints'; import { useApmParams } from '../../../hooks/use_apm_params'; -import { useTimeRange } from '../../../hooks/use_time_range'; import { useApmRouter } from '../../../hooks/use_apm_router'; +import { useBreakpoints } from '../../../hooks/use_breakpoints'; +import { useTimeRange } from '../../../hooks/use_time_range'; +import { AggregatedTransactionsBadge } from '../../shared/aggregated_transactions_badge'; +import { FailedTransactionRateChart } from '../../shared/charts/failed_transaction_rate_chart'; import { LatencyChart } from '../../shared/charts/latency_chart'; import { TransactionBreakdownChart } from '../../shared/charts/transaction_breakdown_chart'; import { TransactionColdstartRateChart } from '../../shared/charts/transaction_coldstart_rate_chart'; -import { FailedTransactionRateChart } from '../../shared/charts/failed_transaction_rate_chart'; +import { TransactionsTable } from '../../shared/transactions_table'; import { ServiceOverviewDependenciesTable } from './service_overview_dependencies_table'; import { ServiceOverviewErrorsTable } from './service_overview_errors_table'; import { ServiceOverviewInstancesChartAndTable } from './service_overview_instances_chart_and_table'; import { ServiceOverviewThroughputChart } from './service_overview_throughput_chart'; -import { TransactionsTable } from '../../shared/transactions_table'; -import { AggregatedTransactionsBadge } from '../../shared/aggregated_transactions_badge'; -import { - isRumAgentName, - isServerlessAgent, -} from '../../../../common/agent_name'; /** * The height a chart should be if it's next to a table with 5 rows and a title. * Add the height of the pagination row. diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview.stories.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview.stories.tsx index e269f198b5954..f8b5dc3e0b992 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview.stories.tsx @@ -8,6 +8,7 @@ import type { CoreStart } from '@kbn/core/public'; import { Meta, Story } from '@storybook/react'; import React from 'react'; +import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { ServiceOverview } from '.'; import type { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context'; import { MockApmPluginStorybook } from '../../../context/apm_plugin/mock_apm_plugin_storybook'; @@ -19,6 +20,8 @@ const stories: Meta<{}> = { decorators: [ (StoryComponent) => { const serviceName = 'testServiceName'; + const transactionType = 'type'; + const transactionTypeStatus = FETCH_STATUS.SUCCESS; const mockCore = { http: { get: (endpoint: string) => { @@ -37,6 +40,8 @@ const stories: Meta<{}> = { } as unknown as CoreStart; const serviceContextValue = { serviceName, + transactionType, + transactionTypeStatus, } as unknown as APMServiceContextValue; return ( diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx index 13bd5324f6444..ab6d66ab2130d 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_chart_and_table.tsx @@ -67,7 +67,7 @@ export function ServiceOverviewInstancesChartAndTable({ chartHeight, serviceName, }: ServiceOverviewInstancesChartAndTableProps) { - const { transactionType } = useApmServiceContext(); + const { transactionType, transactionTypeStatus } = useApmServiceContext(); const [tableOptions, setTableOptions] = useState({ pageIndex: 0, sort: DEFAULT_SORT, @@ -95,6 +95,10 @@ export function ServiceOverviewInstancesChartAndTable({ status: mainStatsStatus, } = useFetcher( (callApmApi) => { + if (!transactionType && transactionTypeStatus === FETCH_STATUS.SUCCESS) { + return Promise.resolve(INITIAL_STATE_MAIN_STATS); + } + if (!start || !end || !transactionType || !latencyAggregationType) { return; } @@ -125,9 +129,9 @@ export function ServiceOverviewInstancesChartAndTable({ return { // Everytime the main statistics is refetched, updates the requestId making the detailed API to be refetched. requestId: uuidv4(), - currentPeriodItems: response.currentPeriod, - currentPeriodItemsCount: response.currentPeriod.length, - previousPeriodItems: response.previousPeriod, + currentPeriodItems: response?.currentPeriod ?? [], + currentPeriodItemsCount: response?.currentPeriod.length, + previousPeriodItems: response?.previousPeriod, }; }); }, @@ -140,6 +144,7 @@ export function ServiceOverviewInstancesChartAndTable({ end, serviceName, transactionType, + transactionTypeStatus, pageIndex, field, direction, diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx index fcc4f3a97cd5c..30df64a9b4d0c 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx @@ -21,7 +21,7 @@ import { asExactTransactionRate } from '../../../../common/utils/formatters'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; import { useEnvironmentsContext } from '../../../context/environments_context/use_environments_context'; import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; -import { useFetcher } from '../../../hooks/use_fetcher'; +import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; import { usePreferredServiceAnomalyTimeseries } from '../../../hooks/use_preferred_service_anomaly_timeseries'; import { useTimeRange } from '../../../hooks/use_time_range'; import { TimeseriesChartWithContext } from '../../shared/charts/timeseries_chart_with_context'; @@ -60,12 +60,17 @@ export function ServiceOverviewThroughputChart({ const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const { transactionType, serviceName } = useApmServiceContext(); + const { transactionType, serviceName, transactionTypeStatus } = + useApmServiceContext(); const comparisonChartTheme = getComparisonChartTheme(); const { data = INITIAL_STATE, status } = useFetcher( (callApmApi) => { + if (!transactionType && transactionTypeStatus === FETCH_STATUS.SUCCESS) { + return Promise.resolve(INITIAL_STATE); + } + if (serviceName && transactionType && start && end) { return callApmApi( 'GET /internal/apm/services/{serviceName}/throughput', @@ -98,6 +103,7 @@ export function ServiceOverviewThroughputChart({ start, end, transactionType, + transactionTypeStatus, offset, transactionName, comparisonEnabled, @@ -111,7 +117,7 @@ export function ServiceOverviewThroughputChart({ const previousPeriodLabel = usePreviousPeriodLabel(); const timeseries = [ { - data: data.currentPeriod, + data: data?.currentPeriod ?? [], type: 'linemark', color: currentPeriodColor, title: i18n.translate('xpack.apm.serviceOverview.throughtputChartTitle', { @@ -121,7 +127,7 @@ export function ServiceOverviewThroughputChart({ ...(comparisonEnabled ? [ { - data: data.previousPeriod, + data: data?.previousPeriod ?? [], type: 'area', color: previousPeriodColor, title: previousPeriodLabel, diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx index 21a51babd04b3..21b830fb314af 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_overview/index.tsx @@ -8,6 +8,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer } from '@elastic/eui'; import React from 'react'; import { useHistory } from 'react-router-dom'; +import { isServerlessAgent } from '../../../../common/agent_name'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; import { useApmParams } from '../../../hooks/use_apm_params'; import { useTimeRange } from '../../../hooks/use_time_range'; @@ -15,7 +16,6 @@ import { AggregatedTransactionsBadge } from '../../shared/aggregated_transaction import { TransactionCharts } from '../../shared/charts/transaction_charts'; import { replace } from '../../shared/links/url_helpers'; import { TransactionsTable } from '../../shared/transactions_table'; -import { isServerlessAgent } from '../../../../common/agent_name'; export function TransactionOverview() { const { diff --git a/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx b/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx index 5b3118e527fa4..f27aab3724ab5 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_overview/transaction_overview.test.tsx @@ -49,7 +49,10 @@ function setup({ // mock transaction types jest .spyOn(useServiceTransactionTypesHook, 'useServiceTransactionTypesFetcher') - .mockReturnValue(serviceTransactionTypes); + .mockReturnValue({ + transactionTypes: serviceTransactionTypes, + status: useFetcherHook.FETCH_STATUS.SUCCESS, + }); // mock agent jest diff --git a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx index 57a0e789267b1..a08e575dcd752 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/apm_service_template/analyze_data_button.stories.tsx @@ -49,6 +49,7 @@ export default { { + if (!transactionType && transactionTypeStatus === FETCH_STATUS.SUCCESS) { + return Promise.resolve(INITIAL_STATE); + } + if (transactionType && serviceName && start && end) { return callApmApi( 'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate', @@ -115,6 +120,7 @@ export function FailedTransactionRateChart({ start, end, transactionType, + transactionTypeStatus, transactionName, offset, comparisonEnabled, @@ -128,7 +134,7 @@ export function FailedTransactionRateChart({ const previousPeriodLabel = usePreviousPeriodLabel(); const timeseries = [ { - data: data.currentPeriod.timeseries, + data: data?.currentPeriod?.timeseries ?? [], type: 'linemark', color: currentPeriodColor, title: i18n.translate('xpack.apm.errorRate.chart.errorRate', { @@ -138,7 +144,7 @@ export function FailedTransactionRateChart({ ...(comparisonEnabled ? [ { - data: data.previousPeriod.timeseries, + data: data?.previousPeriod?.timeseries ?? [], type: 'area', color: previousPeriodColor, title: previousPeriodLabel, diff --git a/x-pack/plugins/apm/public/components/shared/charts/helper/helper.ts b/x-pack/plugins/apm/public/components/shared/charts/helper/helper.ts index d203bd8cfe022..6558c6fd03af6 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/helper/helper.ts +++ b/x-pack/plugins/apm/public/components/shared/charts/helper/helper.ts @@ -39,6 +39,7 @@ export const onBrushEnd = ({ export function isTimeseriesEmpty(timeseries?: Array>) { return ( !timeseries || + timeseries.length === 0 || timeseries .map((serie) => serie.data) .flat() diff --git a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx index 23ec2140f5be7..8f084b17381ec 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx @@ -84,6 +84,7 @@ const stories: Meta = { value={{ serviceName, transactionType, + transactionTypeStatus: FETCH_STATUS.SUCCESS, transactionTypes: [], fallbackToTransactions: false, serviceAgentStatus: FETCH_STATUS.SUCCESS, diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts b/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts index 742bef523a143..538e7bb26fef3 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_breakdown_chart/use_transaction_breakdown.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { useFetcher } from '../../../../hooks/use_fetcher'; +import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; import { useLegacyUrlParams } from '../../../../context/url_params_context/use_url_params'; import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; import { useAnyOfApmParams } from '../../../../hooks/use_apm_params'; @@ -31,7 +31,8 @@ export function useTransactionBreakdown({ const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const { transactionType, serviceName } = useApmServiceContext(); + const { transactionType, serviceName, transactionTypeStatus } = + useApmServiceContext(); const { data = { timeseries: undefined }, @@ -39,6 +40,10 @@ export function useTransactionBreakdown({ status, } = useFetcher( (callApmApi) => { + if (!transactionType && transactionTypeStatus === FETCH_STATUS.SUCCESS) { + return Promise.resolve({ timeseries: undefined }); + } + if (serviceName && start && end && transactionType) { return callApmApi( 'GET /internal/apm/services/{serviceName}/transaction/charts/breakdown', @@ -65,6 +70,7 @@ export function useTransactionBreakdown({ start, end, transactionType, + transactionTypeStatus, transactionName, ] ); diff --git a/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx index 3dfc22a1c2809..b236f92d0f892 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/transaction_coldstart_rate_chart/index.tsx @@ -18,7 +18,7 @@ import { usePreviousPeriodLabel } from '../../../../hooks/use_previous_period_te import { isTimeComparison } from '../../time_comparison/get_comparison_options'; import { APIReturnType } from '../../../../services/rest/create_call_apm_api'; import { asPercent } from '../../../../../common/utils/formatters'; -import { useFetcher } from '../../../../hooks/use_fetcher'; +import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; import { useTheme } from '../../../../hooks/use_theme'; import { TimeseriesChartWithContext } from '../timeseries_chart_with_context'; import { useApmServiceContext } from '../../../../context/apm_service/use_apm_service_context'; @@ -71,7 +71,8 @@ export function TransactionColdstartRateChart({ const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - const { serviceName, transactionType } = useApmServiceContext(); + const { serviceName, transactionType, transactionTypeStatus } = + useApmServiceContext(); const comparisonChartTheme = getComparisonChartTheme(); const endpoint = transactionName @@ -80,6 +81,10 @@ export function TransactionColdstartRateChart({ const { data = INITIAL_STATE, status } = useFetcher( (callApmApi) => { + if (!transactionType && transactionTypeStatus === FETCH_STATUS.SUCCESS) { + return Promise.resolve(INITIAL_STATE); + } + if (transactionType && serviceName && start && end) { return callApmApi(endpoint, { params: { @@ -109,6 +114,7 @@ export function TransactionColdstartRateChart({ start, end, transactionType, + transactionTypeStatus, transactionName, offset, endpoint, @@ -119,7 +125,7 @@ export function TransactionColdstartRateChart({ const timeseries = [ { - data: data.currentPeriod.transactionColdstartRate, + data: data?.currentPeriod?.transactionColdstartRate ?? [], type: 'linemark', color: theme.eui.euiColorVis5, title: i18n.translate('xpack.apm.coldstartRate.chart.coldstartRate', { @@ -129,7 +135,7 @@ export function TransactionColdstartRateChart({ ...(comparisonEnabled ? [ { - data: data.previousPeriod.transactionColdstartRate, + data: data?.previousPeriod?.transactionColdstartRate ?? [], type: 'area', color: theme.eui.euiColorMediumShade, title: previousPeriodLabel, diff --git a/x-pack/plugins/apm/public/components/shared/search_bar/search_bar.test.tsx b/x-pack/plugins/apm/public/components/shared/search_bar/search_bar.test.tsx index f07fc415eaf7d..27eecaf573bf6 100644 --- a/x-pack/plugins/apm/public/components/shared/search_bar/search_bar.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/search_bar/search_bar.test.tsx @@ -44,7 +44,10 @@ function setup({ // mock transaction types jest .spyOn(useServiceTransactionTypesHook, 'useServiceTransactionTypesFetcher') - .mockReturnValue(serviceTransactionTypes); + .mockReturnValue({ + transactionTypes: serviceTransactionTypes, + status: useFetcherHook.FETCH_STATUS.SUCCESS, + }); // mock transaction types jest diff --git a/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx b/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx index 3c2520e9b219e..fc97216c4ae2f 100644 --- a/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/transactions_table/index.tsx @@ -132,7 +132,7 @@ export function TransactionsTable({ const { data = INITIAL_STATE, status } = useFetcher( (callApmApi) => { if (!start || !end || !latencyAggregationType || !transactionType) { - return; + return Promise.resolve(undefined); } return callApmApi( 'GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics', @@ -260,10 +260,6 @@ export function TransactionsTable({ transactionOverflowCount, }); - const isLoading = status === FETCH_STATUS.LOADING; - const isNotInitiated = status === FETCH_STATUS.NOT_INITIATED; - const hasFailed = status === FETCH_STATUS.FAILURE; - const pagination = useMemo( () => ({ pageIndex: index, @@ -338,13 +334,14 @@ export function TransactionsTable({ ({ serviceName: '', + transactionTypeStatus: FETCH_STATUS.NOT_INITIATED, transactionTypes: [], fallbackToTransactions: false, serviceAgentStatus: FETCH_STATUS.NOT_INITIATED, @@ -65,11 +67,12 @@ export function ApmServiceContextProvider({ end, }); - const transactionTypes = useServiceTransactionTypesFetcher({ - serviceName, - start, - end, - }); + const { transactionTypes, status: transactionTypeStatus } = + useServiceTransactionTypesFetcher({ + serviceName, + start, + end, + }); const currentTransactionType = getOrRedirectToTransactionType({ transactionType: query.transactionType, @@ -89,6 +92,7 @@ export function ApmServiceContextProvider({ agentName, serverlessType, transactionType: currentTransactionType, + transactionTypeStatus, transactionTypes, runtimeName, fallbackToTransactions, diff --git a/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx b/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx index 96a4141e824cc..fa00f7f45e743 100644 --- a/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx +++ b/x-pack/plugins/apm/public/context/apm_service/use_service_transaction_types_fetcher.tsx @@ -18,7 +18,7 @@ export function useServiceTransactionTypesFetcher({ start?: string; end?: string; }) { - const { data = INITIAL_DATA } = useFetcher( + const { data = INITIAL_DATA, status } = useFetcher( (callApmApi) => { if (serviceName && start && end) { return callApmApi( @@ -35,5 +35,5 @@ export function useServiceTransactionTypesFetcher({ [serviceName, start, end] ); - return data.transactionTypes; + return { transactionTypes: data.transactionTypes, status }; } diff --git a/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts b/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts index 32b0c06e99198..d3640afe9f9ea 100644 --- a/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts +++ b/x-pack/plugins/apm/public/hooks/use_transaction_latency_chart_fetcher.ts @@ -6,14 +6,14 @@ */ import { useMemo } from 'react'; -import { usePreviousPeriodLabel } from './use_previous_period_text'; import { isTimeComparison } from '../components/shared/time_comparison/get_comparison_options'; -import { useFetcher } from './use_fetcher'; -import { useLegacyUrlParams } from '../context/url_params_context/use_url_params'; import { useApmServiceContext } from '../context/apm_service/use_apm_service_context'; +import { useLegacyUrlParams } from '../context/url_params_context/use_url_params'; import { getLatencyChartSelector } from '../selectors/latency_chart_selectors'; -import { useTimeRange } from './use_time_range'; import { useAnyOfApmParams } from './use_apm_params'; +import { FETCH_STATUS, useFetcher } from './use_fetcher'; +import { usePreviousPeriodLabel } from './use_previous_period_text'; +import { useTimeRange } from './use_time_range'; export function useTransactionLatencyChartsFetcher({ kuery, @@ -22,7 +22,8 @@ export function useTransactionLatencyChartsFetcher({ kuery: string; environment: string; }) { - const { transactionType, serviceName } = useApmServiceContext(); + const { transactionType, serviceName, transactionTypeStatus } = + useApmServiceContext(); const { urlParams: { transactionName, latencyAggregationType }, } = useLegacyUrlParams(); @@ -38,6 +39,10 @@ export function useTransactionLatencyChartsFetcher({ const { data, error, status } = useFetcher( (callApmApi) => { + if (!transactionType && transactionTypeStatus === FETCH_STATUS.SUCCESS) { + return Promise.resolve(undefined); + } + if ( serviceName && start && @@ -76,6 +81,7 @@ export function useTransactionLatencyChartsFetcher({ end, transactionName, transactionType, + transactionTypeStatus, latencyAggregationType, offset, comparisonEnabled, From 539cbc52b577e4c895f9dee2ed6f55eb076122bb Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Mon, 27 Feb 2023 12:18:39 -0500 Subject: [PATCH 012/131] feat(slo): show active alerts badge (#151628) --- .../e2e/journeys/step_duration.journey.ts | 5 +- .../burn_rate_rule_editor.stories.tsx | 3 +- .../slo_selector.stories.tsx | 2 + .../__storybook_mocks__/use_capabilities.ts | 13 ++ .../use_fetch_active_alerts.ts | 27 ++++ .../use_fetch_historical_summary.ts | 1 - .../hooks/slo/use_fetch_active_alerts.ts | 115 ++++++++++++++++++ .../hooks/slo/use_fetch_apm_suggestions.ts | 5 +- .../hooks/slo/use_fetch_historical_summary.ts | 51 +++----- .../public/hooks/slo/use_fetch_slo_list.ts | 4 +- .../slos/components/badges/slo_badges.tsx | 52 +++++++- .../components/badges/slo_status_badge.tsx | 11 +- .../pages/slos/components/slo_list_item.tsx | 5 +- .../pages/slos/components/slo_list_items.tsx | 6 + .../server/services/slo/update_slo.ts | 3 +- 15 files changed, 250 insertions(+), 53 deletions(-) create mode 100644 x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_capabilities.ts create mode 100644 x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_active_alerts.ts create mode 100644 x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts diff --git a/x-pack/plugins/observability/e2e/journeys/step_duration.journey.ts b/x-pack/plugins/observability/e2e/journeys/step_duration.journey.ts index 1e24fbb120f53..13cde8e940e13 100644 --- a/x-pack/plugins/observability/e2e/journeys/step_duration.journey.ts +++ b/x-pack/plugins/observability/e2e/journeys/step_duration.journey.ts @@ -56,10 +56,7 @@ journey('Exploratory view', async ({ page, params }) => { }); step('Open exploratory view with monitor duration', async () => { - await Promise.all([ - page.waitForNavigation(TIMEOUT_60_SEC), - page.click('text=Explore data', TIMEOUT_60_SEC), - ]); + await page.waitForNavigation(TIMEOUT_60_SEC); await waitForLoadingToFinish({ page }); await page.click('text=browser', TIMEOUT_60_SEC); diff --git a/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/burn_rate_rule_editor.stories.tsx b/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/burn_rate_rule_editor.stories.tsx index 95ec0d73aa6ae..0c53fae9af248 100644 --- a/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/burn_rate_rule_editor.stories.tsx +++ b/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/burn_rate_rule_editor.stories.tsx @@ -8,13 +8,14 @@ import React from 'react'; import { ComponentStory } from '@storybook/react'; +import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; import { BurnRateRuleParams } from '../../../typings'; import { BurnRateRuleEditor as Component } from './burn_rate_rule_editor'; export default { component: Component, title: 'app/SLO/BurnRateRule', - argTypes: {}, + decorators: [KibanaReactStorybookDecorator], }; const Template: ComponentStory = () => ( diff --git a/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/slo_selector.stories.tsx b/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/slo_selector.stories.tsx index fd06b1fef6ab5..1debffc408049 100644 --- a/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/slo_selector.stories.tsx +++ b/x-pack/plugins/observability/public/components/app/burn_rate_rule_editor/slo_selector.stories.tsx @@ -9,11 +9,13 @@ import React from 'react'; import { ComponentStory } from '@storybook/react'; import { SLOResponse } from '@kbn/slo-schema'; +import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; import { SloSelector as Component } from './slo_selector'; export default { component: Component, title: 'app/SLO/BurnRateRule', + decorators: [KibanaReactStorybookDecorator], }; const Template: ComponentStory = () => ( diff --git a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_capabilities.ts b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_capabilities.ts new file mode 100644 index 0000000000000..f34d7a4a7070b --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_capabilities.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export function useCapabilities() { + return { + hasReadCapabilities: true, + hasWriteCapabilities: true, + }; +} diff --git a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_active_alerts.ts b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_active_alerts.ts new file mode 100644 index 0000000000000..f493eadac3806 --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_active_alerts.ts @@ -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 { UseFetchActiveAlerts } from '../use_fetch_active_alerts'; + +export const useFetchActiveAlerts = ({ + sloIds = [], +}: { + sloIds: string[]; +}): UseFetchActiveAlerts => { + return { + isLoading: false, + isSuccess: false, + isError: false, + data: sloIds.reduce( + (acc, sloId, index) => ({ + ...acc, + ...(index % 2 === 0 && { [sloId]: { count: 2, ruleIds: ['rule-1', 'rule-2'] } }), + }), + {} + ), + }; +}; diff --git a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts index f869e6da47c64..fe10d84c4f428 100644 --- a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts +++ b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts @@ -23,6 +23,5 @@ export const useFetchHistoricalSummary = ({ isSuccess: false, isError: false, sloHistoricalSummaryResponse: data, - refetch: function () {} as UseFetchHistoricalSummaryResponse['refetch'], }; }; diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts new file mode 100644 index 0000000000000..4e90e51060df0 --- /dev/null +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useQuery } from '@tanstack/react-query'; +import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; + +import { useKibana } from '../../utils/kibana_react'; + +type SloId = string; + +interface Params { + sloIds: SloId[]; +} + +export interface ActiveAlerts { + count: number; + ruleIds: string[]; +} + +type ActiveAlertsMap = Record; + +export interface UseFetchActiveAlerts { + data: ActiveAlertsMap; + isLoading: boolean; + isSuccess: boolean; + isError: boolean; +} + +interface FindApiResponse { + aggregations: { + perSloId: { + buckets: Array<{ + key: string; + doc_count: number; + perRuleId: { buckets: Array<{ key: string; doc_count: number }> }; + }>; + }; + }; +} + +const EMPTY_ACTIVE_ALERTS_MAP = {}; + +export function useFetchActiveAlerts({ sloIds = [] }: Params): UseFetchActiveAlerts { + const { http } = useKibana().services; + + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + queryKey: ['fetchActiveAlerts', sloIds], + queryFn: async ({ signal }) => { + try { + const response = await http.post(`${BASE_RAC_ALERTS_API_PATH}/find`, { + body: JSON.stringify({ + feature_ids: ['slo'], + size: 0, + query: { + bool: { + filter: [ + { + term: { + 'kibana.alert.rule.rule_type_id': 'slo.rules.burnRate', + }, + }, + { + term: { + 'kibana.alert.status': 'active', + }, + }, + ], + }, + }, + aggs: { + perSloId: { + terms: { + field: 'kibana.alert.rule.parameters.sloId', + }, + aggs: { + perRuleId: { + terms: { + field: 'kibana.alert.rule.uuid', + }, + }, + }, + }, + }, + }), + signal, + }); + + return response.aggregations.perSloId.buckets.reduce( + (acc, bucket) => ({ + ...acc, + [bucket.key]: { + count: bucket.doc_count ?? 0, + ruleIds: bucket.perRuleId.buckets.map((rule) => rule.key), + } as ActiveAlerts, + }), + {} + ); + } catch (error) { + // ignore error + } + }, + refetchOnWindowFocus: false, + }); + + return { + data: isInitialLoading ? EMPTY_ACTIVE_ALERTS_MAP : data ?? EMPTY_ACTIVE_ALERTS_MAP, + isLoading: isInitialLoading || isLoading || isRefetching, + isSuccess, + isError, + }; +} diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts index cc7bdb1193d63..63ed913902ee8 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_apm_suggestions.ts @@ -11,6 +11,7 @@ import moment from 'moment'; import { useKibana } from '../../utils/kibana_react'; export type Suggestion = string; + export interface UseFetchApmSuggestions { suggestions: Suggestion[]; isLoading: boolean; @@ -28,7 +29,7 @@ interface ApiResponse { terms: string[]; } -const EMPTY_RESPONSE: ApiResponse = { terms: [] }; +const NO_SUGGESTIONS: Suggestion[] = []; export function useFetchApmSuggestions({ fieldName, @@ -61,7 +62,7 @@ export function useFetchApmSuggestions({ }); return { - suggestions: isInitialLoading ? EMPTY_RESPONSE.terms : data ?? EMPTY_RESPONSE.terms, + suggestions: isInitialLoading ? NO_SUGGESTIONS : data ?? NO_SUGGESTIONS, isLoading: isInitialLoading || isLoading || isRefetching, isSuccess, isError, diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts index e1bca23188295..2037c97df52c1 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts @@ -5,12 +5,7 @@ * 2.0. */ -import { - QueryObserverResult, - RefetchOptions, - RefetchQueryFilters, - useQuery, -} from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import { FetchHistoricalSummaryResponse } from '@kbn/slo-schema'; import { useKibana } from '../../utils/kibana_react'; @@ -22,9 +17,6 @@ export interface UseFetchHistoricalSummaryResponse { isLoading: boolean; isSuccess: boolean; isError: boolean; - refetch: ( - options?: (RefetchOptions & RefetchQueryFilters) | undefined - ) => Promise>; } export interface Params { @@ -36,33 +28,30 @@ export function useFetchHistoricalSummary({ }: Params): UseFetchHistoricalSummaryResponse { const { http } = useKibana().services; - const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( - { - queryKey: ['fetchHistoricalSummary', sloIds], - queryFn: async ({ signal }) => { - try { - const response = await http.post( - '/internal/observability/slos/_historical_summary', - { - body: JSON.stringify({ sloIds }), - signal, - } - ); - - return response; - } catch (error) { - // ignore error for retrieving slos - } - }, - refetchOnWindowFocus: false, - } - ); + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + queryKey: ['fetchHistoricalSummary', sloIds], + queryFn: async ({ signal }) => { + try { + const response = await http.post( + '/internal/observability/slos/_historical_summary', + { + body: JSON.stringify({ sloIds }), + signal, + } + ); + + return response; + } catch (error) { + // ignore error + } + }, + refetchOnWindowFocus: false, + }); return { sloHistoricalSummaryResponse: isInitialLoading ? EMPTY_RESPONSE : data ?? EMPTY_RESPONSE, isLoading: isInitialLoading || isLoading || isRefetching, isSuccess, isError, - refetch, }; } diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts index 7864b85181a3f..648efb5481d31 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts @@ -11,8 +11,8 @@ import { RefetchQueryFilters, useQuery, } from '@tanstack/react-query'; - import { FindSLOResponse } from '@kbn/slo-schema'; + import { useKibana } from '../../utils/kibana_react'; interface SLOListParams { @@ -61,7 +61,7 @@ export function useFetchSloList({ return response; } catch (error) { - // ignore error for retrieving slos + // ignore error } }, refetchOnWindowFocus: false, diff --git a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_badges.tsx b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_badges.tsx index 32cdeb785270e..cd4c7d9c2d5d5 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_badges.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_badges.tsx @@ -6,20 +6,38 @@ */ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; +import { i18n } from '@kbn/i18n'; +import { useKibana } from '../../../../utils/kibana_react'; +import { paths } from '../../../../config'; +import { ActiveAlerts } from '../../../../hooks/slo/use_fetch_active_alerts'; import { SloStatusBadge } from './slo_status_badge'; import { SloIndicatorTypeBadge } from './slo_indicator_type_badge'; import { SloTimeWindowBadge } from './slo_time_window_badge'; export interface Props { slo: SLOWithSummaryResponse; + activeAlerts?: ActiveAlerts; } -export function SloBadges({ slo }: Props) { +export function SloBadges({ slo, activeAlerts }: Props) { + const { + application: { navigateToUrl }, + http: { basePath }, + } = useKibana().services; + + const handleClick = () => { + if (activeAlerts) { + navigateToUrl( + `${basePath.prepend(paths.observability.alerts)}?_a=${toAlertsPageQuery(activeAlerts)}` + ); + } + }; + return ( - + @@ -27,6 +45,34 @@ export function SloBadges({ slo }: Props) { + {!!activeAlerts && ( + + + {i18n.translate('xpack.observability.slos.slo.activeAlertsBadge.label', { + defaultMessage: '{count, plural, one {# alert} other {# alerts}}', + values: { count: activeAlerts.count }, + })} + + + )} ); } + +function toAlertsPageQuery(activeAlerts: ActiveAlerts): string { + const kuery = activeAlerts.ruleIds + .map((ruleId) => `kibana.alert.rule.uuid:"${activeAlerts.ruleIds[0]}"`) + .join(' or '); + + const query = `(kuery:'${kuery}',rangeFrom:now-15m,rangeTo:now,status:all)`; + return query; +} diff --git a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_status_badge.tsx b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_status_badge.tsx index a1c89ca857b18..ed69ebae221e5 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/badges/slo_status_badge.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/badges/slo_status_badge.tsx @@ -8,7 +8,6 @@ import React from 'react'; import { EuiBadge, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { euiLightVars } from '@kbn/ui-theme'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; export interface SloStatusProps { @@ -21,7 +20,7 @@ export function SloStatusBadge({ slo }: SloStatusProps) {
{slo.summary.status === 'NO_DATA' && ( - + {i18n.translate('xpack.observability.slos.slo.state.noData', { defaultMessage: 'No data', })} @@ -29,7 +28,7 @@ export function SloStatusBadge({ slo }: SloStatusProps) { )} {slo.summary.status === 'HEALTHY' && ( - + {i18n.translate('xpack.observability.slos.slo.state.healthy', { defaultMessage: 'Healthy', })} @@ -37,7 +36,7 @@ export function SloStatusBadge({ slo }: SloStatusProps) { )} {slo.summary.status === 'DEGRADING' && ( - + {i18n.translate('xpack.observability.slos.slo.state.degrading', { defaultMessage: 'Degrading', })} @@ -45,7 +44,7 @@ export function SloStatusBadge({ slo }: SloStatusProps) { )} {slo.summary.status === 'VIOLATED' && ( - + {i18n.translate('xpack.observability.slos.slo.state.violated', { defaultMessage: 'Violated', })} @@ -56,7 +55,7 @@ export function SloStatusBadge({ slo }: SloStatusProps) { {slo.summary.errorBudget.isEstimated && (
- + {i18n.translate('xpack.observability.slos.slo.state.forecasted', { defaultMessage: 'Forecasted', })} diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx index a56d48698d540..282b82bf41b7e 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx @@ -20,6 +20,7 @@ import { import { i18n } from '@kbn/i18n'; import { HistoricalSummaryResponse, SLOWithSummaryResponse } from '@kbn/slo-schema'; +import { ActiveAlerts } from '../../../hooks/slo/use_fetch_active_alerts'; import { useCapabilities } from '../../../hooks/slo/use_capabilities'; import { useKibana } from '../../../utils/kibana_react'; import { useCloneSlo } from '../../../hooks/slo/use_clone_slo'; @@ -36,12 +37,14 @@ export interface SloListItemProps { slo: SLOWithSummaryResponse; historicalSummary?: HistoricalSummaryResponse[]; historicalSummaryLoading: boolean; + activeAlerts?: ActiveAlerts; } export function SloListItem({ slo, historicalSummary = [], historicalSummaryLoading, + activeAlerts, }: SloListItemProps) { const { application: { navigateToUrl }, @@ -101,7 +104,7 @@ export function SloListItem({ {slo.name} - + diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx index 2e0bb5b267b7a..85ce283c90b18 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; +import { useFetchActiveAlerts } from '../../../hooks/slo/use_fetch_active_alerts'; import { useFetchHistoricalSummary } from '../../../hooks/slo/use_fetch_historical_summary'; import { SloListItem } from './slo_list_item'; import { SloListEmpty } from './slo_list_empty'; @@ -23,6 +24,10 @@ export function SloListItems({ sloList, loading, error }: Props) { const { isLoading: historicalSummaryLoading, sloHistoricalSummaryResponse } = useFetchHistoricalSummary({ sloIds: sloList.map((slo) => slo.id) }); + const { data: activeAlertsBySlo } = useFetchActiveAlerts({ + sloIds: sloList.map((slo) => slo.id), + }); + if (!loading && !error && sloList.length === 0) { return ; } @@ -38,6 +43,7 @@ export function SloListItems({ sloList, loading, error }: Props) { slo={slo} historicalSummary={sloHistoricalSummaryResponse[slo.id]} historicalSummaryLoading={historicalSummaryLoading} + activeAlerts={activeAlertsBySlo[slo.id]} /> ))} diff --git a/x-pack/plugins/observability/server/services/slo/update_slo.ts b/x-pack/plugins/observability/server/services/slo/update_slo.ts index 9b4aa4e7dc213..cf2c0e2e1c89f 100644 --- a/x-pack/plugins/observability/server/services/slo/update_slo.ts +++ b/x-pack/plugins/observability/server/services/slo/update_slo.ts @@ -6,7 +6,6 @@ */ import deepEqual from 'fast-deep-equal'; -import merge from 'lodash/merge'; import { ElasticsearchClient } from '@kbn/core/server'; import { UpdateSLOParams, UpdateSLOResponse, updateSLOResponseSchema } from '@kbn/slo-schema'; @@ -42,7 +41,7 @@ export class UpdateSLO { private updateSLO(originalSlo: SLO, params: UpdateSLOParams) { let hasBreakingChange = false; - const updatedSlo: SLO = merge({}, originalSlo, params, { updatedAt: new Date() }); + const updatedSlo: SLO = Object.assign({}, originalSlo, params, { updatedAt: new Date() }); validateSLO(updatedSlo); if (!deepEqual(originalSlo.indicator, updatedSlo.indicator)) { From a988cd4442918d113199b7a1b0a14a04c82dc960 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Mon, 27 Feb 2023 12:23:35 -0500 Subject: [PATCH 013/131] [Synthetics] fix icmp monitor to not trigger error boundary on edit (#152241) ## Summary Resolves https://github.com/elastic/kibana/issues/152239 Fixes error boundary in ICMP monitor. Before [Add-Monitor-Uptime---Kibana (1).webm](https://user-images.githubusercontent.com/11356435/221615611-12479071-c445-40dc-98fc-5e1268cdd07f.webm) After [Add-Monitor-Uptime---Kibana (2).webm](https://user-images.githubusercontent.com/11356435/221615727-3a5d40e1-b268-44e9-a821-319422f4ad6a.webm) --- .../synthetics_policy_edit_extension_wrapper.tsx | 8 ++++---- .../components/monitor_management/edit_monitor_config.tsx | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx index 8a2671c14cc6c..00d5e8bd7b940 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/fleet_package/synthetics_policy_edit_extension_wrapper.tsx @@ -14,8 +14,8 @@ import type { } from '@kbn/fleet-plugin/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useEditMonitorLocator } from '../../../apps/synthetics/hooks'; -import { PolicyConfig, MonitorFields } from './types'; -import { ConfigKey, DataStream, TLSFields } from './types'; +import type { PolicyConfig, MonitorFields, TLSFields } from './types'; +import { ConfigKey, DataStream } from './types'; import { SyntheticsPolicyEditExtension } from './synthetics_policy_edit_extension'; import { PolicyConfigContextProvider, @@ -80,10 +80,10 @@ export const SyntheticsPolicyEditExtensionWrapper = memo = { diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/edit_monitor_config.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/edit_monitor_config.tsx index 0c487eb1fdc3d..e80a305afa6fa 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/edit_monitor_config.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/edit_monitor_config.tsx @@ -52,8 +52,8 @@ export const EditMonitorConfig = ({ monitor, throttling }: Props) => { [ConfigKey.TLS_VERSION]: monitor[ConfigKey.TLS_VERSION], }; - enableTLS = Boolean(monitor[ConfigKey.METADATA].is_tls_enabled); - enableZipUrlTLS = Boolean(monitor[ConfigKey.METADATA].is_zip_url_tls_enabled); + enableTLS = Boolean(monitor[ConfigKey.METADATA]?.is_tls_enabled); + enableZipUrlTLS = Boolean(monitor[ConfigKey.METADATA]?.is_zip_url_tls_enabled); const formattedDefaultConfig: Partial = { [type]: monitor, From 130d2a7a7c49356dfd92b12078201c5e418db9e0 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Mon, 27 Feb 2023 09:51:15 -0800 Subject: [PATCH 014/131] [DOCS] Add alert summaries to overview (#151817) --- .../alerting-getting-started.asciidoc | 60 ++++------ .../alerting/create-and-manage-rules.asciidoc | 12 +- docs/user/alerting/images/alerts.svg | 63 +++++++++- .../images/rule-concepts-connectors.svg | 1 - .../alerting/images/rule-concepts-summary.svg | 110 +++++++++++++++++- docs/user/alerting/images/what-is-a-rule.svg | 25 +++- .../alerting/images/what-is-an-action.svg | 1 - 7 files changed, 224 insertions(+), 48 deletions(-) delete mode 100644 docs/user/alerting/images/rule-concepts-connectors.svg delete mode 100644 docs/user/alerting/images/what-is-an-action.svg diff --git a/docs/user/alerting/alerting-getting-started.asciidoc b/docs/user/alerting/alerting-getting-started.asciidoc index e169bcfc24869..b7ca2f3c58b55 100644 --- a/docs/user/alerting/alerting-getting-started.asciidoc +++ b/docs/user/alerting/alerting-getting-started.asciidoc @@ -3,7 +3,7 @@ -- -Alerting allows you to define _rules_ to detect complex conditions within different {kib} apps and trigger actions when those conditions are met. Alerting is integrated with {observability-guide}/create-alerts.html[*Observability*], {security-guide}/prebuilt-rules.html[*Security*], <> and {ml-docs}/ml-configuring-alerts.html[*{ml-app}*], can be centrally managed from the <> UI, and provides a set of built-in <> and <> (known as stack rules) for you to use. +Alerting enables you to define _rules_, which detect complex conditions within different {kib} apps and trigger actions when those conditions are met. Alerting is integrated with {observability-guide}/create-alerts.html[*{observability}*], {security-guide}/prebuilt-rules.html[*Security*], <> and {ml-docs}/ml-configuring-alerts.html[*{ml-app}*]. It can be centrally managed from *{stack-manage-app}* and provides a set of built-in <> and <> for you to use. image::images/alerting-overview.png[{rules-ui} UI] @@ -12,15 +12,12 @@ image::images/alerting-overview.png[{rules-ui} UI] To make sure you can access alerting and actions, see the <> section. ============================================== -[float] -== Concepts and terminology - Alerting works by running checks on a schedule to detect conditions defined by a rule. When a condition is met, the rule tracks it as an _alert_ and responds by triggering one or more _actions_. -Actions typically involve interaction with {kib} services or third party integrations. _Connectors_ allow actions to talk to these services and integrations. +Actions typically involve interaction with {kib} services or third party integrations. _Connectors_ enable actions to talk to these services and integrations. This section describes all of these elements and how they operate together. [float] -=== Rules +== Rules A rule specifies a background task that runs on the {kib} server to check for specific conditions. {kib} provides two types of rules: stack rules that are built into {kib} and the rules that are registered by {kib} apps. For more information, refer to <>. @@ -42,7 +39,7 @@ The following sections describe each part of the rule in more detail. [float] [[alerting-concepts-conditions]] -==== Conditions +=== Conditions Under the hood, {kib} rules detect conditions by running a JavaScript function on the {kib} server, which gives it the flexibility to support a wide range of conditions, anything from the results of a simple {es} query to heavy computations involving data from multiple sources or external systems. @@ -55,58 +52,47 @@ See <> for the rules provided by {kib} and how they express their co [float] [[alerting-concepts-scheduling]] -==== Schedule +=== Schedule Rule schedules are defined as an interval between subsequent checks, and can range from a few seconds to months. [IMPORTANT] ============================================== -The intervals of rule checks in {kib} are approximate. Their timing is affected by factors such as the frequency at which tasks are claimed and the task load on the system. Refer to <> for more information. +The intervals of rule checks in {kib} are approximate. Their timing is affected by factors such as the frequency at which tasks are claimed and the task load on the system. Refer to <> for more information. ============================================== [float] [[alerting-concepts-actions]] -==== Actions +=== Actions -Actions are invocations of connectors, which allow interaction with {kib} services or integrations with third-party systems. Actions run as background tasks on the {kib} server when rule conditions are met. +Actions run as background tasks on the {kib} server when rule conditions are met. Recovery actions likewise run when rule conditions are no longer met. They send notifications by connecting with services inside {kib} or integrating with third-party systems. When defining actions in a rule, you specify: -* The _connector type_: the type of service or integration to use -* The connection for that type by referencing a <> +* A connector +* An action frequency * A mapping of rule values to properties exposed for that type of action -The result is a template: all the parameters needed to invoke a service are supplied except for specific values that are only known at the time the rule condition is detected. +Rather than repeatedly entering connection information and credentials for each action, {kib} simplifies action setup using <>. For example if four rules send email notifications via the same SMTP service, they can all reference the same SMTP connector. -In the server monitoring example, the `email` connector type is used, and `server` is mapped to the body of the email, using the template string `CPU on {{server}} is high`. +The _action frequency_ defines when the action runs (for example, only when the alert status changes or at specific time intervals). Each rule type also has a set of the _action groups_ that affects when the action runs (for example, when the threshold is met or when the alert is recovered). If you want to reduce the number of notifications you receive without affecting their timeliness, some rule types support alert summaries. You can set the action frequency such that you receive notifications that summarize the new, ongoing, and recovered alerts at your preferred time intervals. -When the rule detects the condition, it creates an <> containing the details of the condition, renders the template with these details such as server name, and runs the action on the {kib} server by invoking the `email` connector type. +Each action definition is therefore a template: all the parameters needed to invoke a service are supplied except for specific values that are only known at the time the rule condition is detected. -image::images/what-is-an-action.svg[Actions are like templates that are rendered when an alert detects a condition] +In the server monitoring example, the `email` connector type is used, and `server` is mapped to the body of the email, using the template string `CPU on {{server}} is high`. -See <> for details on the types of connectors provided by {kib}. +When the rule detects the condition, it creates an alert containing the details of the condition. [float] [[alerting-concepts-alerts]] -=== Alerts +== Alerts -When checking for a condition, a rule might identify multiple occurrences of the condition. {kib} tracks each of these *alerts* separately and takes an action per alert. +When checking for a condition, a rule might identify multiple occurrences of the condition. {kib} tracks each of these alerts separately. Depending on the action frequency, an action occurs per alert or at the specified alert summary interval. -Using the server monitoring example, each server with average CPU > 0.9 is tracked as an alert. This means a separate email is sent for each server that exceeds the threshold. +Using the server monitoring example, each server with average CPU > 0.9 is tracked as an alert. This means a separate email is sent for each server that exceeds the threshold whenever the alert status changes. image::images/alerts.svg[{kib} tracks each detected condition as an alert and takes action on each alert] -[float] -[[alerting-concepts-connectors]] -=== Connectors - -Actions often involve connecting with services inside {kib} or integrating with third-party systems. -Rather than repeatedly entering connection information and credentials for each action, {kib} simplifies action setup using connectors. - -Connectors provide a central place to store connection information for services and integrations. For example if four rules send email notifications via the same SMTP service, they can all reference the same SMTP connector. When the SMTP settings change, you can update them once in the connector, instead of having to update four rules. - -image::images/rule-concepts-connectors.svg[Connectors provide a central place to store service connection settings] - [float] == Putting it all together @@ -114,10 +100,10 @@ A rule consists of conditions, actions, and a schedule. When conditions are met, image::images/rule-concepts-summary.svg[Rules, connectors, alerts and actions work together to convert detection into action] -. Anytime a rule's conditions are met, an alert is created. This example checks for servers with average CPU > 0.9. Three servers meet the condition, so three alerts are created. -. Alerts create actions as long as they are not muted or throttled. When actions are created, the template that was setup in the rule is filled with actual values. In this example, three actions are created, and the template string {{server}} is replaced with the server name for each alert. -. {kib} invokes the actions, sending them to a third party integration like an email service. -. If the third party integration has connection parameters or credentials, {kib} will fetch these from the connector referenced in the action. +. Any time a rule's conditions are met, an alert is created. This example checks for servers with average CPU > 0.9. Three servers meet the condition, so three alerts are created. +. Alerts create actions according to the action frequency, as long as they are not muted or throttled. When actions are created, its properties are filled with actual values. In this example, three actions are created when the threshold is met, and the template string {{server}} is replaced with the appropriate server name for each alert. +. {kib} runs the actions, sending notifications by using a third party integration like an email service. +. If the third party integration has connection parameters or credentials, {kib} fetches these from the appropriate connector. [float] [[alerting-concepts-differences]] @@ -135,7 +121,7 @@ Functionally, the {alert-features} differ in that: * Scheduled checks are run on {kib} instead of {es} * {kib} <> through rule types, whereas watches provide low-level control over inputs, conditions, and transformations. * {kib} rules track and persist the state of each detected condition through alerts. This makes it possible to mute and throttle individual alerts, and detect changes in state such as resolution. -* Actions are linked to alerts in Alerting. Actions are fired for each occurrence of a detected condition, rather than for the entire rule. +* Actions are linked to alerts. Actions are fired for each occurrence of a detected condition, rather than for the entire rule. At a higher level, the {alert-features} allow rich integrations across use cases like <>, <>, <>, and <>. Prepackaged rule types simplify setup and hide the details of complex, domain-specific detections, while providing a consistent interface across {kib}. diff --git a/docs/user/alerting/create-and-manage-rules.asciidoc b/docs/user/alerting/create-and-manage-rules.asciidoc index d381087809620..86716a99f51ab 100644 --- a/docs/user/alerting/create-and-manage-rules.asciidoc +++ b/docs/user/alerting/create-and-manage-rules.asciidoc @@ -79,21 +79,21 @@ Each connector enables different action properties. For example, an email connec [[alerting-concepts-suppressing-duplicate-notifications]] [TIP] ============================================== -If you are not using alert summaries, actions are triggered per alert and a rule can end up generating a large number of actions. Take the following example where a rule is monitoring three servers every minute for CPU usage > 0.9, and the rule is set to notify `On check intervals`: +If you are not using alert summaries, actions are triggered per alert and a rule can end up generating a large number of actions. Take the following example where a rule is monitoring three servers every minute for CPU usage > 0.9, and the action frequency is `On check intervals`: * Minute 1: server X123 > 0.9. _One email_ is sent for server X123. * Minute 2: X123 and Y456 > 0.9. _Two emails_ are sent, one for X123 and one for Y456. * Minute 3: X123, Y456, Z789 > 0.9. _Three emails_ are sent, one for each of X123, Y456, Z789. In this example, three emails are sent for server X123 in the span of 3 minutes for the same rule. Often, it's desirable to suppress these re-notifications. If -you set the rule notify setting to `On custom action intervals` with an interval of 5 minutes, you reduce noise by getting emails only every 5 minutes for +you set the action frequency to `On custom action intervals` with an interval of 5 minutes, you reduce noise by getting emails only every 5 minutes for servers that continue to exceed the threshold: -* Minute 1: server X123 > 0.9. _One email_ is sent for server X123. -* Minute 2: X123 and Y456 > 0.9. _One email_ is sent for Y456. -* Minute 3: X123, Y456, Z789 > 0.9. _One email_ is sent for Z789. +* Minute 1: server X123 > 0.9. _One email_ will be sent for server X123. +* Minute 2: X123 and Y456 > 0.9. _One email_ will be sent for Y456. +* Minute 3: X123, Y456, Z789 > 0.9. _One email_ will be sent for Z789. -To get notified only once when a server exceeds the threshold, you can set the rule notify setting to `On status changes`. +To get notified only once when a server exceeds the threshold, you can set the action frequency to `On status changes`. Alternatively, if the rule type supports alert summaries, consider using them to reduce the volume of notifications. ============================================== [float] diff --git a/docs/user/alerting/images/alerts.svg b/docs/user/alerting/images/alerts.svg index 022b3106ae802..5e7819dd583f1 100644 --- a/docs/user/alerting/images/alerts.svg +++ b/docs/user/alerting/images/alerts.svg @@ -1 +1,62 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/alerting/images/rule-concepts-connectors.svg b/docs/user/alerting/images/rule-concepts-connectors.svg deleted file mode 100644 index caee5f858fea9..0000000000000 --- a/docs/user/alerting/images/rule-concepts-connectors.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/user/alerting/images/rule-concepts-summary.svg b/docs/user/alerting/images/rule-concepts-summary.svg index aed7020b9d3e2..d7fd2c5806b39 100644 --- a/docs/user/alerting/images/rule-concepts-summary.svg +++ b/docs/user/alerting/images/rule-concepts-summary.svg @@ -1 +1,109 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/alerting/images/what-is-a-rule.svg b/docs/user/alerting/images/what-is-a-rule.svg index 2117e448ba136..2f89c2b4edd59 100644 --- a/docs/user/alerting/images/what-is-a-rule.svg +++ b/docs/user/alerting/images/what-is-a-rule.svg @@ -1 +1,24 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/user/alerting/images/what-is-an-action.svg b/docs/user/alerting/images/what-is-an-action.svg deleted file mode 100644 index f8435ee24fc19..0000000000000 --- a/docs/user/alerting/images/what-is-an-action.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file From 5c2b4d2c3ec57789d83a4c03c4cfeff5f4ddb2e9 Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Mon, 27 Feb 2023 12:13:15 -0600 Subject: [PATCH 015/131] [Security Solution] sign response action documents (#151947) --- x-pack/plugins/fleet/server/mocks/index.ts | 16 +++++---- .../common/endpoint/types/actions.ts | 5 +++ .../endpoint/endpoint_app_context_services.ts | 11 +++++- .../server/endpoint/mocks.ts | 2 ++ .../routes/actions/response_actions.test.ts | 35 +++++++++++++++++++ .../routes/actions/response_actions.ts | 31 +++++++++++----- .../security_solution/server/plugin.ts | 1 + 7 files changed, 86 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/fleet/server/mocks/index.ts b/x-pack/plugins/fleet/server/mocks/index.ts index 4c1d37e3d0f52..8e228f445977e 100644 --- a/x-pack/plugins/fleet/server/mocks/index.ts +++ b/x-pack/plugins/fleet/server/mocks/index.ts @@ -75,12 +75,7 @@ export const createAppContextStartContractMock = ( kibanaBranch: 'main', telemetryEventsSender: createMockTelemetryEventsSender(), bulkActionsResolver: {} as any, - messageSigningService: { - isEncryptionAvailable: true, - generateKeyPair: jest.fn(), - sign: jest.fn(), - getPublicKey: jest.fn(), - }, + messageSigningService: createMessageSigningServiceMock(), }; }; @@ -165,3 +160,12 @@ export const createMockAgentClient = () => agentServiceMock.createClient(); * Creates a mock PackageService */ export const createMockPackageService = () => packageServiceMock.create(); + +export function createMessageSigningServiceMock() { + return { + isEncryptionAvailable: true, + generateKeyPair: jest.fn(), + sign: jest.fn(), + getPublicKey: jest.fn(), + }; +} 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 0a1f482c8583f..b47b4004f9a5b 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts @@ -203,6 +203,11 @@ export interface EndpointAction extends ActionRequestFields { // wait to send back an action result before it will timeout timeout?: number; data: EndpointActionData; + // signature of the endpoint action + signed?: { + data: string; + signature: string; + }; } export interface EndpointActionResponse { diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index d1e236f897ade..0f29e1d46801d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -12,7 +12,7 @@ import type { PluginStartContract as CasesPluginStartContract, } from '@kbn/cases-plugin/server'; import type { SecurityPluginStart } from '@kbn/security-plugin/server'; -import type { FleetStartContract } from '@kbn/fleet-plugin/server'; +import type { FleetStartContract, MessageSigningServiceInterface } from '@kbn/fleet-plugin/server'; import type { PluginStartContract as AlertsPluginStartContract } from '@kbn/alerting-plugin/server'; import { ENDPOINT_HOST_ISOLATION_EXCEPTIONS_LIST_ID } from '@kbn/securitysolution-list-constants'; import { @@ -61,6 +61,7 @@ export interface EndpointAppContextServiceStartContract { cases: CasesPluginStartContract | undefined; featureUsageService: FeatureUsageService; experimentalFeatures: ExperimentalFeatures; + messageSigningService: MessageSigningServiceInterface | undefined; } /** @@ -223,4 +224,12 @@ export class EndpointAppContextService { return this.startDependencies.exceptionListsClient; } + + public getMessageSigningService(): MessageSigningServiceInterface { + if (!this.startDependencies?.messageSigningService) { + throw new EndpointAppContentServicesNotStartedError(); + } + + return this.startDependencies.messageSigningService; + } } diff --git a/x-pack/plugins/security_solution/server/endpoint/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/mocks.ts index be0738c5f0288..7b57a384e0e10 100644 --- a/x-pack/plugins/security_solution/server/endpoint/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/mocks.ts @@ -33,6 +33,7 @@ import { createMockAgentPolicyService, createMockAgentService, createMockPackageService, + createMessageSigningServiceMock, } from '@kbn/fleet-plugin/server/mocks'; // A TS error (TS2403) is thrown when attempting to export the mock function below from Cases // plugin server `index.ts`. Its unclear what is actually causing the error. Since this is a Mock @@ -176,6 +177,7 @@ export const createMockEndpointAppContextServiceStartContract = }, featureUsageService: createFeatureUsageServiceMock(), experimentalFeatures: createMockConfig().experimentalFeatures, + messageSigningService: createMessageSigningServiceMock(), }; }; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts index 0c89c183f0835..42e337efba2d9 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.test.ts @@ -108,6 +108,12 @@ describe('Response actions', () => { const routerMock = httpServiceMock.createRouter(); mockResponse = httpServerMock.createResponseFactory(); const startContract = createMockEndpointAppContextServiceStartContract(); + (startContract.messageSigningService?.sign as jest.Mock).mockImplementation(() => { + return { + data: 'thisisthedata', + signature: 'thisisasignature', + }; + }); endpointAppContextService = new EndpointAppContextService(); const mockSavedObjectClient = savedObjectsClientMock.create(); @@ -637,6 +643,35 @@ describe('Response actions', () => { expect(responseBody.action).toBeUndefined(); }); + it('signs the action', async () => { + const ctx = await callRoute( + ISOLATE_HOST_ROUTE_V2, + { + body: { endpoint_ids: ['XYZ'] }, + }, + { endpointDsExists: true } + ); + + const indexDoc = ctx.core.elasticsearch.client.asInternalUser.index; + const actionDocs: [ + { index: string; body?: LogsEndpointAction }, + { index: string; body?: EndpointAction } + ] = [ + indexDoc.mock.calls[0][0] as estypes.IndexRequest, + indexDoc.mock.calls[1][0] as estypes.IndexRequest, + ]; + + expect(actionDocs[1].index).toEqual(AGENT_ACTIONS_INDEX); + expect(actionDocs[1].body?.signed).toEqual({ + data: 'thisisthedata', + signature: 'thisisasignature', + }); + + expect(mockResponse.ok).toBeCalled(); + const responseBody = mockResponse.ok.mock.calls[0][0]?.body as ResponseActionApiResponse; + expect(responseBody.action).toBeTruthy(); + }); + it('handles errors', async () => { const ErrMessage = 'Uh oh!'; await callRoute( diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts index 559cd0009a4e2..b4197bb947d93 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/response_actions.ts @@ -335,21 +335,36 @@ function responseActionRequestHandler( { index: AGENT_ACTIONS_INDEX, - body: { - ...doc.EndpointActions, - '@timestamp': doc['@timestamp'], - agents, - timeout: 300, // 5 minutes - user_id: doc.user.id, - }, + body: signedFleetActionDoc, refresh: 'wait_for', }, - { meta: true } + { + meta: true, + } ); if (fleetActionIndexResult.statusCode !== 201) { diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index db7a32670727b..5d76046edd7c6 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -509,6 +509,7 @@ export class Plugin implements ISecuritySolutionPlugin { registerListsServerExtension: this.lists?.registerExtension, featureUsageService, experimentalFeatures: config.experimentalFeatures, + messageSigningService: plugins.fleet?.messageSigningService, }); this.telemetryReceiver.start( From cfd0e8731a5921651a8a578afe634a54a225fdf1 Mon Sep 17 00:00:00 2001 From: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com> Date: Mon, 27 Feb 2023 10:14:12 -0800 Subject: [PATCH 016/131] [RAM] Add strict_date_optional_time to excludeHitsFromPreviousRun time range query for ES query rule (#151958) ## Summary Resolves: https://github.com/elastic/kibana/issues/150448 Adds `strict_date_optional_time` to the `excludeHitsFromPreviousRun` last timestamp range query to allow querying data views with non-ISO `timefields`. This fixes the crash that occurred when we didn't have this field when the ES query ran consecutively to exclude previous hits for data views with non-iso time fields. ### To test: ##### 1. Create mapping with date with non-ISO format ``` PUT test-index { "mappings": { "properties": { "date": { "type": "date", "format": "epoch_second" }, "test_field": { "type": "keyword" } } } } ``` ##### 2. Insert test data ``` PUT test-index/_bulk?refresh { "index" : { "_id" : "1" } } { "date": 1677105176, "test_field": "hi"} { "index" : { "_id" : "2" } } { "date": 1677108776, "test_field": "bye"} ``` ##### 3. Create data view with the `date` as the time field. ##### 4. Create a Elasticsearch query rule with KQL, making sure `Exclude matches from previous runs` is checked. Let rule run twice to generate alerts ##### 5. The rule should run without errors (especially after the first run). Before this fix, the rule would error after 1 run. ### 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 --- .../es_query/lib/fetch_search_source_query.test.ts | 1 + .../rule_types/es_query/lib/fetch_search_source_query.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.test.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.test.ts index 9a4026b582381..9afffb7c10ceb 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.test.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.test.ts @@ -124,6 +124,7 @@ describe('fetchSearchSourceQuery', () => { Object { "range": Object { "time": Object { + "format": "strict_date_optional_time", "gt": "2020-02-09T23:12:41.941Z", }, }, diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts index e033f9c6ef4a8..bc22a228ce988 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/lib/fetch_search_source_query.ts @@ -122,7 +122,11 @@ export function updateSearchSource( // add additional filter for documents with a timestamp greater then // the timestamp of the previous run, so that those documents are not counted twice const field = index.fields.find((f) => f.name === timeFieldName); - const addTimeRangeField = buildRangeFilter(field!, { gt: latestTimestamp }, index); + const addTimeRangeField = buildRangeFilter( + field!, + { gt: latestTimestamp, format: 'strict_date_optional_time' }, + index + ); filters.push(addTimeRangeField); } } From 0e2a4480348af43296976c6d7aa4ff5e79179784 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 13:17:26 -0500 Subject: [PATCH 017/131] Update dependency selenium-webdriver to ^4.8.1 (main) (#152156) 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 | |---|---|---|---|---|---| | [selenium-webdriver](https://togithub.com/SeleniumHQ/selenium/tree/trunk/javascript/node/selenium-webdriver#readme) ([source](https://togithub.com/SeleniumHQ/selenium)) | [`^4.8.0` -> `^4.8.1`](https://renovatebot.com/diffs/npm/selenium-webdriver/4.8.0/4.8.1) | [![age](https://badges.renovateapi.com/packages/npm/selenium-webdriver/4.8.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/selenium-webdriver/4.8.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/selenium-webdriver/4.8.1/compatibility-slim/4.8.0)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/selenium-webdriver/4.8.1/confidence-slim/4.8.0)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
SeleniumHQ/selenium ### [`v4.8.1`](https://togithub.com/SeleniumHQ/selenium/compare/267030adeabce01e662cc69342b76f1811c35ee7...8ebccac989e4feb7c9e940a610b5cc5e81254d34) [Compare Source](https://togithub.com/SeleniumHQ/selenium/compare/267030adeabce01e662cc69342b76f1811c35ee7...8ebccac989e4feb7c9e940a610b5cc5e81254d34)
--- ### 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: Jon --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fd551a6571e62..521c5519684d3 100644 --- a/package.json +++ b/package.json @@ -1430,7 +1430,7 @@ "resolve": "^1.22.0", "rxjs-marbles": "^7.0.1", "sass-loader": "^10.4.1", - "selenium-webdriver": "^4.8.0", + "selenium-webdriver": "^4.8.1", "simple-git": "^3.16.0", "sinon": "^7.4.2", "sort-package-json": "^1.53.1", diff --git a/yarn.lock b/yarn.lock index 905ce3e6a3b5d..f2901f09ceaec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25489,10 +25489,10 @@ select-hose@^2.0.0: resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= -selenium-webdriver@^4.8.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.8.0.tgz#386d57f23fe8edf5178f5bd06aae9ffaffbcb692" - integrity sha512-s/HL8WNwy1ggHR244+tAhjhyKMJnZLt1HKJ6Gn7nQgVjB/ybDF+46Uui0qI2J7AjPNJzlUmTncdC/jg/kKkn0A== +selenium-webdriver@^4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.8.1.tgz#4b0a546c4ea747c44e9688c108f7a46b8d8244ab" + integrity sha512-p4MtfhCQdcV6xxkS7eI0tQN6+WNReRULLCAuT4RDGkrjfObBNXMJ3WT8XdK+aXTr5nnBKuh+PxIevM0EjJgkxA== dependencies: jszip "^3.10.0" tmp "^0.2.1" From e2219e000f8f3cc9da83be8847b48fbfa3bc5958 Mon Sep 17 00:00:00 2001 From: GitStart <1501599+gitstart@users.noreply.github.com> Date: Mon, 27 Feb 2023 19:24:01 +0100 Subject: [PATCH 018/131] [Fleet] Display metrics tooltip on Agent details page (#152153) --- .../agent_details/agent_details_overview.tsx | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx index 7fba954a9ca19..4459b8f762382 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx @@ -52,15 +52,47 @@ export const AgentDetailsOverviewSection: React.FunctionComponent<{ {[ { - title: i18n.translate('xpack.fleet.agentDetails.cpuLabel', { - defaultMessage: 'CPU', - }), + title: ( + + } + > + + +   + + + + ), description: formatAgentCPU(agent.metrics, agentPolicy), }, { - title: i18n.translate('xpack.fleet.agentDetails.memoryLabel', { - defaultMessage: 'Memory', - }), + title: ( + + } + > + + +   + + + + ), description: formatAgentMemory(agent.metrics, agentPolicy), }, ].map(({ title, description }) => { From fa0a29fc54550787b55e5d0962b396a92f53994c Mon Sep 17 00:00:00 2001 From: Natali Date: Mon, 27 Feb 2023 19:40:13 +0100 Subject: [PATCH 019/131] chore: remove usage for stats endpoint (#151082) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alejandro Fernández Haro --- .../usage/integration_tests/usage.test.ts | 6 +- .../server/routes/stats/README.md | 6 +- .../server/routes/stats/stats.ts | 73 ++++--------------- test/api_integration/apis/stats/stats.js | 3 + 4 files changed, 24 insertions(+), 64 deletions(-) diff --git a/src/plugins/files/server/usage/integration_tests/usage.test.ts b/src/plugins/files/server/usage/integration_tests/usage.test.ts index 0bccb869c822e..02cc7dfee55fa 100644 --- a/src/plugins/files/server/usage/integration_tests/usage.test.ts +++ b/src/plugins/files/server/usage/integration_tests/usage.test.ts @@ -44,9 +44,11 @@ describe('Files usage telemetry', () => { request.post(root, `/api/files/shares/${fileKind}/${file3.id}`).send({}).expect(200), ]); - const { body } = await request.get(root, `/api/stats?extended=true&legacy=true`); + const { body } = await request + .post(root, '/api/telemetry/v2/clusters/_stats') + .send({ unencrypted: true }); - expect(body.usage.files).toMatchInlineSnapshot(` + expect(body[0].stats.stack_stats.kibana.plugins.files).toMatchInlineSnapshot(` Object { "countByExtension": Array [ Object { diff --git a/src/plugins/usage_collection/server/routes/stats/README.md b/src/plugins/usage_collection/server/routes/stats/README.md index 09dabefbab44a..48ebda9cecb05 100644 --- a/src/plugins/usage_collection/server/routes/stats/README.md +++ b/src/plugins/usage_collection/server/routes/stats/README.md @@ -8,9 +8,9 @@ However, the information detailed above can be extended, with the combination of | Query Parameter | Default value | Description | |:----------------|:-------------:|:------------| -|`extended`|`false`|When `true`, it adds `clusterUuid` and `usage`. The latter contains the information reported by all the Usage Collectors registered in the Kibana server. It may throw `503 Stats not ready` if any of the collectors is not fully initialized yet.| -|`legacy`|`false`|By default, when `extended=true`, the key names of the data in `usage` are transformed into API-friendlier `snake_case` format (i.e.: `clusterUuid` is transformed to `cluster_uuid`). When this parameter is `true`, the data is returned as-is.| -|`exclude_usage`|`false`|When `true`, and `extended=true`, it will report `clusterUuid` but no `usage`.| +|`extended`|`false`|When `true`, it adds `clusterUuid`.| +|`legacy`|`false`|By default, when `extended=true`, the key names are transformed into API-friendlier `snake_case` format (i.e.: `clusterUuid` is transformed to `cluster_uuid`). When this parameter is `true`, the data is returned as-is.| +|`exclude_usage`|`true`| Deprecated. Only kept for backward-compatibility. Setting this to `false` has no effect. Usage is always excluded. | ## Known use cases diff --git a/src/plugins/usage_collection/server/routes/stats/stats.ts b/src/plugins/usage_collection/server/routes/stats/stats.ts index 9db7f5a8638af..242e93a7554e3 100644 --- a/src/plugins/usage_collection/server/routes/stats/stats.ts +++ b/src/plugins/usage_collection/server/routes/stats/stats.ts @@ -8,14 +8,12 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; -import defaultsDeep from 'lodash/defaultsDeep'; import { firstValueFrom, Observable } from 'rxjs'; import { ElasticsearchClient, IRouter, type MetricsServiceSetup, - SavedObjectsClientContract, ServiceStatus, ServiceStatusLevels, } from '@kbn/core/server'; @@ -51,14 +49,6 @@ export function registerStatsRoute({ metrics: MetricsServiceSetup; overallStatus$: Observable; }) { - const getUsage = async ( - esClient: ElasticsearchClient, - savedObjectsClient: SavedObjectsClientContract - ): Promise => { - const usage = await collectorSet.bulkFetchUsage(esClient, savedObjectsClient); - return collectorSet.toObject(usage); - }; - const getClusterUuid = async (asCurrentUser: ElasticsearchClient): Promise => { const body = await asCurrentUser.info({ filter_path: 'cluster_uuid' }); const { cluster_uuid: uuid } = body; @@ -77,7 +67,7 @@ export function registerStatsRoute({ extended: schema.oneOf([schema.literal(''), schema.boolean()], { defaultValue: false }), legacy: schema.oneOf([schema.literal(''), schema.boolean()], { defaultValue: false }), exclude_usage: schema.oneOf([schema.literal(''), schema.boolean()], { - defaultValue: false, + defaultValue: true, }), }), }, @@ -85,61 +75,26 @@ export function registerStatsRoute({ async (context, req, res) => { const isExtended = req.query.extended === '' || req.query.extended; const isLegacy = req.query.legacy === '' || req.query.legacy; - const shouldGetUsage = req.query.exclude_usage === false; let extended; if (isExtended) { const core = await context.core; const { asCurrentUser } = core.elasticsearch.client; - const savedObjectsClient = core.savedObjects.client; - - const [usage, clusterUuid] = await Promise.all([ - shouldGetUsage - ? getUsage(asCurrentUser, savedObjectsClient) - : Promise.resolve({}), - getClusterUuid(asCurrentUser), - ]); - - let modifiedUsage = usage; - if (isLegacy) { - // In an effort to make telemetry more easily augmented, we need to ensure - // we can passthrough the data without every part of the process needing - // to know about the change; however, to support legacy use cases where this - // wasn't true, we need to be backwards compatible with how the legacy data - // looked and support those use cases here. - modifiedUsage = Object.keys(usage).reduce((accum, usageKey) => { - if (usageKey === 'kibana') { - accum = { - ...accum, - ...usage[usageKey], - }; - } else if (usageKey === 'reporting') { - accum = { - ...accum, - xpack: { - ...accum.xpack, - reporting: usage[usageKey], - }, - }; - } else { - // I don't think we need to it this for the above conditions, but do it for most as it will - // match the behavior done in monitoring/bulk_uploader - defaultsDeep(accum, { [usageKey]: usage[usageKey] }); - } - return accum; - }, {} as UsageObject); + const usage = {} as UsageObject; + const clusterUuid = await getClusterUuid(asCurrentUser); - extended = { - usage: modifiedUsage, - clusterUuid, - }; - } else { - extended = collectorSet.toApiFieldNames({ - usage: modifiedUsage, - clusterUuid, - }); - } + // In an effort to make telemetry more easily augmented, we need to ensure + // we can passthrough the data without every part of the process needing + // to know about the change; however, to support legacy use cases where this + // wasn't true, we need to be backwards compatible with how the legacy data + // looked and support those use cases here. + extended = isLegacy + ? { usage, clusterUuid } + : collectorSet.toApiFieldNames({ + usage, + clusterUuid, + }); } // Guaranteed to resolve immediately due to replay effect on getOpsMetrics$ diff --git a/test/api_integration/apis/stats/stats.js b/test/api_integration/apis/stats/stats.js index a95204b5fff4a..3d69a949a4db3 100644 --- a/test/api_integration/apis/stats/stats.js +++ b/test/api_integration/apis/stats/stats.js @@ -91,6 +91,7 @@ export default function ({ getService }) { .then(({ body }) => { expect(body.cluster_uuid).to.be.a('string'); expect(body.usage).to.be.an('object'); // no usage collectors have been registered so usage is an empty object + expect(body.usage).to.eql({}); assertStatsAndMetrics(body); }); }); @@ -103,6 +104,7 @@ export default function ({ getService }) { .then(({ body }) => { expect(body.cluster_uuid).to.be.a('string'); expect(body.usage).to.be.an('object'); + expect(body.usage).to.eql({}); assertStatsAndMetrics(body); }); }); @@ -116,6 +118,7 @@ export default function ({ getService }) { .then(({ body }) => { expect(body.clusterUuid).to.be.a('string'); expect(body.usage).to.be.an('object'); // no usage collectors have been registered so usage is an empty object + expect(body.usage).to.eql({}); assertStatsAndMetrics(body, true); }); }); From b86849030eb48effcfa12996c46687188e3b4153 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Mon, 27 Feb 2023 12:50:51 -0600 Subject: [PATCH 020/131] skip flaky suite (#151979, #151980, #151981) --- .../case_view/components/case_view_activity.test.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx index c454a864d9af5..cb2b501ed4041 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx @@ -111,7 +111,10 @@ const usePostPushToServiceMock = usePostPushToService as jest.Mock; const useGetCaseConnectorsMock = useGetCaseConnectors as jest.Mock; const useGetCaseUsersMock = useGetCaseUsers as jest.Mock; -describe('Case View Page activity tab', () => { +// FLAKY: https://github.com/elastic/kibana/issues/151979 +// FLAKY: https://github.com/elastic/kibana/issues/151980 +// FLAKY: https://github.com/elastic/kibana/issues/151981 +describe.skip('Case View Page activity tab', () => { const caseConnectors = getCaseConnectorsMockResponse(); beforeAll(() => { From b558ba45a58cf826cd31eea1362b66f3f8765d21 Mon Sep 17 00:00:00 2001 From: Ido Cohen <90558359+CohenIdo@users.noreply.github.com> Date: Mon, 27 Feb 2023 20:58:53 +0200 Subject: [PATCH 021/131] [Cloud Security] posture dashboard page journey (#151613) --- .buildkite/ftr_configs.yml | 1 + src/dev/performance/run_performance_cli.ts | 2 +- .../configs/cloud_security_posture_config.ts | 42 ++ .../es_archives/kspm_findings/data.json.gz | Bin 0 -> 49569 bytes .../es_archives/kspm_findings/mappings.json | 464 ++++++++++++++++++ .../journeys/cloud_security_dashboard.ts | 50 ++ x-pack/performance/tsconfig.json | 2 + 7 files changed, 560 insertions(+), 1 deletion(-) create mode 100644 x-pack/performance/configs/cloud_security_posture_config.ts create mode 100644 x-pack/performance/es_archives/kspm_findings/data.json.gz create mode 100644 x-pack/performance/es_archives/kspm_findings/mappings.json create mode 100644 x-pack/performance/journeys/cloud_security_dashboard.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 4adb920c81e43..1400d1fdee4cf 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -359,4 +359,5 @@ enabled: - x-pack/performance/journeys/ecommerce_dashboard_saved_search_only.ts - x-pack/performance/journeys/ecommerce_dashboard_tsvb_gauge_only.ts - x-pack/performance/journeys/dashboard_listing_page.ts + - x-pack/performance/journeys/cloud_security_dashboard.ts - x-pack/test/custom_branding/config.ts diff --git a/src/dev/performance/run_performance_cli.ts b/src/dev/performance/run_performance_cli.ts index daec946f8962b..3539ada07e405 100644 --- a/src/dev/performance/run_performance_cli.ts +++ b/src/dev/performance/run_performance_cli.ts @@ -103,7 +103,7 @@ run( process.stdout.write(`--- Starting ES\n`); await procRunner.run('es', { cmd: 'node', - args: ['scripts/es', 'snapshot'], + args: ['scripts/es', 'snapshot', '--license=trial'], cwd: REPO_ROOT, wait: /kbn\/es setup complete/, }); diff --git a/x-pack/performance/configs/cloud_security_posture_config.ts b/x-pack/performance/configs/cloud_security_posture_config.ts new file mode 100644 index 0000000000000..3d4f36bb2c605 --- /dev/null +++ b/x-pack/performance/configs/cloud_security_posture_config.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const xpackFunctionalConfig = await readConfigFile( + // eslint-disable-next-line @kbn/imports/no_boundary_crossing + require.resolve('../../test/functional/config.base.js') + ); + + return { + ...xpackFunctionalConfig.getAll(), + kbnTestServer: { + ...xpackFunctionalConfig.get('kbnTestServer'), + serverArgs: [ + ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), + /** + * Package version is fixed (not latest) so FTR won't suddenly break when package is changed. + * + * test a new package: + * 1. build the package and start the registry with elastic-package and uncomment the 'registryUrl' flag below + * 2. locally checkout the kibana version that matches the new package + * 3. update the package version below to use the new package version + * 4. run tests with NODE_EXTRA_CA_CERTS pointing to the elastic-package certificate. example: + * NODE_EXTRA_CA_CERTS=HOME/.elastic-package/profiles/default/certs/kibana/ca-cert.pem yarn start + * 5. when test pass: + * 1. release a new package to EPR + * 2. merge the updated version number change to kibana + */ + `--xpack.fleet.packages.0.name=cloud_security_posture`, + `--xpack.fleet.packages.0.version=1.2.8`, + // `--xpack.fleet.registryUrl=https://localhost:8080`, + ], + }, + }; +} diff --git a/x-pack/performance/es_archives/kspm_findings/data.json.gz b/x-pack/performance/es_archives/kspm_findings/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..075885aacbb45c52c3e7a39daca4548d6f1e41c4 GIT binary patch literal 49569 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 V_RVh`V1sXh@sSjCn1V=P{|~6Csn!4h literal 0 HcmV?d00001 diff --git a/x-pack/performance/es_archives/kspm_findings/mappings.json b/x-pack/performance/es_archives/kspm_findings/mappings.json new file mode 100644 index 0000000000000..148507b88cc73 --- /dev/null +++ b/x-pack/performance/es_archives/kspm_findings/mappings.json @@ -0,0 +1,464 @@ +{ + "type": "index", + "value": { + "aliases": {}, + "index": "logs-cloud_security_posture.findings_latest-default", + "mappings": { + "_meta": { + "managed": true, + "managed_by": "fleet", + "package": { + "name": "cloud_security_posture" + } + }, + "date_detection": false, + "dynamic": "false", + "dynamic_templates": [ + { + "strings_as_keyword": { + "mapping": { + "ignore_above": 1024, + "type": "keyword" + }, + "match_mapping_type": "string" + } + } + ], + "properties": { + "@timestamp": { + "type": "date" + }, + "agent": { + "properties": { + "ephemeral_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "provider": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cloudbeat": { + "properties": { + "commit_sha": { + "ignore_above": 1024, + "type": "keyword" + }, + "commit_time": { + "type": "date" + }, + "kubernetes": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "policy": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "cluster_id": { + "ignore_above": 1024, + "type": "keyword" + }, + "data_stream": { + "properties": { + "dataset": { + "type": "constant_keyword", + "value": "cloud_security_posture.findings" + }, + "namespace": { + "type": "constant_keyword", + "value": "default" + }, + "type": { + "type": "constant_keyword", + "value": "logs" + } + } + }, + "ecs": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "event": { + "properties": { + "agent_id_status": { + "ignore_above": 1024, + "type": "keyword" + }, + "category": { + "ignore_above": 1024, + "type": "keyword" + }, + "created": { + "type": "date" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "ingested": { + "format": "strict_date_time_no_millis||strict_date_optional_time||epoch_millis", + "type": "date" + }, + "kind": { + "ignore_above": 1024, + "type": "keyword" + }, + "outcome": { + "ignore_above": 1024, + "type": "keyword" + }, + "sequence": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "directory": { + "ignore_above": 1024, + "type": "keyword" + }, + "extension": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "ignore_above": 1024, + "type": "keyword" + }, + "group": { + "ignore_above": 1024, + "type": "keyword" + }, + "inode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mode": { + "ignore_above": 1024, + "type": "keyword" + }, + "mtime": { + "type": "date" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "owner": { + "ignore_above": 1024, + "type": "keyword" + }, + "path": { + "ignore_above": 1024, + "type": "keyword" + }, + "size": { + "type": "long" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "uid": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "host": { + "properties": { + "architecture": { + "ignore_above": 1024, + "type": "keyword" + }, + "containerized": { + "type": "boolean" + }, + "hostname": { + "ignore_above": 1024, + "type": "keyword" + }, + "ip": { + "type": "ip" + }, + "mac": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "os": { + "properties": { + "codename": { + "ignore_above": 1024, + "type": "keyword" + }, + "family": { + "ignore_above": 1024, + "type": "keyword" + }, + "full": { + "ignore_above": 1024, + "type": "keyword" + }, + "kernel": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "platform": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "message": { + "type": "match_only_text" + }, + "orchestrator": { + "properties": { + "cluster": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "process": { + "properties": { + "args": { + "ignore_above": 1024, + "type": "keyword" + }, + "args_count": { + "type": "long" + }, + "command_line": { + "ignore_above": 1024, + "type": "wildcard" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "parent": { + "properties": { + "pid": { + "type": "long" + }, + "start": { + "type": "date" + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "title": { + "ignore_above": 1024, + "type": "keyword" + }, + "uptime": { + "type": "long" + } + } + }, + "resource": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "raw": { + "enabled": false, + "type": "object" + }, + "sub_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "result": { + "properties": { + "evaluation": { + "ignore_above": 1024, + "type": "keyword" + }, + "evidence": { + "enabled": false, + "type": "object" + }, + "expected": { + "enabled": false, + "type": "object" + } + } + }, + "rule": { + "properties": { + "benchmark": { + "properties": { + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "posture_type": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "description": { + "ignore_above": 1024, + "type": "keyword" + }, + "id": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "rule_number": { + "ignore_above": 1024, + "type": "keyword" + }, + "section": { + "ignore_above": 1024, + "type": "keyword" + }, + "tags": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + }, + "settings": { + "index": { + "codec": "best_compression", + "lifecycle": { + "name": "" + }, + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} diff --git a/x-pack/performance/journeys/cloud_security_dashboard.ts b/x-pack/performance/journeys/cloud_security_dashboard.ts new file mode 100644 index 0000000000000..39625126e7067 --- /dev/null +++ b/x-pack/performance/journeys/cloud_security_dashboard.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Journey } from '@kbn/journeys'; +import expect from '@kbn/expect'; + +export const journey = new Journey({ + beforeSteps: async ({ kibanaServer, retry }) => { + await retry.try(async () => { + const response = await kibanaServer.request({ + path: '/internal/cloud_security_posture/status?check=init', + method: 'GET', + }); + expect(response.status).to.eql(200); + expect(response.data).to.eql({ isPluginInitialized: true }); + }); + }, + ftrConfigPath: 'x-pack/performance/configs/cloud_security_posture_config.ts', + esArchives: ['x-pack/performance/es_archives/kspm_findings'], + scalabilitySetup: { + warmup: [ + { + action: 'constantConcurrentUsers', + userCount: 10, + duration: '30s', + }, + { + action: 'rampConcurrentUsers', + minUsersCount: 10, + maxUsersCount: 50, + duration: '2m', + }, + ], + test: [ + { + action: 'constantConcurrentUsers', + userCount: 50, + duration: '3m', + }, + ], + maxDuration: '10m', + }, +}).step('Go to cloud security dashboards Page', async ({ page, kbnUrl }) => { + await page.goto(kbnUrl.get(`/app/security/cloud_security_posture/dashboard`)); + await page.waitForSelector(`[data-test-subj="csp:dashboard-sections-table-header-score"]`); +}); diff --git a/x-pack/performance/tsconfig.json b/x-pack/performance/tsconfig.json index 636c4e1f5ed1f..fb60be2e310ce 100644 --- a/x-pack/performance/tsconfig.json +++ b/x-pack/performance/tsconfig.json @@ -12,5 +12,7 @@ "@kbn/journeys", "@kbn/test-subj-selector", "@kbn/tooling-log", + "@kbn/test", + "@kbn/expect", ] } From 723c428139d93c1813209fa8f00232be1583041b Mon Sep 17 00:00:00 2001 From: Drew Tate Date: Mon, 27 Feb 2023 13:12:24 -0600 Subject: [PATCH 022/131] [esaggs] Remove out-of-date comment (#152238) Removes an out-of-date comment in the request handler. --- .../common/search/expressions/esaggs/request_handler.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts index 1497dd9aa1a37..196ebfa55810f 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts @@ -61,13 +61,6 @@ export const handleRequest = ({ searchSource.setField('index', indexPattern); searchSource.setField('size', 0); - // Create a new search source that inherits the original search source - // but has the appropriate timeRange applied via a filter. - // This is a temporary solution until we properly pass down all required - // information for the request to the request handler (https://github.com/elastic/kibana/issues/16641). - // Using callParentStartHandlers: true we make sure, that the parent searchSource - // onSearchRequestStart will be called properly even though we use an inherited - // search source. const timeFilterSearchSource = searchSource.createChild({ callParentStartHandlers: true }); const requestSearchSource = timeFilterSearchSource.createChild({ callParentStartHandlers: true, From dcf752e8dfc895c6ea1f7d7213e9f2fd074c24ef Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Mon, 27 Feb 2023 14:24:44 -0500 Subject: [PATCH 023/131] [Response Ops][Alerting] Update common component template generation for framework alerts as data (#150384) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Resolves https://github.com/elastic/kibana/issues/150358 ## Summary In a previous [PR](https://github.com/elastic/kibana/pull/145581) we started installing a common component template for framework alerts as data when the `xpack.alerting.enableFrameworkAlerts` config flag is set to true. In that PR we used a different naming pattern than what is used by the rule registry for its component templates. In this PR we are doing the following: * Renaming the installed `alerts-common-component-template` to `.alerts-framework-mappings`. * Creating and installing `.alerts-legacy-alert-mappings` component template when `enableFrameworkAlerts: true` on alerting plugin setup * The combination of the two component templates creates the same set of mappings as the rule registry technical component template * Creating and installing `.alerts-ecs-mappings` component template when `enableFrameworkAlerts: true` on alerting plugin setup (when `enableFrameworkAlerts: false`, the rule registry continues to install this component template * Using the `@kbn/ecs` package provided by core to generate the ECS field map. The rule registry will continue to install the existing ECS field map which is actually a subset of ECS fields * Adding `useLegacy` and `useEcs` flags that allow rule types to specify whether to include the legacy alerts component template and the ECS component template when registering with framework alerts-as-data. * Moved some common functions to alerting framework from the rule registry ## Things to note * When generating the ECS field map, we are now including the `ignore_above` setting from the `@kbn/ecs` package. This changes the ECS component template to include those settings. I tested updating an index with just `"type":"keyword"` mappings to add the `ignore_above` field to the mapping and had no issues so this seems like an additive change to the mapping that will hopefully prevent problems in the future. * The rule registry ECS component template also includes the technical fields which is redundant because the technical component template is automatically installed for all index templates so the framework ECS component template only contains ECS fields. | Previous mapping | Updated mapping | | ----------- | ----------- | | `{ "organization": { "type": "keyword" } }` | `{ "organization": { "type": "keyword", "ignore_above": 1024 } }` | ## To Verify ### Verify that the generated component templates are as expected: Get the following **While running `main`:** 1. Get the ECS component template `GET _component_template/.alerts-ecs-mappings` 2. Get the technical component template `GET _component_template/.alerts-technical-mappings` 3. Create a detection rule that creates an alert and then get the index mapping for the concrete security alert index `GET .internal.alerts-security.alerts-default-000001/_mapping` **While running this branch with `xpack.alerting.enableFrameworkAlerts: false`:** 4. Get the ECS component template `GET _component_template/.alerts-ecs-mappings` 5. Get the technical component template `GET _component_template/.alerts-technical-mappings` 6. Create a detection rule that creates an alert and then get the index mapping for the concrete security alert index `GET .internal.alerts-security.alerts-default-000001/_mapping` **While running this branch with `xpack.alerting.enableFrameworkAlerts: true`:** 7. Get the ECS component template `GET _component_template/.alerts-ecs-mappings` 8. Get the technical component template `GET _component_template/.alerts-technical-mappings` 9. Create a detection rule that creates an alert and then get the index mapping for the concrete security alert index `GET .internal.alerts-security.alerts-default-000001/_mapping` 10. Verify that component templates exist for `.alerts-framework-mappings` and `.alerts-legacy-alert-mappings` **Compare the ECS component templates** Compare 1 and 4 (ECS component template from `main` and installed by rule registry in this branch). The difference should be: * no difference in ECS fields * because the rule registry ECS component template also includes technical fields, you will see the 2 new technical fields in this branch Compare 4 and 7 (ECS component template from rule registry & alerting framework in this branch). * some new ECS fields for alerting installed template * each `keyword` mapped field for alerting installed template should have `ignore_above` setting * no `kibana.*` fields in the alerting installed template **Compare the technical component templates** Compare 2 and 5 (technical component template from `main` and installed by rule registry in this branch). The difference should be: * 2 new `kibana.alert` fields (`flapping_history` and `last_detected`) Compare 5 and 8 (technical component template from rule registry & alerting framework in this branch). * there should be no difference! **Compare the index mappings** Compare 3 and 6 (index mapping from `main` and installed by rule registry in this branch). The difference should be: * 2 new `kibana.alert` fields (`flapping_history` and `last_detected`) Compare 6 and 9 (index mapping from rule registry & alerting framework in this branch). * some new ECS fields * each `keyword` mapped ECS field should have `ignore_above` setting ### Verify that the generated component templates work with existing rule registry index templates & indices: 1. Run `main` or a previous version and create a rule that uses both ECS component templates & technical component templates (detection rules use both). Let it run a few times. 2. Using the same ES data, switch to this branch with `xpack.alerting.enableFrameworkAlerts: false` and verify Kibana starts with no rule registry errors and the rule continues to run as expected. 3. Using the same ES data, switch to this branch with `xpack.alerting.enableFrameworkAlerts: true` and verify Kibana starts with no alerting or rule registry errors and the rule continues to run as expected. Verify that the mapping on the existing `.internal.alerts-security.alerts-default-000001` has been updated to include the latest ECS mappings and the two new technical fields. ### 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: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Mike Côté --- .github/CODEOWNERS | 1 + package.json | 1 + packages/kbn-alerts-as-data-utils/index.ts | 9 + .../kbn-alerts-as-data-utils/kibana.jsonc | 5 + .../kbn-alerts-as-data-utils/package.json | 6 + .../src}/field_maps/alert_field_map.ts | 128 ++++--- .../src/field_maps/ecs_field_map.ts | 27 ++ .../src/field_maps/index.ts | 12 + .../src/field_maps/legacy_alert_field_map.ts | 202 +++++++++++ .../src/field_maps/types.ts | 54 +++ .../kbn-alerts-as-data-utils/tsconfig.json | 20 ++ packages/kbn-rule-data-utils/index.ts | 1 + .../src/default_alerts_as_data.ts | 32 +- .../src/legacy_alerts_as_data.ts | 84 +++++ .../src/technical_field_names.ts | 121 +++---- packages/kbn-rule-data-utils/tsconfig.json | 2 +- tsconfig.base.json | 2 + .../component_template_from_field_map.ts | 2 +- .../field_maps/mapping_from_field_map.test.ts | 97 +++++- .../field_maps/mapping_from_field_map.ts | 3 +- .../common/alert_schema/field_maps/types.ts | 29 -- .../alerting/common/alert_schema/index.ts | 2 +- x-pack/plugins/alerting/common/index.ts | 2 + .../alerts_service/alerts_service.test.ts | 314 ++++++++++++++---- .../server/alerts_service/alerts_service.ts | 159 +++++++-- .../server/alerts_service/index.ts} | 16 +- .../alerting/server/alerts_service/types.ts | 8 +- x-pack/plugins/alerting/server/index.ts | 5 +- x-pack/plugins/alerting/server/types.ts | 4 +- x-pack/plugins/alerting/tsconfig.json | 2 + x-pack/plugins/apm/server/plugin.ts | 9 +- .../server/services/rules/rule_data_client.ts | 4 +- x-pack/plugins/observability/server/plugin.ts | 4 +- x-pack/plugins/rule_registry/common/assets.ts | 3 +- .../ecs_component_template.ts | 2 +- .../technical_component_template.ts | 2 +- .../experimental_rule_field_map.test.ts | 2 + .../field_maps/experimental_rule_field_map.ts | 8 +- .../technical_rule_field_map.test.ts | 25 ++ .../field_maps/technical_rule_field_map.ts | 219 +----------- .../rule_registry/common/field_map/index.ts | 1 - .../common/field_map/merge_field_maps.ts | 3 +- .../runtime_type_from_fieldmap.test.ts | 8 +- .../field_map/runtime_type_from_fieldmap.ts | 2 +- .../common/mapping_from_field_map.ts | 36 -- .../resource_installer.test.ts | 31 +- .../resource_installer.ts | 32 +- x-pack/plugins/rule_registry/tsconfig.json | 2 +- .../security_solution/server/plugin.ts | 7 +- .../plugins/security_solution/tsconfig.json | 1 + .../common/rules/uptime_rule_field_map.ts | 14 + x-pack/plugins/synthetics/server/plugin.ts | 2 +- .../tests/alerting/group4/alerts_as_data.ts | 82 ++++- .../tests/trial/get_summarized_alerts.ts | 2 +- .../tests/trial/lifecycle_executor.ts | 2 +- x-pack/test/tsconfig.json | 1 + yarn.lock | 4 + 57 files changed, 1234 insertions(+), 624 deletions(-) create mode 100644 packages/kbn-alerts-as-data-utils/index.ts create mode 100644 packages/kbn-alerts-as-data-utils/kibana.jsonc create mode 100644 packages/kbn-alerts-as-data-utils/package.json rename {x-pack/plugins/alerting/common/alert_schema => packages/kbn-alerts-as-data-utils/src}/field_maps/alert_field_map.ts (77%) create mode 100644 packages/kbn-alerts-as-data-utils/src/field_maps/ecs_field_map.ts create mode 100644 packages/kbn-alerts-as-data-utils/src/field_maps/index.ts create mode 100644 packages/kbn-alerts-as-data-utils/src/field_maps/legacy_alert_field_map.ts create mode 100644 packages/kbn-alerts-as-data-utils/src/field_maps/types.ts create mode 100644 packages/kbn-alerts-as-data-utils/tsconfig.json create mode 100644 packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts delete mode 100644 x-pack/plugins/alerting/common/alert_schema/field_maps/types.ts rename x-pack/plugins/{rule_registry/common/field_map/types.ts => alerting/server/alerts_service/index.ts} (52%) delete mode 100644 x-pack/plugins/rule_registry/common/mapping_from_field_map.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 40677dc5a498e..f44a2e962f1fa 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -19,6 +19,7 @@ x-pack/examples/alerting_example @elastic/response-ops x-pack/test/functional_with_es_ssl/plugins/alerts @elastic/response-ops x-pack/plugins/alerting @elastic/response-ops packages/kbn-alerts @elastic/security-solution +packages/kbn-alerts-as-data-utils @elastic/response-ops x-pack/test/alerting_api_integration/common/plugins/alerts_restricted @elastic/response-ops packages/kbn-alerts-ui-shared @elastic/response-ops packages/kbn-ambient-common-types @elastic/kibana-operations diff --git a/package.json b/package.json index 521c5519684d3..ec45d23c195e2 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "@kbn/alerting-fixture-plugin": "link:x-pack/test/functional_with_es_ssl/plugins/alerts", "@kbn/alerting-plugin": "link:x-pack/plugins/alerting", "@kbn/alerts": "link:packages/kbn-alerts", + "@kbn/alerts-as-data-utils": "link:packages/kbn-alerts-as-data-utils", "@kbn/alerts-restricted-fixtures-plugin": "link:x-pack/test/alerting_api_integration/common/plugins/alerts_restricted", "@kbn/alerts-ui-shared": "link:packages/kbn-alerts-ui-shared", "@kbn/analytics": "link:packages/kbn-analytics", diff --git a/packages/kbn-alerts-as-data-utils/index.ts b/packages/kbn-alerts-as-data-utils/index.ts new file mode 100644 index 0000000000000..7b2cad2ca5440 --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/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 * from './src/field_maps'; diff --git a/packages/kbn-alerts-as-data-utils/kibana.jsonc b/packages/kbn-alerts-as-data-utils/kibana.jsonc new file mode 100644 index 0000000000000..07e8490dde7b5 --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/alerts-as-data-utils", + "owner": "@elastic/response-ops" +} diff --git a/packages/kbn-alerts-as-data-utils/package.json b/packages/kbn-alerts-as-data-utils/package.json new file mode 100644 index 0000000000000..25aa26b3d435c --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/alerts-as-data-utils", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} \ No newline at end of file diff --git a/x-pack/plugins/alerting/common/alert_schema/field_maps/alert_field_map.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts similarity index 77% rename from x-pack/plugins/alerting/common/alert_schema/field_maps/alert_field_map.ts rename to packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts index 4613415e0fa00..8e5a606a91017 100644 --- a/x-pack/plugins/alerting/common/alert_schema/field_maps/alert_field_map.ts +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts @@ -1,16 +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. + * 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 { ALERT_ACTION_GROUP, + ALERT_CASE_IDS, ALERT_DURATION, ALERT_END, ALERT_FLAPPING, - ALERT_ID, + ALERT_FLAPPING_HISTORY, + ALERT_INSTANCE_ID, + ALERT_LAST_DETECTED, ALERT_REASON, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, @@ -27,92 +31,93 @@ import { ALERT_UUID, ALERT_WORKFLOW_STATUS, SPACE_IDS, + TIMESTAMP, VERSION, } from '@kbn/rule-data-utils'; export const alertFieldMap = { - [ALERT_RULE_PARAMETERS]: { - type: 'object', - enabled: false, + [ALERT_ACTION_GROUP]: { + type: 'keyword', + array: false, required: false, }, - [ALERT_RULE_TYPE_ID]: { + [ALERT_CASE_IDS]: { type: 'keyword', + array: true, + required: false, + }, + [ALERT_DURATION]: { + type: 'long', array: false, - required: true, + required: false, }, - [ALERT_RULE_CONSUMER]: { - type: 'keyword', + [ALERT_END]: { + type: 'date', array: false, - required: true, + required: false, }, - [ALERT_RULE_PRODUCER]: { - type: 'keyword', + [ALERT_FLAPPING]: { + type: 'boolean', array: false, - required: true, + required: false, }, - [SPACE_IDS]: { - type: 'keyword', + [ALERT_FLAPPING_HISTORY]: { + type: 'boolean', array: true, - required: true, - }, - [ALERT_UUID]: { - type: 'keyword', - array: false, - required: true, + required: false, }, - [ALERT_ID]: { + [ALERT_INSTANCE_ID]: { type: 'keyword', array: false, required: true, }, - [ALERT_START]: { + [ALERT_LAST_DETECTED]: { type: 'date', - array: false, required: false, - }, - [ALERT_TIME_RANGE]: { - type: 'date_range', - format: 'epoch_millis||strict_date_optional_time', array: false, - required: false, }, - [ALERT_END]: { - type: 'date', + [ALERT_REASON]: { + type: 'keyword', array: false, required: false, }, - [ALERT_DURATION]: { - type: 'long', + [ALERT_RULE_CATEGORY]: { + type: 'keyword', array: false, - required: false, + required: true, }, - [ALERT_STATUS]: { + [ALERT_RULE_CONSUMER]: { type: 'keyword', array: false, required: true, }, - [VERSION]: { - type: 'version', + [ALERT_RULE_EXECUTION_UUID]: { + type: 'keyword', array: false, required: false, }, - [ALERT_WORKFLOW_STATUS]: { + [ALERT_RULE_NAME]: { type: 'keyword', array: false, - required: false, + required: true, }, - [ALERT_ACTION_GROUP]: { - type: 'keyword', + [ALERT_RULE_PARAMETERS]: { array: false, + type: 'flattened', + ignore_above: 4096, required: false, }, - [ALERT_REASON]: { + [ALERT_RULE_PRODUCER]: { type: 'keyword', array: false, + required: true, + }, + [ALERT_RULE_TAGS]: { + type: 'keyword', + array: true, required: false, }, - [ALERT_RULE_CATEGORY]: { + [ALERT_RULE_TYPE_ID]: { type: 'keyword', array: false, required: true, @@ -122,26 +127,47 @@ export const alertFieldMap = { array: false, required: true, }, - [ALERT_RULE_EXECUTION_UUID]: { + [ALERT_START]: { + type: 'date', + array: false, + required: false, + }, + [ALERT_STATUS]: { type: 'keyword', array: false, + required: true, + }, + [ALERT_TIME_RANGE]: { + type: 'date_range', + format: 'epoch_millis||strict_date_optional_time', + array: false, required: false, }, - [ALERT_RULE_NAME]: { + [ALERT_UUID]: { type: 'keyword', array: false, required: true, }, - [ALERT_RULE_TAGS]: { + [ALERT_WORKFLOW_STATUS]: { type: 'keyword', - array: true, + array: false, required: false, }, - [ALERT_FLAPPING]: { - type: 'boolean', + [SPACE_IDS]: { + type: 'keyword', + array: true, + required: true, + }, + [TIMESTAMP]: { + type: 'date', + required: true, + array: false, + }, + [VERSION]: { + type: 'version', array: false, required: false, }, -}; +} as const; export type AlertFieldMap = typeof alertFieldMap; diff --git a/packages/kbn-alerts-as-data-utils/src/field_maps/ecs_field_map.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/ecs_field_map.ts new file mode 100644 index 0000000000000..9294a12b4ce50 --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/ecs_field_map.ts @@ -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 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 { EcsFlat } from '@kbn/ecs'; +import { EcsMetadata, FieldMap } from './types'; + +export const ecsFieldMap: FieldMap = Object.keys(EcsFlat).reduce((acc, currKey) => { + const value: EcsMetadata = EcsFlat[currKey as keyof typeof EcsFlat]; + return { + ...acc, + [currKey]: { + type: value.type, + array: value.normalize.includes('array'), + required: !!value.required, + ...(value.scaling_factor ? { scaling_factor: value.scaling_factor } : {}), + ...(value.ignore_above ? { ignore_above: value.ignore_above } : {}), + ...(value.multi_fields ? { multi_fields: value.multi_fields } : {}), + }, + }; +}, {}); + +export type EcsFieldMap = typeof ecsFieldMap; diff --git a/packages/kbn-alerts-as-data-utils/src/field_maps/index.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/index.ts new file mode 100644 index 0000000000000..9aef7690b343c --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './alert_field_map'; +export * from './ecs_field_map'; +export * from './legacy_alert_field_map'; +export type { FieldMap, MultiField } from './types'; diff --git a/packages/kbn-alerts-as-data-utils/src/field_maps/legacy_alert_field_map.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/legacy_alert_field_map.ts new file mode 100644 index 0000000000000..6faa403188fdb --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/legacy_alert_field_map.ts @@ -0,0 +1,202 @@ +/* + * Copyright 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 { + ALERT_RISK_SCORE, + ALERT_RULE_AUTHOR, + ALERT_RULE_CREATED_AT, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FROM, + ALERT_RULE_INTERVAL, + ALERT_RULE_LICENSE, + ALERT_RULE_NOTE, + ALERT_RULE_REFERENCES, + ALERT_RULE_RULE_ID, + ALERT_RULE_RULE_NAME_OVERRIDE, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_AT, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_SEVERITY, + ALERT_SUPPRESSION_DOCS_COUNT, + ALERT_SUPPRESSION_END, + ALERT_SUPPRESSION_FIELD, + ALERT_SUPPRESSION_START, + ALERT_SUPPRESSION_VALUE, + ALERT_SYSTEM_STATUS, + ALERT_WORKFLOW_REASON, + ALERT_WORKFLOW_USER, + ECS_VERSION, + EVENT_ACTION, + EVENT_KIND, + TAGS, +} from '@kbn/rule-data-utils'; + +export const legacyAlertFieldMap = { + [ALERT_RISK_SCORE]: { + type: 'float', + array: false, + required: false, + }, + [ALERT_RULE_AUTHOR]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_CREATED_AT]: { + type: 'date', + array: false, + required: false, + }, + [ALERT_RULE_CREATED_BY]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_DESCRIPTION]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_ENABLED]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_FROM]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_INTERVAL]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_LICENSE]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_NOTE]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_REFERENCES]: { + type: 'keyword', + array: true, + required: false, + }, + [ALERT_RULE_RULE_ID]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_RULE_NAME_OVERRIDE]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_TO]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_TYPE]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_UPDATED_AT]: { + type: 'date', + array: false, + required: false, + }, + [ALERT_RULE_UPDATED_BY]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_RULE_VERSION]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_SEVERITY]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_SUPPRESSION_DOCS_COUNT]: { + type: 'long', + array: false, + required: false, + }, + [ALERT_SUPPRESSION_END]: { + type: 'date', + array: false, + required: false, + }, + [ALERT_SUPPRESSION_FIELD]: { + type: 'keyword', + array: true, + required: false, + }, + [ALERT_SUPPRESSION_START]: { + type: 'date', + array: false, + required: false, + }, + [ALERT_SUPPRESSION_VALUE]: { + type: 'keyword', + array: true, + required: false, + }, + [ALERT_SYSTEM_STATUS]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_WORKFLOW_REASON]: { + type: 'keyword', + array: false, + required: false, + }, + [ALERT_WORKFLOW_USER]: { + type: 'keyword', + array: false, + required: false, + }, + // get these from ecs field map when available + [ECS_VERSION]: { + type: 'keyword', + array: false, + required: false, + }, + [EVENT_ACTION]: { + type: 'keyword', + array: false, + required: false, + }, + [EVENT_KIND]: { + type: 'keyword', + array: false, + required: false, + }, + [TAGS]: { + type: 'keyword', + array: true, + required: false, + }, +} as const; + +export type LegacyAlertFieldMap = typeof legacyAlertFieldMap; diff --git a/packages/kbn-alerts-as-data-utils/src/field_maps/types.ts b/packages/kbn-alerts-as-data-utils/src/field_maps/types.ts new file mode 100644 index 0000000000000..04f9d045f6e28 --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/src/field_maps/types.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 AllowedValue { + description?: string; + name?: string; +} + +export interface MultiField { + flat_name: string; + name: string; + type: string; +} + +export interface EcsMetadata { + allowed_values?: AllowedValue[]; + dashed_name: string; + description: string; + doc_values?: boolean; + example?: string | number | boolean; + flat_name: string; + ignore_above?: number; + index?: boolean; + level: string; + multi_fields?: MultiField[]; + name: string; + normalize: string[]; + required?: boolean; + scaling_factor?: number; + short: string; + type: string; +} + +export interface FieldMap { + [key: string]: { + type: string; + required: boolean; + array?: boolean; + doc_values?: boolean; + enabled?: boolean; + format?: string; + ignore_above?: number; + multi_fields?: MultiField[]; + index?: boolean; + path?: string; + scaling_factor?: number; + dynamic?: boolean | 'strict'; + }; +} diff --git a/packages/kbn-alerts-as-data-utils/tsconfig.json b/packages/kbn-alerts-as-data-utils/tsconfig.json new file mode 100644 index 0000000000000..00b7ffc082c95 --- /dev/null +++ b/packages/kbn-alerts-as-data-utils/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/ecs", + "@kbn/rule-data-utils", + ] +} diff --git a/packages/kbn-rule-data-utils/index.ts b/packages/kbn-rule-data-utils/index.ts index 145cc2c5220e9..ea0028b972ed9 100644 --- a/packages/kbn-rule-data-utils/index.ts +++ b/packages/kbn-rule-data-utils/index.ts @@ -7,6 +7,7 @@ */ export * from './src/default_alerts_as_data'; +export * from './src/legacy_alerts_as_data'; export * from './src/technical_field_names'; export * from './src/alerts_as_data_rbac'; export * from './src/alerts_as_data_severity'; diff --git a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts index 3a982124b58e6..34b04116b9522 100644 --- a/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts +++ b/packages/kbn-rule-data-utils/src/default_alerts_as_data.ts @@ -8,6 +8,9 @@ import { ValuesType } from 'utility-types'; +const TIMESTAMP = '@timestamp' as const; + +// namespaces const KIBANA_NAMESPACE = 'kibana' as const; const ALERT_NAMESPACE = `${KIBANA_NAMESPACE}.alert` as const; const ALERT_RULE_NAMESPACE = `${ALERT_NAMESPACE}.rule` as const; @@ -21,6 +24,9 @@ const VERSION = `${KIBANA_NAMESPACE}.version` as const; // kibana.alert.action_group - framework action group ID for this alert const ALERT_ACTION_GROUP = `${ALERT_NAMESPACE}.action_group` as const; +// kibana.alert.case_ids - array of cases associated with the alert +const ALERT_CASE_IDS = `${ALERT_NAMESPACE}.case_ids` as const; + // kibana.alert.duration.us - alert duration in nanoseconds - updated each execution // that the alert is active const ALERT_DURATION = `${ALERT_NAMESPACE}.duration.us` as const; @@ -31,8 +37,11 @@ const ALERT_END = `${ALERT_NAMESPACE}.end` as const; // kibana.alert.flapping - whether the alert is currently in a flapping state const ALERT_FLAPPING = `${ALERT_NAMESPACE}.flapping` as const; -// kibana.alert.id - alert ID, also known as alert instance ID -const ALERT_ID = `${ALERT_NAMESPACE}.id` as const; +// kibana.alert.flapping_history - whether the alert is currently in a flapping state +const ALERT_FLAPPING_HISTORY = `${ALERT_NAMESPACE}.flapping_history` as const; + +// kibana.alert.instance.id - alert ID, also known as alert instance ID +const ALERT_INSTANCE_ID = `${ALERT_NAMESPACE}.instance.id` as const; // kibana.alert.last_detected - timestamp when the alert was last seen const ALERT_LAST_DETECTED = `${ALERT_NAMESPACE}.last_detected` as const; @@ -90,10 +99,12 @@ const namespaces = { const fields = { ALERT_ACTION_GROUP, + ALERT_CASE_IDS, ALERT_DURATION, ALERT_END, ALERT_FLAPPING, - ALERT_ID, + ALERT_FLAPPING_HISTORY, + ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, ALERT_RULE_CATEGORY, @@ -111,15 +122,24 @@ const fields = { ALERT_UUID, ALERT_WORKFLOW_STATUS, SPACE_IDS, + TIMESTAMP, VERSION, }; export { + // namespaces + ALERT_NAMESPACE, + ALERT_RULE_NAMESPACE, + KIBANA_NAMESPACE, + + // fields ALERT_ACTION_GROUP, + ALERT_CASE_IDS, ALERT_DURATION, ALERT_END, ALERT_FLAPPING, - ALERT_ID, + ALERT_FLAPPING_HISTORY, + ALERT_INSTANCE_ID, ALERT_LAST_DETECTED, ALERT_REASON, ALERT_RULE_CATEGORY, @@ -137,10 +157,8 @@ export { ALERT_UUID, ALERT_WORKFLOW_STATUS, SPACE_IDS, + TIMESTAMP, VERSION, - ALERT_NAMESPACE, - ALERT_RULE_NAMESPACE, - KIBANA_NAMESPACE, }; export type DefaultAlertFieldName = ValuesType; diff --git a/packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts b/packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts new file mode 100644 index 0000000000000..4dd6c2be0c2a6 --- /dev/null +++ b/packages/kbn-rule-data-utils/src/legacy_alerts_as_data.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 { ALERT_NAMESPACE, ALERT_RULE_NAMESPACE } from './default_alerts_as_data'; + +const ECS_VERSION = 'ecs.version' as const; +const EVENT_ACTION = 'event.action' as const; +const EVENT_KIND = 'event.kind' as const; +const TAGS = 'tags' as const; + +// These are the fields that are in the rule registry technical component template +// that are NOT in the framework alerts as data common component template + +// We will maintain a legacy component template that can be used by legacy +// rule registry rules with these fields. +const ALERT_RISK_SCORE = `${ALERT_NAMESPACE}.risk_score` as const; +const ALERT_RULE_AUTHOR = `${ALERT_RULE_NAMESPACE}.author` as const; +const ALERT_RULE_CREATED_AT = `${ALERT_RULE_NAMESPACE}.created_at` as const; +const ALERT_RULE_CREATED_BY = `${ALERT_RULE_NAMESPACE}.created_by` as const; +const ALERT_RULE_DESCRIPTION = `${ALERT_RULE_NAMESPACE}.description` as const; +const ALERT_RULE_ENABLED = `${ALERT_RULE_NAMESPACE}.enabled` as const; +const ALERT_RULE_FROM = `${ALERT_RULE_NAMESPACE}.from` as const; +const ALERT_RULE_INTERVAL = `${ALERT_RULE_NAMESPACE}.interval` as const; +const ALERT_RULE_LICENSE = `${ALERT_RULE_NAMESPACE}.license` as const; +const ALERT_RULE_NOTE = `${ALERT_RULE_NAMESPACE}.note` as const; +const ALERT_RULE_REFERENCES = `${ALERT_RULE_NAMESPACE}.references` as const; +const ALERT_RULE_RULE_ID = `${ALERT_RULE_NAMESPACE}.rule_id` as const; +const ALERT_RULE_RULE_NAME_OVERRIDE = `${ALERT_RULE_NAMESPACE}.rule_name_override` as const; +const ALERT_RULE_TO = `${ALERT_RULE_NAMESPACE}.to` as const; +const ALERT_RULE_TYPE = `${ALERT_RULE_NAMESPACE}.type` as const; +const ALERT_RULE_UPDATED_AT = `${ALERT_RULE_NAMESPACE}.updated_at` as const; +const ALERT_RULE_UPDATED_BY = `${ALERT_RULE_NAMESPACE}.updated_by` as const; +const ALERT_RULE_VERSION = `${ALERT_RULE_NAMESPACE}.version` as const; +const ALERT_SEVERITY = `${ALERT_NAMESPACE}.severity` as const; +const ALERT_SUPPRESSION_META = `${ALERT_NAMESPACE}.suppression` as const; +const ALERT_SUPPRESSION_TERMS = `${ALERT_SUPPRESSION_META}.terms` as const; +const ALERT_SUPPRESSION_FIELD = `${ALERT_SUPPRESSION_TERMS}.field` as const; +const ALERT_SUPPRESSION_VALUE = `${ALERT_SUPPRESSION_TERMS}.value` as const; +const ALERT_SUPPRESSION_START = `${ALERT_SUPPRESSION_META}.start` as const; +const ALERT_SUPPRESSION_END = `${ALERT_SUPPRESSION_META}.end` as const; +const ALERT_SUPPRESSION_DOCS_COUNT = `${ALERT_SUPPRESSION_META}.docs_count` as const; +const ALERT_SYSTEM_STATUS = `${ALERT_NAMESPACE}.system_status` as const; +const ALERT_WORKFLOW_REASON = `${ALERT_NAMESPACE}.workflow_reason` as const; +const ALERT_WORKFLOW_USER = `${ALERT_NAMESPACE}.workflow_user` as const; + +export { + ALERT_RISK_SCORE, + ALERT_RULE_AUTHOR, + ALERT_RULE_CREATED_AT, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FROM, + ALERT_RULE_INTERVAL, + ALERT_RULE_LICENSE, + ALERT_RULE_NOTE, + ALERT_RULE_REFERENCES, + ALERT_RULE_RULE_ID, + ALERT_RULE_RULE_NAME_OVERRIDE, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_AT, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_SEVERITY, + ALERT_SUPPRESSION_DOCS_COUNT, + ALERT_SUPPRESSION_END, + ALERT_SUPPRESSION_FIELD, + ALERT_SUPPRESSION_START, + ALERT_SUPPRESSION_TERMS, + ALERT_SUPPRESSION_VALUE, + ALERT_SYSTEM_STATUS, + ALERT_WORKFLOW_REASON, + ALERT_WORKFLOW_USER, + ECS_VERSION, + EVENT_ACTION, + EVENT_KIND, + TAGS, +}; diff --git a/packages/kbn-rule-data-utils/src/technical_field_names.ts b/packages/kbn-rule-data-utils/src/technical_field_names.ts index 89eca0f923046..cf45162b20853 100644 --- a/packages/kbn-rule-data-utils/src/technical_field_names.ts +++ b/packages/kbn-rule-data-utils/src/technical_field_names.ts @@ -8,11 +8,15 @@ import { ValuesType } from 'utility-types'; import { + ALERT_NAMESPACE, + ALERT_RULE_NAMESPACE, KIBANA_NAMESPACE, ALERT_ACTION_GROUP, + ALERT_CASE_IDS, ALERT_DURATION, ALERT_END, ALERT_FLAPPING, + ALERT_INSTANCE_ID, ALERT_REASON, ALERT_RULE_CATEGORY, ALERT_RULE_CONSUMER, @@ -29,61 +33,61 @@ import { ALERT_UUID, ALERT_WORKFLOW_STATUS, SPACE_IDS, + TIMESTAMP, VERSION, - ALERT_NAMESPACE, - ALERT_RULE_NAMESPACE, } from './default_alerts_as_data'; +import { + ALERT_RISK_SCORE, + ALERT_RULE_AUTHOR, + ALERT_RULE_CREATED_AT, + ALERT_RULE_CREATED_BY, + ALERT_RULE_DESCRIPTION, + ALERT_RULE_ENABLED, + ALERT_RULE_FROM, + ALERT_RULE_INTERVAL, + ALERT_RULE_LICENSE, + ALERT_RULE_NOTE, + ALERT_RULE_REFERENCES, + ALERT_RULE_RULE_ID, + ALERT_RULE_RULE_NAME_OVERRIDE, + ALERT_RULE_TO, + ALERT_RULE_TYPE, + ALERT_RULE_UPDATED_AT, + ALERT_RULE_UPDATED_BY, + ALERT_RULE_VERSION, + ALERT_SEVERITY, + ALERT_SUPPRESSION_DOCS_COUNT, + ALERT_SUPPRESSION_END, + ALERT_SUPPRESSION_FIELD, + ALERT_SUPPRESSION_START, + ALERT_SUPPRESSION_TERMS, + ALERT_SUPPRESSION_VALUE, + ALERT_SYSTEM_STATUS, + ALERT_WORKFLOW_REASON, + ALERT_WORKFLOW_USER, + ECS_VERSION, + EVENT_ACTION, + EVENT_KIND, + TAGS, +} from './legacy_alerts_as_data'; + +// The following fields were identified as technical field names but were not defined in the +// rule registry technical component template. We will leave these here for backwards +// compatibility but these consts should be moved to the plugin that uses them + const ALERT_RULE_THREAT_NAMESPACE = `${ALERT_RULE_NAMESPACE}.threat` as const; -const ECS_VERSION = 'ecs.version' as const; -const EVENT_ACTION = 'event.action' as const; -const EVENT_KIND = 'event.kind' as const; const EVENT_MODULE = 'event.module' as const; -const TAGS = 'tags' as const; -const TIMESTAMP = '@timestamp' as const; // Fields pertaining to the alert const ALERT_BUILDING_BLOCK_TYPE = `${ALERT_NAMESPACE}.building_block_type` as const; const ALERT_EVALUATION_THRESHOLD = `${ALERT_NAMESPACE}.evaluation.threshold` as const; const ALERT_EVALUATION_VALUE = `${ALERT_NAMESPACE}.evaluation.value` as const; -const ALERT_INSTANCE_ID = `${ALERT_NAMESPACE}.instance.id` as const; -const ALERT_RISK_SCORE = `${ALERT_NAMESPACE}.risk_score` as const; -const ALERT_SEVERITY = `${ALERT_NAMESPACE}.severity` as const; -const ALERT_SYSTEM_STATUS = `${ALERT_NAMESPACE}.system_status` as const; -const ALERT_WORKFLOW_REASON = `${ALERT_NAMESPACE}.workflow_reason` as const; -const ALERT_WORKFLOW_USER = `${ALERT_NAMESPACE}.workflow_user` as const; -const ALERT_SUPPRESSION_META = `${ALERT_NAMESPACE}.suppression` as const; -const ALERT_SUPPRESSION_TERMS = `${ALERT_SUPPRESSION_META}.terms` as const; -const ALERT_SUPPRESSION_FIELD = `${ALERT_SUPPRESSION_TERMS}.field` as const; -const ALERT_SUPPRESSION_VALUE = `${ALERT_SUPPRESSION_TERMS}.value` as const; -const ALERT_SUPPRESSION_START = `${ALERT_SUPPRESSION_META}.start` as const; -const ALERT_SUPPRESSION_END = `${ALERT_SUPPRESSION_META}.end` as const; -const ALERT_SUPPRESSION_DOCS_COUNT = `${ALERT_SUPPRESSION_META}.docs_count` as const; - -// Fields pertaining to the cases associated with the alert -const ALERT_CASE_IDS = `${ALERT_NAMESPACE}.case_ids` as const; // Fields pertaining to the rule associated with the alert -const ALERT_RULE_AUTHOR = `${ALERT_RULE_NAMESPACE}.author` as const; -const ALERT_RULE_CREATED_AT = `${ALERT_RULE_NAMESPACE}.created_at` as const; -const ALERT_RULE_CREATED_BY = `${ALERT_RULE_NAMESPACE}.created_by` as const; -const ALERT_RULE_DESCRIPTION = `${ALERT_RULE_NAMESPACE}.description` as const; -const ALERT_RULE_ENABLED = `${ALERT_RULE_NAMESPACE}.enabled` as const; const ALERT_RULE_EXCEPTIONS_LIST = `${ALERT_RULE_NAMESPACE}.exceptions_list` as const; -const ALERT_RULE_FROM = `${ALERT_RULE_NAMESPACE}.from` as const; -const ALERT_RULE_INTERVAL = `${ALERT_RULE_NAMESPACE}.interval` as const; -const ALERT_RULE_LICENSE = `${ALERT_RULE_NAMESPACE}.license` as const; const ALERT_RULE_NAMESPACE_FIELD = `${ALERT_RULE_NAMESPACE}.namespace` as const; -const ALERT_RULE_NOTE = `${ALERT_RULE_NAMESPACE}.note` as const; -const ALERT_RULE_REFERENCES = `${ALERT_RULE_NAMESPACE}.references` as const; -const ALERT_RULE_RULE_ID = `${ALERT_RULE_NAMESPACE}.rule_id` as const; -const ALERT_RULE_RULE_NAME_OVERRIDE = `${ALERT_RULE_NAMESPACE}.rule_name_override` as const; -const ALERT_RULE_TO = `${ALERT_RULE_NAMESPACE}.to` as const; -const ALERT_RULE_TYPE = `${ALERT_RULE_NAMESPACE}.type` as const; -const ALERT_RULE_UPDATED_AT = `${ALERT_RULE_NAMESPACE}.updated_at` as const; -const ALERT_RULE_UPDATED_BY = `${ALERT_RULE_NAMESPACE}.updated_by` as const; -const ALERT_RULE_VERSION = `${ALERT_RULE_NAMESPACE}.version` as const; // Fields pertaining to the threat tactic associated with the rule const ALERT_THREAT_FRAMEWORK = `${ALERT_RULE_THREAT_NAMESPACE}.framework` as const; @@ -186,36 +190,8 @@ export { ALERT_BUILDING_BLOCK_TYPE, ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, - ALERT_INSTANCE_ID, - ALERT_RISK_SCORE, - ALERT_WORKFLOW_REASON, - ALERT_WORKFLOW_USER, - ALERT_CASE_IDS, - ALERT_RULE_AUTHOR, - ALERT_RULE_CREATED_AT, - ALERT_RULE_CREATED_BY, - ALERT_RULE_DESCRIPTION, - ALERT_RULE_ENABLED, ALERT_RULE_EXCEPTIONS_LIST, - ALERT_RULE_FROM, - ALERT_RULE_INTERVAL, - ALERT_RULE_LICENSE, ALERT_RULE_NAMESPACE_FIELD, - ALERT_RULE_NOTE, - ALERT_RULE_REFERENCES, - ALERT_RULE_RULE_ID, - ALERT_RULE_RULE_NAME_OVERRIDE, - ALERT_RULE_TO, - ALERT_RULE_TYPE, - ALERT_RULE_UPDATED_AT, - ALERT_RULE_UPDATED_BY, - ALERT_RULE_VERSION, - ALERT_SEVERITY, - ALERT_SYSTEM_STATUS, - ECS_VERSION, - EVENT_ACTION, - EVENT_KIND, - EVENT_MODULE, ALERT_THREAT_FRAMEWORK, ALERT_THREAT_TACTIC_ID, ALERT_THREAT_TACTIC_NAME, @@ -226,14 +202,7 @@ export { ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_ID, ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_NAME, ALERT_THREAT_TECHNIQUE_SUBTECHNIQUE_REFERENCE, - ALERT_SUPPRESSION_TERMS, - ALERT_SUPPRESSION_FIELD, - ALERT_SUPPRESSION_VALUE, - ALERT_SUPPRESSION_START, - ALERT_SUPPRESSION_END, - ALERT_SUPPRESSION_DOCS_COUNT, - TAGS, - TIMESTAMP, + EVENT_MODULE, }; export type TechnicalRuleDataFieldName = ValuesType; diff --git a/packages/kbn-rule-data-utils/tsconfig.json b/packages/kbn-rule-data-utils/tsconfig.json index 5c94013fc2eaf..77352c4f44209 100644 --- a/packages/kbn-rule-data-utils/tsconfig.json +++ b/packages/kbn-rule-data-utils/tsconfig.json @@ -11,7 +11,7 @@ "**/*.ts" ], "kbn_references": [ - "@kbn/es-query" + "@kbn/es-query", ], "exclude": [ "target/**/*", diff --git a/tsconfig.base.json b/tsconfig.base.json index cff7037533bfe..6a11e26dda7ac 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -32,6 +32,8 @@ "@kbn/alerting-plugin/*": ["x-pack/plugins/alerting/*"], "@kbn/alerts": ["packages/kbn-alerts"], "@kbn/alerts/*": ["packages/kbn-alerts/*"], + "@kbn/alerts-as-data-utils": ["packages/kbn-alerts-as-data-utils"], + "@kbn/alerts-as-data-utils/*": ["packages/kbn-alerts-as-data-utils/*"], "@kbn/alerts-restricted-fixtures-plugin": ["x-pack/test/alerting_api_integration/common/plugins/alerts_restricted"], "@kbn/alerts-restricted-fixtures-plugin/*": ["x-pack/test/alerting_api_integration/common/plugins/alerts_restricted/*"], "@kbn/alerts-ui-shared": ["packages/kbn-alerts-ui-shared"], diff --git a/x-pack/plugins/alerting/common/alert_schema/field_maps/component_template_from_field_map.ts b/x-pack/plugins/alerting/common/alert_schema/field_maps/component_template_from_field_map.ts index b4cd25a4f4126..4fc36193a15d9 100644 --- a/x-pack/plugins/alerting/common/alert_schema/field_maps/component_template_from_field_map.ts +++ b/x-pack/plugins/alerting/common/alert_schema/field_maps/component_template_from_field_map.ts @@ -6,8 +6,8 @@ */ import { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; +import { type FieldMap } from '@kbn/alerts-as-data-utils'; import { mappingFromFieldMap } from './mapping_from_field_map'; -import { FieldMap } from './types'; export interface GetComponentTemplateFromFieldMapOpts { name: string; diff --git a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts index 2f2cac2367e8b..f5eeeb8ba6c35 100644 --- a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts +++ b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.test.ts @@ -4,9 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { alertFieldMap, legacyAlertFieldMap, type FieldMap } from '@kbn/alerts-as-data-utils'; import { mappingFromFieldMap } from './mapping_from_field_map'; -import { FieldMap } from './types'; -import { alertFieldMap } from './alert_field_map'; describe('mappingFromFieldMap', () => { const fieldMap: FieldMap = { @@ -118,6 +117,15 @@ describe('mappingFromFieldMap', () => { date_field: { type: 'date', }, + multifield_field: { + fields: { + text: { + type: 'match_only_text', + }, + }, + ignore_above: 1024, + type: 'keyword', + }, geopoint_field: { type: 'geo_point', }, @@ -131,15 +139,6 @@ describe('mappingFromFieldMap', () => { long_field: { type: 'long', }, - multifield_field: { - fields: { - text: { - type: 'match_only_text', - }, - }, - ignore_above: 1024, - type: 'keyword', - }, nested_array_field: { properties: { field1: { @@ -184,6 +183,9 @@ describe('mappingFromFieldMap', () => { expect(mappingFromFieldMap(alertFieldMap)).toEqual({ dynamic: 'strict', properties: { + '@timestamp': { + type: 'date', + }, kibana: { properties: { alert: { @@ -191,6 +193,9 @@ describe('mappingFromFieldMap', () => { action_group: { type: 'keyword', }, + case_ids: { + type: 'keyword', + }, duration: { properties: { us: { @@ -204,8 +209,18 @@ describe('mappingFromFieldMap', () => { flapping: { type: 'boolean', }, - id: { - type: 'keyword', + flapping_history: { + type: 'boolean', + }, + instance: { + properties: { + id: { + type: 'keyword', + }, + }, + }, + last_detected: { + type: 'date', }, reason: { type: 'keyword', @@ -229,8 +244,8 @@ describe('mappingFromFieldMap', () => { type: 'keyword', }, parameters: { - type: 'object', - enabled: false, + type: 'flattened', + ignore_above: 4096, }, producer: { type: 'keyword', @@ -274,6 +289,58 @@ describe('mappingFromFieldMap', () => { }, }, }); + expect(mappingFromFieldMap(legacyAlertFieldMap)).toEqual({ + dynamic: 'strict', + properties: { + kibana: { + properties: { + alert: { + properties: { + risk_score: { type: 'float' }, + rule: { + properties: { + author: { type: 'keyword' }, + created_at: { type: 'date' }, + created_by: { type: 'keyword' }, + description: { type: 'keyword' }, + enabled: { type: 'keyword' }, + from: { type: 'keyword' }, + interval: { type: 'keyword' }, + license: { type: 'keyword' }, + note: { type: 'keyword' }, + references: { type: 'keyword' }, + rule_id: { type: 'keyword' }, + rule_name_override: { type: 'keyword' }, + to: { type: 'keyword' }, + type: { type: 'keyword' }, + updated_at: { type: 'date' }, + updated_by: { type: 'keyword' }, + version: { type: 'keyword' }, + }, + }, + severity: { type: 'keyword' }, + suppression: { + properties: { + docs_count: { type: 'long' }, + end: { type: 'date' }, + terms: { + properties: { field: { type: 'keyword' }, value: { type: 'keyword' } }, + }, + start: { type: 'date' }, + }, + }, + system_status: { type: 'keyword' }, + workflow_reason: { type: 'keyword' }, + workflow_user: { type: 'keyword' }, + }, + }, + }, + }, + ecs: { properties: { version: { type: 'keyword' } } }, + event: { properties: { action: { type: 'keyword' }, kind: { type: 'keyword' } } }, + tags: { type: 'keyword' }, + }, + }); }); it('uses dynamic setting if specified', () => { diff --git a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts index 5a1de7a995b36..9d1db8e577aa5 100644 --- a/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts +++ b/x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts @@ -7,7 +7,7 @@ import type { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { set } from '@kbn/safer-lodash-set'; -import { FieldMap, MultiField } from './types'; +import type { FieldMap, MultiField } from '@kbn/alerts-as-data-utils'; export function mappingFromFieldMap( fieldMap: FieldMap, @@ -29,7 +29,6 @@ export function mappingFromFieldMap( fields.forEach((field) => { // eslint-disable-next-line @typescript-eslint/naming-convention const { name, required, array, multi_fields, ...rest } = field; - const mapped = multi_fields ? { ...rest, diff --git a/x-pack/plugins/alerting/common/alert_schema/field_maps/types.ts b/x-pack/plugins/alerting/common/alert_schema/field_maps/types.ts deleted file mode 100644 index b687cbfb0cf7d..0000000000000 --- a/x-pack/plugins/alerting/common/alert_schema/field_maps/types.ts +++ /dev/null @@ -1,29 +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 interface MultiField { - flat_name?: string; - name: string; - type: string; -} - -export interface FieldMap { - [key: string]: { - type: string; - required: boolean; - array?: boolean; - doc_values?: boolean; - enabled?: boolean; - format?: string; - ignore_above?: number; - index?: boolean; - multi_fields?: MultiField[]; - path?: string; - scaling_factor?: number; - dynamic?: boolean | string; - }; -} diff --git a/x-pack/plugins/alerting/common/alert_schema/index.ts b/x-pack/plugins/alerting/common/alert_schema/index.ts index acca43450fe34..cccb492b10e17 100644 --- a/x-pack/plugins/alerting/common/alert_schema/index.ts +++ b/x-pack/plugins/alerting/common/alert_schema/index.ts @@ -5,5 +5,5 @@ * 2.0. */ -export { alertFieldMap } from './field_maps/alert_field_map'; +export { mappingFromFieldMap } from './field_maps/mapping_from_field_map'; export { getComponentTemplateFromFieldMap } from './field_maps/component_template_from_field_map'; diff --git a/x-pack/plugins/alerting/common/index.ts b/x-pack/plugins/alerting/common/index.ts index fafadcdb99ee4..64e5a78d21e8d 100644 --- a/x-pack/plugins/alerting/common/index.ts +++ b/x-pack/plugins/alerting/common/index.ts @@ -24,6 +24,8 @@ export * from './parse_duration'; export * from './execution_log_types'; export * from './rule_snooze_type'; +export { mappingFromFieldMap, getComponentTemplateFromFieldMap } from './alert_schema'; + export interface AlertingFrameworkHealth { isSufficientlySecure: boolean; hasPermanentEncryptionKey: boolean; 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 82716f935c6b3..ca64faa7c51ea 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 @@ -6,9 +6,11 @@ */ import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; import { errors as EsErrors } from '@elastic/elasticsearch'; import { ReplaySubject, Subject } from 'rxjs'; import { AlertsService } from './alerts_service'; +import { IRuleTypeAlerts } from '../types'; let logger: ReturnType; const clusterClient = elasticsearchServiceMock.createClusterClient().asInternalUser; @@ -75,40 +77,52 @@ const IlmPutBody = { name: '.alerts-ilm-policy', }; -const getIndexTemplatePutBody = (context?: string) => ({ - name: `.alerts-${context ? context : 'test'}-default-template`, - body: { - index_patterns: [`.alerts-${context ? context : 'test'}-default-*`], - composed_of: [ - 'alerts-common-component-template', - `alerts-${context ? context : 'test'}-component-template`, - ], - template: { - settings: { - auto_expand_replicas: '0-1', - hidden: true, - 'index.lifecycle': { - name: '.alerts-ilm-policy', - rollover_alias: `.alerts-${context ? context : 'test'}-default`, +interface GetIndexTemplatePutBodyOpts { + context?: string; + useLegacyAlerts?: boolean; + useEcs?: boolean; +} +const getIndexTemplatePutBody = (opts?: GetIndexTemplatePutBodyOpts) => { + const context = opts ? opts.context : undefined; + const useLegacyAlerts = opts ? opts.useLegacyAlerts : undefined; + const useEcs = opts ? opts.useEcs : undefined; + return { + name: `.alerts-${context ? context : 'test'}-default-template`, + body: { + index_patterns: [`.alerts-${context ? context : 'test'}-default-*`], + composed_of: [ + `.alerts-${context ? context : 'test'}-mappings`, + ...(useLegacyAlerts ? ['.alerts-legacy-alert-mappings'] : []), + ...(useEcs ? ['.alerts-ecs-mappings'] : []), + '.alerts-framework-mappings', + ], + template: { + settings: { + auto_expand_replicas: '0-1', + hidden: true, + 'index.lifecycle': { + name: '.alerts-ilm-policy', + rollover_alias: `.alerts-${context ? context : 'test'}-default`, + }, + 'index.mapping.total_fields.limit': 2500, + }, + mappings: { + dynamic: false, }, - 'index.mapping.total_fields.limit': 2500, }, - mappings: { - dynamic: false, + _meta: { + managed: true, }, }, - _meta: { - managed: true, - }, - }, -}); + }; +}; -const TestRegistrationContext = { +const TestRegistrationContext: IRuleTypeAlerts = { context: 'test', fieldMap: { field: { type: 'keyword', required: false } }, }; -const AnotherRegistrationContext = { +const AnotherRegistrationContext: IRuleTypeAlerts = { context: 'another', fieldMap: { field: { type: 'keyword', required: false } }, }; @@ -145,10 +159,14 @@ describe('Alerts Service', () => { expect(alertsService.isInitialized()).toEqual(true); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(1); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('alerts-common-component-template'); + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); }); test('should log error and set initialized to false if adding ILM policy throws error', async () => { @@ -185,13 +203,105 @@ describe('Alerts Service', () => { expect(alertsService.isInitialized()).toEqual(false); expect(logger.error).toHaveBeenCalledWith( - `Error installing component template alerts-common-component-template - fail` + `Error installing component template .alerts-framework-mappings - fail` ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(1); }); + test('should update index template field limit and retry initialization if creating/updating common component template fails with field limit error', async () => { + clusterClient.cluster.putComponentTemplate.mockRejectedValueOnce( + new EsErrors.ResponseError( + elasticsearchClientMock.createApiResponse({ + statusCode: 400, + body: { + error: { + root_cause: [ + { + type: 'illegal_argument_exception', + reason: + 'updating component template [.alerts-ecs-mappings] results in invalid composable template [.alerts-security.alerts-default-index-template] after templates are merged', + }, + ], + type: 'illegal_argument_exception', + reason: + 'updating component template [.alerts-ecs-mappings] results in invalid composable template [.alerts-security.alerts-default-index-template] after templates are merged', + caused_by: { + type: 'illegal_argument_exception', + reason: + 'composable template [.alerts-security.alerts-default-index-template] template after composition with component templates [.alerts-ecs-mappings, .alerts-security.alerts-mappings, .alerts-technical-mappings] is invalid', + caused_by: { + type: 'illegal_argument_exception', + reason: + 'invalid composite mappings for [.alerts-security.alerts-default-index-template]', + caused_by: { + type: 'illegal_argument_exception', + reason: 'Limit of total fields [1900] has been exceeded', + }, + }, + }, + }, + }, + }) + ) + ); + const existingIndexTemplate = { + name: 'test-template', + index_template: { + index_patterns: ['test*'], + composed_of: ['.alerts-framework-mappings'], + template: { + settings: { + auto_expand_replicas: '0-1', + hidden: true, + 'index.lifecycle': { + name: '.alerts-ilm-policy', + rollover_alias: `.alerts-empty-default`, + }, + 'index.mapping.total_fields.limit': 1800, + }, + mappings: { + dynamic: false, + }, + }, + }, + }; + clusterClient.indices.getIndexTemplate.mockResolvedValueOnce({ + index_templates: [existingIndexTemplate], + }); + const alertsService = new AlertsService({ + logger, + elasticsearchClientPromise: Promise.resolve(clusterClient), + pluginStop$, + }); + + alertsService.initialize(); + await new Promise((r) => setTimeout(r, 50)); + + expect(alertsService.isInitialized()).toEqual(true); + expect(clusterClient.indices.getIndexTemplate).toHaveBeenCalledTimes(1); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(1); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ + name: existingIndexTemplate.name, + body: { + ...existingIndexTemplate.index_template, + template: { + ...existingIndexTemplate.index_template.template, + settings: { + ...existingIndexTemplate.index_template.template?.settings, + 'index.mapping.total_fields.limit': 2500, + }, + }, + }, + }); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); + // 3x for framework, legacy-alert and ecs mappings, then 1 extra time to update component template + // after updating index template field limit + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + }); + test('should install resources for contexts awaiting initialization when common resources are initialized', async () => { const alertsService = new AlertsService({ logger, @@ -214,20 +324,24 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - // 1x for common component template, 2x for context specific - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); + // 1x for framework component template, 1x for legacy alert, 1x for ecs, 2x for context specific + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(5); const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('alerts-common-component-template'); + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('alerts-another-component-template'); + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; - expect(componentTemplate3.name).toEqual('alerts-test-component-template'); + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-another-mappings'); + const componentTemplate5 = clusterClient.cluster.putComponentTemplate.mock.calls[4][0]; + expect(componentTemplate5.name).toEqual('.alerts-test-mappings'); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(2); expect(clusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( 1, - getIndexTemplatePutBody('another') + getIndexTemplatePutBody({ context: 'another' }) ); expect(clusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( 2, @@ -291,11 +405,15 @@ describe('Alerts Service', () => { expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('alerts-common-component-template'); + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; - expect(componentTemplate2.name).toEqual('alerts-test-component-template'); + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-test-mappings'); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( getIndexTemplatePutBody() @@ -318,7 +436,87 @@ describe('Alerts Service', () => { }); }); - test('should not install component template for context fieldMap is empty', async () => { + test('should correctly install resources for context when useLegacyAlerts is true', async () => { + alertsService.register({ ...TestRegistrationContext, useLegacyAlerts: true }); + await new Promise((r) => setTimeout(r, 50)); + expect(await alertsService.isContextInitialized(TestRegistrationContext.context)).toEqual( + true + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-test-mappings'); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( + getIndexTemplatePutBody({ useLegacyAlerts: true }) + ); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ + index: '.alerts-test-default-*', + }); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.alerts-test-default-000001', + body: { + aliases: { + '.alerts-test-default': { + is_write_index: true, + }, + }, + }, + }); + }); + + test('should correctly install resources for context when useEcs is true', async () => { + alertsService.register({ ...TestRegistrationContext, useEcs: true }); + await new Promise((r) => setTimeout(r, 50)); + expect(await alertsService.isContextInitialized(TestRegistrationContext.context)).toEqual( + true + ); + + expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); + + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); + const componentTemplate4 = clusterClient.cluster.putComponentTemplate.mock.calls[3][0]; + expect(componentTemplate4.name).toEqual('.alerts-test-mappings'); + + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith( + getIndexTemplatePutBody({ useEcs: true }) + ); + expect(clusterClient.indices.getAlias).toHaveBeenCalledWith({ + index: '.alerts-test-default-*', + }); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.simulateIndexTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(2); + expect(clusterClient.indices.create).toHaveBeenCalledWith({ + index: '.alerts-test-default-000001', + body: { + aliases: { + '.alerts-test-default': { + is_write_index: true, + }, + }, + }, + }); + }); + + test('should not install component template for context if fieldMap is empty', async () => { alertsService.register({ context: 'empty', fieldMap: {}, @@ -328,15 +526,19 @@ describe('Alerts Service', () => { expect(clusterClient.ilm.putLifecycle).toHaveBeenCalledWith(IlmPutBody); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(1); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); const componentTemplate1 = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate1.name).toEqual('alerts-common-component-template'); + expect(componentTemplate1.name).toEqual('.alerts-framework-mappings'); + const componentTemplate2 = clusterClient.cluster.putComponentTemplate.mock.calls[1][0]; + expect(componentTemplate2.name).toEqual('.alerts-legacy-alert-mappings'); + const componentTemplate3 = clusterClient.cluster.putComponentTemplate.mock.calls[2][0]; + expect(componentTemplate3.name).toEqual('.alerts-ecs-mappings'); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledWith({ name: `.alerts-empty-default-template`, body: { index_patterns: [`.alerts-empty-default-*`], - composed_of: ['alerts-common-component-template'], + composed_of: ['.alerts-framework-mappings'], template: { settings: { auto_expand_replicas: '0-1', @@ -410,7 +612,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); // putIndexTemplate is skipped but other operations are called as expected expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); @@ -443,7 +645,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); @@ -467,7 +669,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).not.toHaveBeenCalled(); @@ -491,7 +693,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); @@ -512,7 +714,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putSettings).not.toHaveBeenCalled(); @@ -535,7 +737,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -559,7 +761,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -581,7 +783,7 @@ describe('Alerts Service', () => { expect(logger.error).toHaveBeenCalledWith(`Failed to PUT mapping for alias alias_1: fail`); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -601,7 +803,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -640,7 +842,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -673,7 +875,7 @@ describe('Alerts Service', () => { ); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -695,7 +897,7 @@ describe('Alerts Service', () => { expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -730,7 +932,7 @@ describe('Alerts Service', () => { expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -766,7 +968,7 @@ describe('Alerts Service', () => { expect(logger.error).toHaveBeenCalledWith(`Error creating concrete write index - fail`); expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled(); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(clusterClient.indices.simulateTemplate).toHaveBeenCalled(); expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalled(); expect(clusterClient.indices.getAlias).toHaveBeenCalled(); @@ -810,7 +1012,7 @@ describe('Alerts Service', () => { alertsService.initialize(); await new Promise((r) => setTimeout(r, 150)); expect(alertsService.isInitialized()).toEqual(true); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(5); }); test('should retry updating index template for transient ES errors', async () => { 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 08643caf862f5..22cb9f4df1884 100644 --- a/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts +++ b/x-pack/plugins/alerting/server/alerts_service/alerts_service.ts @@ -13,8 +13,14 @@ import { import { get, isEmpty, isEqual } from 'lodash'; 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 { + alertFieldMap, + ecsFieldMap, + legacyAlertFieldMap, + type FieldMap, +} from '@kbn/alerts-as-data-utils'; +import { IndicesGetIndexTemplateIndexTemplateItem } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { asyncForEach } from '@kbn/std'; import { DEFAULT_ALERTS_ILM_POLICY_NAME, DEFAULT_ALERTS_ILM_POLICY, @@ -34,7 +40,9 @@ import { const TOTAL_FIELDS_LIMIT = 2500; const INSTALLATION_TIMEOUT = 20 * 60 * 1000; // 20 minutes - +const LEGACY_ALERT_CONTEXT = 'legacy-alert'; +export const ECS_CONTEXT = `ecs`; +export const ECS_COMPONENT_TEMPLATE_NAME = getComponentTemplateName(ECS_CONTEXT); interface AlertsServiceParams { logger: Logger; pluginStop$: Observable; @@ -107,6 +115,16 @@ export class AlertsService implements IAlertsService { const initFns = [ () => this.createOrUpdateIlmPolicy(esClient), () => this.createOrUpdateComponentTemplate(esClient, getComponentTemplate(alertFieldMap)), + () => + this.createOrUpdateComponentTemplate( + esClient, + getComponentTemplate(legacyAlertFieldMap, LEGACY_ALERT_CONTEXT) + ), + () => + this.createOrUpdateComponentTemplate( + esClient, + getComponentTemplate(ecsFieldMap, ECS_CONTEXT) + ), ]; for (const fn of initFns) { @@ -127,7 +145,8 @@ export class AlertsService implements IAlertsService { }); } - public register({ context, fieldMap }: IRuleTypeAlerts, timeoutMs?: number) { + public register(opts: IRuleTypeAlerts, timeoutMs?: number) { + const { context, fieldMap } = opts; // check whether this context has been registered before if (this.registeredContexts.has(context)) { const registeredFieldMap = this.registeredContexts.get(context); @@ -140,37 +159,54 @@ export class AlertsService implements IAlertsService { this.options.logger.info(`Registering resources for context "${context}".`); this.registeredContexts.set(context, fieldMap); - this.resourceInitializationHelper.add({ context, fieldMap }, timeoutMs); + this.resourceInitializationHelper.add(opts, timeoutMs); } - private async initializeContext({ context, fieldMap }: IRuleTypeAlerts, timeoutMs?: number) { + private async initializeContext( + { context, fieldMap, useEcs, useLegacyAlerts }: IRuleTypeAlerts, + timeoutMs?: number + ) { const esClient = await this.options.elasticsearchClientPromise; const indexTemplateAndPattern = getIndexTemplateAndPattern(context); - // Context specific initialization installs component template, index template and write index - // If fieldMap is empty, don't create context specific component template - const initFns = isEmpty(fieldMap) - ? [ - async () => - await this.createOrUpdateIndexTemplate(esClient, indexTemplateAndPattern, [ - getComponentTemplateName(), - ]), - async () => await this.createConcreteWriteIndex(esClient, indexTemplateAndPattern), - ] - : [ - async () => - await this.createOrUpdateComponentTemplate( - esClient, - getComponentTemplate(fieldMap, context) - ), - async () => - await this.createOrUpdateIndexTemplate(esClient, indexTemplateAndPattern, [ - getComponentTemplateName(), - getComponentTemplateName(context), - ]), - async () => await this.createConcreteWriteIndex(esClient, indexTemplateAndPattern), - ]; + let initFns: Array<() => Promise> = []; + + // List of component templates to reference + const componentTemplateRefs: string[] = []; + + // If fieldMap is not empty, create a context specific component template + if (!isEmpty(fieldMap)) { + const componentTemplate = getComponentTemplate(fieldMap, context); + initFns.push( + async () => await this.createOrUpdateComponentTemplate(esClient, componentTemplate) + ); + componentTemplateRefs.push(componentTemplate.name); + } + + // If useLegacy is set to true, add the legacy alert component template to the references + if (useLegacyAlerts) { + componentTemplateRefs.push(getComponentTemplateName(LEGACY_ALERT_CONTEXT)); + } + + // If useEcs is set to true, add the ECS component template to the references + if (useEcs) { + componentTemplateRefs.push(getComponentTemplateName(ECS_CONTEXT)); + } + + // Add framework component template to the references + componentTemplateRefs.push(getComponentTemplateName()); + + // Context specific initialization installs index template and write index + initFns = initFns.concat([ + async () => + await this.createOrUpdateIndexTemplate( + esClient, + indexTemplateAndPattern, + componentTemplateRefs + ), + async () => await this.createConcreteWriteIndex(esClient, indexTemplateAndPattern), + ]); for (const fn of initFns) { await this.installWithTimeout(async () => await fn(), timeoutMs); @@ -200,6 +236,62 @@ export class AlertsService implements IAlertsService { } } + private async getIndexTemplatesUsingComponentTemplate( + esClient: ElasticsearchClient, + componentTemplateName: string + ) { + // Get all index templates and filter down to just the ones referencing this component template + const { index_templates: indexTemplates } = await esClient.indices.getIndexTemplate(); + const indexTemplatesUsingComponentTemplate = (indexTemplates ?? []).filter( + (indexTemplate: IndicesGetIndexTemplateIndexTemplateItem) => + indexTemplate.index_template.composed_of.includes(componentTemplateName) + ); + await asyncForEach( + indexTemplatesUsingComponentTemplate, + async (template: IndicesGetIndexTemplateIndexTemplateItem) => { + await esClient.indices.putIndexTemplate({ + name: template.name, + body: { + ...template.index_template, + template: { + ...template.index_template.template, + settings: { + ...template.index_template.template?.settings, + 'index.mapping.total_fields.limit': TOTAL_FIELDS_LIMIT, + }, + }, + }, + }); + } + ); + } + + private async createOrUpdateComponentTemplateHelper( + esClient: ElasticsearchClient, + template: ClusterPutComponentTemplateRequest + ) { + try { + await esClient.cluster.putComponentTemplate(template); + } catch (error) { + const reason = error?.meta?.body?.error?.caused_by?.caused_by?.caused_by?.reason; + if (reason && reason.match(/Limit of total fields \[\d+\] has been exceeded/) != null) { + // This error message occurs when there is an index template using this component template + // that contains a field limit setting that using this component template exceeds + // Specifically, this can happen for the ECS component template when we add new fields + // to adhere to the ECS spec. Individual index templates specify field limits so if the + // number of new ECS fields pushes the composed mapping above the limit, this error will + // occur. We have to update the field limit inside the index template now otherwise we + // can never update the component template + await this.getIndexTemplatesUsingComponentTemplate(esClient, template.name); + + // Try to update the component template again + await esClient.cluster.putComponentTemplate(template); + } else { + throw error; + } + } + } + private async createOrUpdateComponentTemplate( esClient: ElasticsearchClient, template: ClusterPutComponentTemplateRequest @@ -207,9 +299,12 @@ export class AlertsService implements IAlertsService { this.options.logger.info(`Installing component template ${template.name}`); try { - await retryTransientEsErrors(() => esClient.cluster.putComponentTemplate(template), { - logger: this.options.logger, - }); + await retryTransientEsErrors( + () => this.createOrUpdateComponentTemplateHelper(esClient, template), + { + logger: this.options.logger, + } + ); } catch (err) { this.options.logger.error( `Error installing component template ${template.name} - ${err.message}` diff --git a/x-pack/plugins/rule_registry/common/field_map/types.ts b/x-pack/plugins/alerting/server/alerts_service/index.ts similarity index 52% rename from x-pack/plugins/rule_registry/common/field_map/types.ts rename to x-pack/plugins/alerting/server/alerts_service/index.ts index 52ee246375ad0..49247f3baa243 100644 --- a/x-pack/plugins/rule_registry/common/field_map/types.ts +++ b/x-pack/plugins/alerting/server/alerts_service/index.ts @@ -5,13 +5,9 @@ * 2.0. */ -export interface FieldMap { - [key: string]: { - type: string; - required?: boolean; - array?: boolean; - path?: string; - scaling_factor?: number; - dynamic?: 'strict' | boolean; - }; -} +export { + DEFAULT_ALERTS_ILM_POLICY, + DEFAULT_ALERTS_ILM_POLICY_NAME, +} from './default_lifecycle_policy'; +export { ECS_COMPONENT_TEMPLATE_NAME, ECS_CONTEXT } from './alerts_service'; +export { getComponentTemplate } from './types'; diff --git a/x-pack/plugins/alerting/server/alerts_service/types.ts b/x-pack/plugins/alerting/server/alerts_service/types.ts index db47a9a8e0015..aeb73cab6ffd2 100644 --- a/x-pack/plugins/alerting/server/alerts_service/types.ts +++ b/x-pack/plugins/alerting/server/alerts_service/types.ts @@ -6,11 +6,11 @@ */ import { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; -import { getComponentTemplateFromFieldMap } from '../../common/alert_schema'; -import { FieldMap } from '../../common/alert_schema/field_maps/types'; +import type { FieldMap } from '@kbn/alerts-as-data-utils'; +import { getComponentTemplateFromFieldMap } from '../../common'; export const getComponentTemplateName = (context?: string) => - `alerts-${context ? context : 'common'}-component-template`; + `.alerts-${context || 'framework'}-mappings`; export interface IIndexPatternString { template: string; @@ -40,5 +40,5 @@ export const getComponentTemplate = ( name: getComponentTemplateName(context), fieldMap, // set field limit slightly higher than actual number of fields - fieldLimit: 100, // Math.round(Object.keys(fieldMap).length * 1.5), + fieldLimit: Math.ceil(Object.keys(fieldMap).length / 1000) * 1000 + 500, }); diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts index a13b06596f557..6b5ad3012d8a9 100644 --- a/x-pack/plugins/alerting/server/index.ts +++ b/x-pack/plugins/alerting/server/index.ts @@ -56,7 +56,10 @@ export { export { DEFAULT_ALERTS_ILM_POLICY, DEFAULT_ALERTS_ILM_POLICY_NAME, -} from './alerts_service/default_lifecycle_policy'; + ECS_COMPONENT_TEMPLATE_NAME, + ECS_CONTEXT, + getComponentTemplate, +} from './alerts_service'; export const plugin = (initContext: PluginInitializerContext) => new AlertingPlugin(initContext); diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index e319f315440af..4997d9563d59e 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -22,6 +22,7 @@ import { } from '@kbn/core/server'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { SharePluginStart } from '@kbn/share-plugin/server'; +import { type FieldMap } from '@kbn/alerts-as-data-utils'; import { RuleTypeRegistry as OrigruleTypeRegistry } from './rule_type_registry'; import { PluginSetupContract, PluginStartContract } from './plugin'; import { RulesClient } from './rules_client'; @@ -51,7 +52,6 @@ import { SanitizedRule, } from '../common'; import { PublicAlertFactory } from './alert/create_alert_factory'; -import { FieldMap } from '../common/alert_schema/field_maps/types'; import { RulesSettingsFlappingProperties } from '../common/rules_settings'; export type WithoutQueryAndParams = Pick>; export type SpaceIdToNamespaceFunction = (spaceId?: string) => string | undefined; @@ -172,6 +172,8 @@ export interface IRuleTypeAlerts { context: string; namespace?: string; fieldMap: FieldMap; + useEcs?: boolean; + useLegacyAlerts?: boolean; } export interface RuleType< diff --git a/x-pack/plugins/alerting/tsconfig.json b/x-pack/plugins/alerting/tsconfig.json index 1f7017de59a2e..6fed19209ad12 100644 --- a/x-pack/plugins/alerting/tsconfig.json +++ b/x-pack/plugins/alerting/tsconfig.json @@ -39,6 +39,8 @@ "@kbn/data-views-plugin", "@kbn/share-plugin", "@kbn/safer-lodash-set", + "@kbn/alerts-as-data-utils", + "@kbn/core-elasticsearch-client-server-mocks", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index 86907fdd570be..5b98c8e437782 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -15,10 +15,10 @@ import { PluginInitializerContext, } from '@kbn/core/server'; import { isEmpty, mapValues } from 'lodash'; -import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_from_field_map'; import { experimentalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/experimental_rule_field_map'; import { Dataset } from '@kbn/rule-registry-plugin/server'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { APMConfig, APM_SERVER_FEATURE_ID } from '.'; import { APM_FEATURE, registerFeaturesUsage } from './feature'; import { registerApmRuleTypes } from './routes/alerts/register_apm_rule_types'; @@ -130,25 +130,32 @@ export class APMPlugin ...experimentalRuleFieldMap, [SERVICE_NAME]: { type: 'keyword', + required: false, }, [SERVICE_ENVIRONMENT]: { type: 'keyword', + required: false, }, [TRANSACTION_TYPE]: { type: 'keyword', + required: false, }, [PROCESSOR_EVENT]: { type: 'keyword', + required: false, }, [AGENT_NAME]: { type: 'keyword', + required: false, }, [SERVICE_LANGUAGE_NAME]: { type: 'keyword', + required: false, }, labels: { type: 'object', dynamic: true, + required: false, }, }, 'strict' diff --git a/x-pack/plugins/infra/server/services/rules/rule_data_client.ts b/x-pack/plugins/infra/server/services/rules/rule_data_client.ts index 1435f4812d16c..3a81f957e9314 100644 --- a/x-pack/plugins/infra/server/services/rules/rule_data_client.ts +++ b/x-pack/plugins/infra/server/services/rules/rule_data_client.ts @@ -6,11 +6,11 @@ */ import { CoreSetup, Logger } from '@kbn/core/server'; -import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_from_field_map'; import { experimentalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/experimental_rule_field_map'; import { Dataset, RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; -import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/rule-registry-plugin/common/assets'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; +import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/alerting-plugin/server'; import type { InfraFeatureId } from '../../../common/constants'; import { RuleRegistrationContext, RulesServiceStartDeps } from './types'; diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts index 98b21abbaefe5..39a69d7fa1666 100644 --- a/x-pack/plugins/observability/server/plugin.ts +++ b/x-pack/plugins/observability/server/plugin.ts @@ -18,10 +18,10 @@ import { Dataset, RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plu import { PluginSetupContract as FeaturesSetup } from '@kbn/features-plugin/server'; import { createUICapabilities } from '@kbn/cases-plugin/common'; import { experimentalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/experimental_rule_field_map'; -import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_from_field_map'; -import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/rule-registry-plugin/common/assets'; +import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/alerting-plugin/server'; import type { GuidedOnboardingPluginSetup } from '@kbn/guided-onboarding-plugin/server'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import { kubernetesGuideId, diff --git a/x-pack/plugins/rule_registry/common/assets.ts b/x-pack/plugins/rule_registry/common/assets.ts index a1df09df18a8f..1e8919a3a07e4 100644 --- a/x-pack/plugins/rule_registry/common/assets.ts +++ b/x-pack/plugins/rule_registry/common/assets.ts @@ -5,5 +5,4 @@ * 2.0. */ -export const TECHNICAL_COMPONENT_TEMPLATE_NAME = `technical-mappings`; -export const ECS_COMPONENT_TEMPLATE_NAME = `ecs-mappings`; +export const TECHNICAL_COMPONENT_TEMPLATE_NAME = `.alerts-technical-mappings`; diff --git a/x-pack/plugins/rule_registry/common/assets/component_templates/ecs_component_template.ts b/x-pack/plugins/rule_registry/common/assets/component_templates/ecs_component_template.ts index 8e956ba0004a2..8f30e07a0d9dc 100644 --- a/x-pack/plugins/rule_registry/common/assets/component_templates/ecs_component_template.ts +++ b/x-pack/plugins/rule_registry/common/assets/component_templates/ecs_component_template.ts @@ -5,7 +5,7 @@ * 2.0. */ import { merge } from 'lodash'; -import { mappingFromFieldMap } from '../../mapping_from_field_map'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { ClusterPutComponentTemplateBody } from '../../types'; import { ecsFieldMap } from '../field_maps/ecs_field_map'; import { technicalRuleFieldMap } from '../field_maps/technical_rule_field_map'; diff --git a/x-pack/plugins/rule_registry/common/assets/component_templates/technical_component_template.ts b/x-pack/plugins/rule_registry/common/assets/component_templates/technical_component_template.ts index e110be339d0a0..1315d7f0d1b58 100644 --- a/x-pack/plugins/rule_registry/common/assets/component_templates/technical_component_template.ts +++ b/x-pack/plugins/rule_registry/common/assets/component_templates/technical_component_template.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { mappingFromFieldMap } from '../../mapping_from_field_map'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { ClusterPutComponentTemplateBody } from '../../types'; import { technicalRuleFieldMap } from '../field_maps/technical_rule_field_map'; diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.test.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.test.ts index 4e2d591bf88bd..3a6dbc4f20982 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.test.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.test.ts @@ -13,10 +13,12 @@ it('matches snapshot', () => { expect(experimentalRuleFieldMap).toMatchInlineSnapshot(` Object { "kibana.alert.evaluation.threshold": Object { + "required": false, "scaling_factor": 100, "type": "scaled_float", }, "kibana.alert.evaluation.value": Object { + "required": false, "scaling_factor": 100, "type": "scaled_float", }, diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.ts index 92f93015309c0..3859ebe6df9b6 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/experimental_rule_field_map.ts @@ -8,8 +8,12 @@ import * as Fields from '../../technical_rule_data_field_names'; export const experimentalRuleFieldMap = { - [Fields.ALERT_EVALUATION_THRESHOLD]: { type: 'scaled_float', scaling_factor: 100 }, - [Fields.ALERT_EVALUATION_VALUE]: { type: 'scaled_float', scaling_factor: 100 }, + [Fields.ALERT_EVALUATION_THRESHOLD]: { + type: 'scaled_float', + scaling_factor: 100, + required: false, + }, + [Fields.ALERT_EVALUATION_VALUE]: { type: 'scaled_float', scaling_factor: 100, required: false }, } as const; export type ExperimentalRuleFieldMap = typeof experimentalRuleFieldMap; diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts index e7d39a71a1d6d..7c2cc7c2a02af 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.test.ts @@ -43,15 +43,27 @@ it('matches snapshot', () => { "type": "keyword", }, "kibana.alert.duration.us": Object { + "array": false, + "required": false, "type": "long", }, "kibana.alert.end": Object { + "array": false, + "required": false, "type": "date", }, "kibana.alert.flapping": Object { + "array": false, + "required": false, + "type": "boolean", + }, + "kibana.alert.flapping_history": Object { + "array": true, + "required": false, "type": "boolean", }, "kibana.alert.instance.id": Object { + "array": false, "required": true, "type": "keyword", }, @@ -81,6 +93,7 @@ it('matches snapshot', () => { "type": "keyword", }, "kibana.alert.rule.consumer": Object { + "array": false, "required": true, "type": "keyword", }, @@ -135,10 +148,13 @@ it('matches snapshot', () => { "type": "keyword", }, "kibana.alert.rule.parameters": Object { + "array": false, "ignore_above": 4096, + "required": false, "type": "flattened", }, "kibana.alert.rule.producer": Object { + "array": false, "required": true, "type": "keyword", }, @@ -158,6 +174,7 @@ it('matches snapshot', () => { "type": "keyword", }, "kibana.alert.rule.rule_type_id": Object { + "array": false, "required": true, "type": "keyword", }, @@ -197,12 +214,17 @@ it('matches snapshot', () => { "type": "keyword", }, "kibana.alert.severity": Object { + "array": false, + "required": false, "type": "keyword", }, "kibana.alert.start": Object { + "array": false, + "required": false, "type": "date", }, "kibana.alert.status": Object { + "array": false, "required": true, "type": "keyword", }, @@ -237,10 +259,13 @@ it('matches snapshot', () => { "type": "keyword", }, "kibana.alert.time_range": Object { + "array": false, "format": "epoch_millis||strict_date_optional_time", + "required": false, "type": "date_range", }, "kibana.alert.uuid": Object { + "array": false, "required": true, "type": "keyword", }, diff --git a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts index 32d1b45e44cad..ef476f468544b 100644 --- a/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts +++ b/x-pack/plugins/rule_registry/common/assets/field_maps/technical_rule_field_map.ts @@ -5,225 +5,12 @@ * 2.0. */ +import { alertFieldMap, legacyAlertFieldMap } from '@kbn/alerts-as-data-utils'; import { pickWithPatterns } from '../../pick_with_patterns'; -import * as Fields from '../../technical_rule_data_field_names'; -import { ecsFieldMap } from './ecs_field_map'; export const technicalRuleFieldMap = { - ...pickWithPatterns( - ecsFieldMap, - Fields.TIMESTAMP, - Fields.EVENT_KIND, - Fields.EVENT_ACTION, - Fields.TAGS - ), - [Fields.ALERT_RULE_PARAMETERS]: { type: 'flattened', ignore_above: 4096 }, - [Fields.ALERT_RULE_TYPE_ID]: { type: 'keyword', required: true }, - [Fields.ALERT_RULE_CONSUMER]: { type: 'keyword', required: true }, - [Fields.ALERT_RULE_PRODUCER]: { type: 'keyword', required: true }, - [Fields.SPACE_IDS]: { type: 'keyword', array: true, required: true }, - [Fields.ALERT_UUID]: { type: 'keyword', required: true }, - [Fields.ALERT_INSTANCE_ID]: { type: 'keyword', required: true }, - [Fields.ALERT_START]: { type: 'date' }, - [Fields.ALERT_TIME_RANGE]: { - type: 'date_range', - format: 'epoch_millis||strict_date_optional_time', - }, - [Fields.ALERT_END]: { type: 'date' }, - [Fields.ALERT_DURATION]: { type: 'long' }, - [Fields.ALERT_SEVERITY]: { type: 'keyword' }, - [Fields.ALERT_STATUS]: { type: 'keyword', required: true }, - [Fields.ALERT_FLAPPING]: { type: 'boolean' }, - [Fields.VERSION]: { - type: 'version', - array: false, - required: false, - }, - [Fields.ECS_VERSION]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RISK_SCORE]: { - type: 'float', - array: false, - required: false, - }, - [Fields.ALERT_WORKFLOW_STATUS]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_WORKFLOW_USER]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_WORKFLOW_REASON]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_SYSTEM_STATUS]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_ACTION_GROUP]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_REASON]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_CASE_IDS]: { - type: 'keyword', - array: true, - required: false, - }, - [Fields.ALERT_RULE_AUTHOR]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_CATEGORY]: { - type: 'keyword', - array: false, - required: true, - }, - [Fields.ALERT_RULE_UUID]: { - type: 'keyword', - array: false, - required: true, - }, - [Fields.ALERT_RULE_CREATED_AT]: { - type: 'date', - array: false, - required: false, - }, - [Fields.ALERT_RULE_CREATED_BY]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_DESCRIPTION]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_ENABLED]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_EXECUTION_UUID]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_FROM]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_INTERVAL]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_LICENSE]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_NAME]: { - type: 'keyword', - array: false, - required: true, - }, - [Fields.ALERT_RULE_NOTE]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_REFERENCES]: { - type: 'keyword', - array: true, - required: false, - }, - [Fields.ALERT_RULE_RULE_ID]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_RULE_NAME_OVERRIDE]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_TAGS]: { - type: 'keyword', - array: true, - required: false, - }, - [Fields.ALERT_RULE_TO]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_TYPE]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_UPDATED_AT]: { - type: 'date', - array: false, - required: false, - }, - [Fields.ALERT_RULE_UPDATED_BY]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_RULE_VERSION]: { - type: 'keyword', - array: false, - required: false, - }, - [Fields.ALERT_SUPPRESSION_FIELD]: { - type: 'keyword', - array: true, - required: false, - }, - [Fields.ALERT_SUPPRESSION_VALUE]: { - type: 'keyword', - array: true, - required: false, - }, - [Fields.ALERT_SUPPRESSION_START]: { - type: 'date', - array: false, - required: false, - }, - [Fields.ALERT_SUPPRESSION_END]: { - type: 'date', - array: false, - required: false, - }, - [Fields.ALERT_SUPPRESSION_DOCS_COUNT]: { - type: 'long', - array: false, - required: false, - }, - [Fields.ALERT_LAST_DETECTED]: { - type: 'date', - array: false, - required: false, - }, + ...pickWithPatterns(alertFieldMap, '*'), + ...pickWithPatterns(legacyAlertFieldMap, '*'), } as const; export type TechnicalRuleFieldMap = typeof technicalRuleFieldMap; diff --git a/x-pack/plugins/rule_registry/common/field_map/index.ts b/x-pack/plugins/rule_registry/common/field_map/index.ts index fac8575b8af48..e64ba5823e673 100644 --- a/x-pack/plugins/rule_registry/common/field_map/index.ts +++ b/x-pack/plugins/rule_registry/common/field_map/index.ts @@ -7,4 +7,3 @@ export * from './merge_field_maps'; export * from './runtime_type_from_fieldmap'; -export * from './types'; diff --git a/x-pack/plugins/rule_registry/common/field_map/merge_field_maps.ts b/x-pack/plugins/rule_registry/common/field_map/merge_field_maps.ts index 124de243352ea..701bab82855d4 100644 --- a/x-pack/plugins/rule_registry/common/field_map/merge_field_maps.ts +++ b/x-pack/plugins/rule_registry/common/field_map/merge_field_maps.ts @@ -4,7 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { FieldMap } from './types'; + +import type { FieldMap } from '@kbn/alerts-as-data-utils'; export function mergeFieldMaps( first: T1, diff --git a/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.test.ts b/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.test.ts index 8ee71356ef706..0b724150f0dcc 100644 --- a/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.test.ts +++ b/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.test.ts @@ -8,11 +8,11 @@ import { runtimeTypeFromFieldMap } from './runtime_type_from_fieldmap'; describe('runtimeTypeFromFieldMap', () => { const fieldmapRt = runtimeTypeFromFieldMap({ - keywordField: { type: 'keyword' }, - longField: { type: 'long' }, - booleanField: { type: 'boolean' }, + keywordField: { type: 'keyword', required: false }, + longField: { type: 'long', required: false }, + booleanField: { type: 'boolean', required: false }, requiredKeywordField: { type: 'keyword', required: true }, - multiKeywordField: { type: 'keyword', array: true }, + multiKeywordField: { type: 'keyword', array: true, required: false }, } as const); it('accepts both singular and array fields', () => { diff --git a/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.ts b/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.ts index feb59f88abc7b..93e182e53af63 100644 --- a/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.ts +++ b/x-pack/plugins/rule_registry/common/field_map/runtime_type_from_fieldmap.ts @@ -8,7 +8,7 @@ import { Optional } from 'utility-types'; import { mapValues, pickBy } from 'lodash'; import { either } from 'fp-ts/lib/Either'; import * as t from 'io-ts'; -import { FieldMap } from './types'; +import type { FieldMap } from '@kbn/alerts-as-data-utils'; const NumberFromString = new t.Type( 'NumberFromString', diff --git a/x-pack/plugins/rule_registry/common/mapping_from_field_map.ts b/x-pack/plugins/rule_registry/common/mapping_from_field_map.ts deleted file mode 100644 index 1b66496bee19b..0000000000000 --- a/x-pack/plugins/rule_registry/common/mapping_from_field_map.ts +++ /dev/null @@ -1,36 +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 type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { set } from '@kbn/safer-lodash-set'; -import { FieldMap } from './field_map/types'; - -export function mappingFromFieldMap( - fieldMap: FieldMap, - dynamic: 'strict' | boolean -): estypes.MappingTypeMapping { - const mappings = { - dynamic, - properties: {}, - }; - - const fields = Object.keys(fieldMap).map((key) => { - const field = fieldMap[key]; - return { - name: key, - ...field, - }; - }); - - fields.forEach((field) => { - const { name, required, array, ...rest } = field; - - set(mappings.properties, field.name.split('.').join('.properties.'), rest); - }); - - return mappings; -} 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 b63fb2aae83d0..083c4d08d4253 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 @@ -12,11 +12,9 @@ import { AlertConsumers } from '@kbn/rule-data-utils'; import { Dataset } from './index_options'; import { IndexInfo } from './index_info'; +import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/alerting-plugin/server'; import { elasticsearchServiceMock, ElasticsearchClientMock } from '@kbn/core/server/mocks'; -import { - ECS_COMPONENT_TEMPLATE_NAME, - TECHNICAL_COMPONENT_TEMPLATE_NAME, -} from '../../common/assets'; +import { TECHNICAL_COMPONENT_TEMPLATE_NAME } from '../../common/assets'; describe('resourceInstaller', () => { let pluginStop$: Subject; @@ -82,15 +80,11 @@ describe('resourceInstaller', () => { it('should install common resources', 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, + getResourceName: jest.fn(), getClusterClient, areFrameworkAlertsEnabled: false, pluginStop$, @@ -102,26 +96,22 @@ describe('resourceInstaller', () => { expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( 1, - expect.objectContaining({ name: TECHNICAL_COMPONENT_TEMPLATE_NAME }) + expect.objectContaining({ name: ECS_COMPONENT_TEMPLATE_NAME }) ); expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( 2, - expect.objectContaining({ name: ECS_COMPONENT_TEMPLATE_NAME }) + expect.objectContaining({ name: TECHNICAL_COMPONENT_TEMPLATE_NAME }) ); }); - it('should install common resources when framework alerts are enabled', async () => { + it('should install subset of 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, + getResourceName: jest.fn(), getClusterClient, areFrameworkAlertsEnabled: true, pluginStop$, @@ -131,15 +121,12 @@ describe('resourceInstaller', () => { // ILM policy should be handled by framework expect(mockClusterClient.ilm.putLifecycle).not.toHaveBeenCalled(); - expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2); + // ECS component template should be handled by framework + expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(1); 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(); 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 6af288e57a4a0..59c74b81712d8 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 @@ -15,18 +15,16 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { 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'; +} from '@kbn/alerting-plugin/server'; +import { 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 type { IndexInfo } from './index_info'; const INSTALLATION_TIMEOUT = 20 * 60 * 1000; // 20 minutes -const TOTAL_FIELDS_LIMIT = 1900; +const TOTAL_FIELDS_LIMIT = 2500; interface ConstructorOptions { getResourceName(relativeName: string): string; getClusterClient: () => Promise; @@ -98,7 +96,7 @@ export class ResourceInstaller { */ public async installCommonResources(): Promise { await this.installWithTimeout('common resources shared between all indices', async () => { - const { getResourceName, logger, areFrameworkAlertsEnabled } = this.options; + const { logger, areFrameworkAlertsEnabled } = this.options; try { // We can install them in parallel @@ -112,16 +110,15 @@ export class ResourceInstaller { name: DEFAULT_ALERTS_ILM_POLICY_NAME, body: DEFAULT_ALERTS_ILM_POLICY, }), + this.createOrUpdateComponentTemplate({ + name: ECS_COMPONENT_TEMPLATE_NAME, + body: ecsComponentTemplate, + }), ]), this.createOrUpdateComponentTemplate({ - name: getResourceName(TECHNICAL_COMPONENT_TEMPLATE_NAME), + name: TECHNICAL_COMPONENT_TEMPLATE_NAME, body: technicalComponentTemplate, }), - - this.createOrUpdateComponentTemplate({ - name: getResourceName(ECS_COMPONENT_TEMPLATE_NAME), - body: ecsComponentTemplate, - }), ]); } catch (err) { logger.error( @@ -315,7 +312,7 @@ export class ResourceInstaller { } private async installNamespacedIndexTemplate(indexInfo: IndexInfo, namespace: string) { - const { logger, getResourceName } = this.options; + const { logger } = this.options; const { componentTemplateRefs, componentTemplates, @@ -329,8 +326,7 @@ export class ResourceInstaller { logger.debug(`Installing index template for ${primaryNamespacedAlias}`); - const technicalComponentNames = [getResourceName(TECHNICAL_COMPONENT_TEMPLATE_NAME)]; - const referencedComponentNames = componentTemplateRefs.map((ref) => getResourceName(ref)); + const technicalComponentNames = [TECHNICAL_COMPONENT_TEMPLATE_NAME]; const ownComponentNames = componentTemplates.map((template) => indexInfo.getComponentTemplateName(template.name) ); @@ -365,11 +361,7 @@ export class ResourceInstaller { // - then we include own component templates registered with this index // - finally, we include technical component templates to make sure the index gets all the // mappings and settings required by all Kibana plugins using rule registry to work properly - composed_of: [ - ...referencedComponentNames, - ...ownComponentNames, - ...technicalComponentNames, - ], + composed_of: [...componentTemplateRefs, ...ownComponentNames, ...technicalComponentNames], template: { settings: { diff --git a/x-pack/plugins/rule_registry/tsconfig.json b/x-pack/plugins/rule_registry/tsconfig.json index a3a2a6d373b2b..1bb9b96e6aa92 100644 --- a/x-pack/plugins/rule_registry/tsconfig.json +++ b/x-pack/plugins/rule_registry/tsconfig.json @@ -16,7 +16,6 @@ "@kbn/data-plugin", "@kbn/alerting-plugin", "@kbn/security-plugin", - "@kbn/safer-lodash-set", "@kbn/rule-data-utils", "@kbn/es-query", "@kbn/data-views-plugin", @@ -32,6 +31,7 @@ "@kbn/logging", "@kbn/securitysolution-io-ts-utils", "@kbn/share-plugin", + "@kbn/alerts-as-data-utils", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 5d76046edd7c6..cbc595a22bbf0 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -21,10 +21,10 @@ import type { Logger } from '@kbn/core/server'; import { SavedObjectsClient } from '@kbn/core/server'; import type { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/rule-registry-plugin/common/assets'; -import type { FieldMap } from '@kbn/rule-registry-plugin/common/field_map'; +import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/alerting-plugin/server'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; +import type { FieldMap } from '@kbn/alerts-as-data-utils'; import { technicalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/technical_rule_field_map'; -import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_from_field_map'; import type { IRuleDataClient } from '@kbn/rule-registry-plugin/server'; import { Dataset } from '@kbn/rule-registry-plugin/server'; import type { ListPluginSetup } from '@kbn/lists-plugin/server'; @@ -220,6 +220,7 @@ export class Plugin implements ISecuritySolutionPlugin { Object.entries(aadFieldConversion).forEach(([key, value]) => { aliasesFieldMap[key] = { type: 'alias', + required: false, path: value, }; }); diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index 6f831e7633dbb..dada95f662bbd 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -141,5 +141,6 @@ "@kbn/securitysolution-ecs", "@kbn/cell-actions", "@kbn/shared-ux-router", + "@kbn/alerts-as-data-utils", ] } diff --git a/x-pack/plugins/synthetics/common/rules/uptime_rule_field_map.ts b/x-pack/plugins/synthetics/common/rules/uptime_rule_field_map.ts index ff69d3a5e6e7f..be097ed8d8268 100644 --- a/x-pack/plugins/synthetics/common/rules/uptime_rule_field_map.ts +++ b/x-pack/plugins/synthetics/common/rules/uptime_rule_field_map.ts @@ -9,48 +9,62 @@ export const uptimeRuleFieldMap = { // common fields 'monitor.id': { type: 'keyword', + required: false, }, 'url.full': { type: 'keyword', + required: false, }, 'observer.geo.name': { type: 'keyword', + required: false, }, // monitor status alert fields 'error.message': { type: 'text', + required: false, }, 'agent.name': { type: 'keyword', + required: false, }, 'monitor.name': { type: 'keyword', + required: false, }, 'monitor.type': { type: 'keyword', + required: false, }, // tls alert fields 'tls.server.x509.issuer.common_name': { type: 'keyword', + required: false, }, 'tls.server.x509.subject.common_name': { type: 'keyword', + required: false, }, 'tls.server.x509.not_after': { type: 'date', + required: false, }, 'tls.server.x509.not_before': { type: 'date', + required: false, }, 'tls.server.hash.sha256': { type: 'keyword', + required: false, }, // anomaly alert fields 'anomaly.start': { type: 'date', + required: false, }, 'anomaly.bucket_span.minutes': { type: 'keyword', + required: false, }, } as const; diff --git a/x-pack/plugins/synthetics/server/plugin.ts b/x-pack/plugins/synthetics/server/plugin.ts index 598fdd18b229b..c6120c70c3818 100644 --- a/x-pack/plugins/synthetics/server/plugin.ts +++ b/x-pack/plugins/synthetics/server/plugin.ts @@ -13,7 +13,7 @@ import { SavedObjectsClient, SavedObjectsClientContract, } from '@kbn/core/server'; -import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_from_field_map'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { experimentalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/experimental_rule_field_map'; import { Dataset } from '@kbn/rule-registry-plugin/server'; import { SyntheticsMonitorClient } from './synthetics_service/synthetics_monitor/synthetics_monitor_client'; 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 3ac2fdb93add8..ad2c33b079b0a 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 @@ -5,20 +5,24 @@ * 2.0. */ -import { alertFieldMap } from '@kbn/alerting-plugin/common/alert_schema'; -import { mappingFromFieldMap } from '@kbn/alerting-plugin/common/alert_schema/field_maps/mapping_from_field_map'; +import { alertFieldMap, ecsFieldMap, legacyAlertFieldMap } from '@kbn/alerts-as-data-utils'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertsAsDataTest({ getService }: FtrProviderContext) { const es = getService('es'); - const commonFrameworkMappings = mappingFromFieldMap(alertFieldMap, 'strict'); + const frameworkMappings = mappingFromFieldMap(alertFieldMap, 'strict'); + const legacyAlertMappings = mappingFromFieldMap(legacyAlertFieldMap, 'strict'); + const ecsMappings = mappingFromFieldMap(ecsFieldMap, 'strict'); describe('alerts as data', () => { it('should install common alerts as data resources on startup', async () => { const ilmPolicyName = '.alerts-ilm-policy'; - const componentTemplateName = 'alerts-common-component-template'; + const frameworkComponentTemplateName = '.alerts-framework-mappings'; + const legacyComponentTemplateName = '.alerts-legacy-alert-mappings'; + const ecsComponentTemplateName = '.alerts-ecs-mappings'; const commonIlmPolicy = await es.ilm.getLifecycle({ name: ilmPolicyName, @@ -41,23 +45,65 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex }, }); - const { component_templates: componentTemplates } = await es.cluster.getComponentTemplate({ - name: componentTemplateName, + const { component_templates: componentTemplates1 } = await es.cluster.getComponentTemplate({ + name: frameworkComponentTemplateName, }); - expect(componentTemplates.length).to.eql(1); - const commonComponentTemplate = componentTemplates[0]; + expect(componentTemplates1.length).to.eql(1); + const frameworkComponentTemplate = componentTemplates1[0]; + + expect(frameworkComponentTemplate.name).to.eql(frameworkComponentTemplateName); + expect(frameworkComponentTemplate.component_template.template.mappings).to.eql( + frameworkMappings + ); + expect(frameworkComponentTemplate.component_template.template.settings).to.eql({ + index: { + number_of_shards: 1, + mapping: { + total_fields: { + limit: 1500, + }, + }, + }, + }); + + const { component_templates: componentTemplates2 } = await es.cluster.getComponentTemplate({ + name: legacyComponentTemplateName, + }); + + expect(componentTemplates2.length).to.eql(1); + const legacyComponentTemplate = componentTemplates2[0]; - expect(commonComponentTemplate.name).to.eql(componentTemplateName); - expect(commonComponentTemplate.component_template.template.mappings).to.eql( - commonFrameworkMappings + expect(legacyComponentTemplate.name).to.eql(legacyComponentTemplateName); + expect(legacyComponentTemplate.component_template.template.mappings).to.eql( + legacyAlertMappings ); - expect(commonComponentTemplate.component_template.template.settings).to.eql({ + expect(legacyComponentTemplate.component_template.template.settings).to.eql({ + index: { + number_of_shards: 1, + mapping: { + total_fields: { + limit: 1500, + }, + }, + }, + }); + + const { component_templates: componentTemplates3 } = await es.cluster.getComponentTemplate({ + name: ecsComponentTemplateName, + }); + + expect(componentTemplates3.length).to.eql(1); + const ecsComponentTemplate = componentTemplates3[0]; + + expect(ecsComponentTemplate.name).to.eql(ecsComponentTemplateName); + expect(ecsComponentTemplate.component_template.template.mappings).to.eql(ecsMappings); + expect(ecsComponentTemplate.component_template.template.settings).to.eql({ index: { number_of_shards: 1, mapping: { total_fields: { - limit: 100, + limit: 2500, }, }, }, @@ -65,7 +111,7 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex }); it('should install context specific alerts as data resources on startup', async () => { - const componentTemplateName = 'alerts-test.always-firing-component-template'; + const componentTemplateName = '.alerts-test.always-firing-mappings'; const indexTemplateName = '.alerts-test.always-firing-default-template'; const indexName = '.alerts-test.always-firing-default-000001'; const contextSpecificMappings = { @@ -98,7 +144,7 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex number_of_shards: 1, mapping: { total_fields: { - limit: 100, + limit: 1500, }, }, }, @@ -114,8 +160,8 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex '.alerts-test.always-firing-default-*', ]); expect(contextIndexTemplate.index_template.composed_of).to.eql([ - 'alerts-common-component-template', - 'alerts-test.always-firing-component-template', + '.alerts-test.always-firing-mappings', + '.alerts-framework-mappings', ]); expect(contextIndexTemplate.index_template.template!.mappings).to.eql({ dynamic: false, @@ -150,7 +196,7 @@ export default function createAlertsAsDataTest({ getService }: FtrProviderContex dynamic: 'false', properties: { ...contextSpecificMappings, - ...commonFrameworkMappings.properties, + ...frameworkMappings.properties, }, }); 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 02765aa8c2a77..b62cf7b39965c 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 @@ -10,7 +10,7 @@ import type { ElasticsearchClient, Logger, LogMeta } from '@kbn/core/server'; import sinon from 'sinon'; import { v4 as uuidv4 } from 'uuid'; import expect from '@kbn/expect'; -import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_from_field_map'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { AlertConsumers, ALERT_REASON, 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 dc5752417bfb4..10351fc6cf2ef 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 @@ -9,7 +9,7 @@ import { type Subject, ReplaySubject } from 'rxjs'; import type { ElasticsearchClient, Logger, LogMeta } from '@kbn/core/server'; import sinon from 'sinon'; import expect from '@kbn/expect'; -import { mappingFromFieldMap } from '@kbn/rule-registry-plugin/common/mapping_from_field_map'; +import { mappingFromFieldMap } from '@kbn/alerting-plugin/common'; import { AlertConsumers, ALERT_REASON, diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 476b6223b9591..be736ec73fd0d 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -115,6 +115,7 @@ "@kbn/cloud-security-posture-plugin", "@kbn/cloud-integration-saml-provider-plugin", "@kbn/security-api-integration-helpers", + "@kbn/alerts-as-data-utils", "@kbn/discover-plugin", ] } diff --git a/yarn.lock b/yarn.lock index f2901f09ceaec..c662b59d24299 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2785,6 +2785,10 @@ version "0.0.0" uid "" +"@kbn/alerts-as-data-utils@link:packages/kbn-alerts-as-data-utils": + version "0.0.0" + uid "" + "@kbn/alerts-restricted-fixtures-plugin@link:x-pack/test/alerting_api_integration/common/plugins/alerts_restricted": version "0.0.0" uid "" From 6f074c7fcb757d4537eae799e41167eccb96503f Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 27 Feb 2023 19:32:29 +0000 Subject: [PATCH 024/131] skip flaky suite --- .../public/components/description/description_wrapper.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cases/public/components/description/description_wrapper.test.tsx b/x-pack/plugins/cases/public/components/description/description_wrapper.test.tsx index b4fb76b8dc94b..40fcf91ffe1fa 100644 --- a/x-pack/plugins/cases/public/components/description/description_wrapper.test.tsx +++ b/x-pack/plugins/cases/public/components/description/description_wrapper.test.tsx @@ -33,7 +33,8 @@ jest.mock('../../common/lib/kibana'); const useUpdateCommentMock = useUpdateComment as jest.Mock; const patchComment = jest.fn(); -describe(`DescriptionWrapper`, () => { +// FLAKY: +describe.skip(`DescriptionWrapper`, () => { const sampleData = { content: 'what a great comment update', }; From 4b90731863a5c101ed348d6a4313f7136fb96e55 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 27 Feb 2023 20:28:13 +0000 Subject: [PATCH 025/131] skip flaky suite (#152176) --- .../sections/alerts_table/bulk_actions/bulk_actions.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/bulk_actions/bulk_actions.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/bulk_actions/bulk_actions.test.tsx index 27188fab622c9..3dc86c5522e8e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/bulk_actions/bulk_actions.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/bulk_actions/bulk_actions.test.tsx @@ -584,7 +584,8 @@ describe('AlertsTable.BulkActions', () => { }); }); - describe('and executing a bulk action', () => { + // FLAKY: https://github.com/elastic/kibana/issues/152176 + describe.skip('and executing a bulk action', () => { it('should return the are all selected flag set to true', async () => { const mockedFn = jest.fn(); const props = { From 63dd07c00c623c57055257505b6360baa871e0f7 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 27 Feb 2023 20:28:57 +0000 Subject: [PATCH 026/131] skip flaky suite (#152268) --- .../rules_list/components/rules_list_bulk_edit.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 40204483e430b..e059bab845116 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 @@ -156,7 +156,8 @@ describe('Rules list Bulk Edit', () => { queryClient.clear(); }); - describe('bulk actions', () => { + // FLAKY: https://github.com/elastic/kibana/issues/152268 + describe.skip('bulk actions', () => { beforeEach(async () => { renderWithProviders(); await waitForElementToBeRemoved(() => screen.queryByTestId('centerJustifiedSpinner')); From d1eb224866e0435a5235c86cdd1686cac567afec Mon Sep 17 00:00:00 2001 From: Sloane Perrault Date: Mon, 27 Feb 2023 15:34:42 -0500 Subject: [PATCH 027/131] [Enterprise Search] Engines Search Preview - Improve these results link (#152146) ## Summary 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] 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)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- .../engine_search_preview.tsx | 11 +++- .../search_ui_components.tsx | 51 +++++++++++-------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview.tsx index f4491baf6a7a6..f31fb2dd911a7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/engine_search_preview.tsx @@ -9,7 +9,7 @@ import React, { useState, useMemo } from 'react'; import { useValues } from 'kea'; -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer } from '@elastic/eui'; import { PagingInfo, Results, @@ -25,7 +25,9 @@ import EnginesAPIConnector, { } from '@elastic/search-ui-engines-connector'; import { HttpSetup } from '@kbn/core-http-browser'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { docLinks } from '../../../../shared/doc_links'; import { HttpLogic } from '../../../../shared/http'; import { EngineViewTabs } from '../../../routes'; import { EnterpriseSearchEnginesPageTemplate } from '../../layout/engines_page_template'; @@ -138,6 +140,13 @@ export const EngineSearchPreview: React.FC = () => { + + + + diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx index 97b1a1608ab60..c685cf5898e3d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/engine/engine_search_preview/search_ui_components.tsx @@ -194,26 +194,33 @@ export const ResultsPerPageView: React.FC = ({ options, value, }) => ( - - - - - ({ - text: i18n.translate( - 'xpack.enterpriseSearch.content.engine.searchPreview.resultsPerPage.label', - { - defaultMessage: '{value} {value, plural, one {Result} other {Results}}', - values: { value: option }, - } - ), - value: option, - })) ?? [] - } - value={value} - onChange={(evt) => onChange(parseInt(evt.target.value, 10))} - /> - + + + + + + ({ + text: i18n.translate( + 'xpack.enterpriseSearch.content.engine.searchPreview.resultsPerPage.option.label', + { + defaultMessage: '{value} {value, plural, one {Result} other {Results}}', + values: { value: option }, + } + ), + value: option, + })) ?? [] + } + value={value} + onChange={(evt) => onChange(parseInt(evt.target.value, 10))} + /> + + ); From 340d59276adb0ddd5dd50d8dac9fb230cb708e78 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 27 Feb 2023 20:48:28 +0000 Subject: [PATCH 028/131] skip flaky suite (#145477) --- test/functional/apps/console/_xjson.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/functional/apps/console/_xjson.ts b/test/functional/apps/console/_xjson.ts index 1535337a2a848..445bfa5d42f0a 100644 --- a/test/functional/apps/console/_xjson.ts +++ b/test/functional/apps/console/_xjson.ts @@ -15,7 +15,8 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => { const log = getService('log'); const PageObjects = getPageObjects(['common', 'console', 'header']); - describe('XJSON', function testXjson() { + // FLAKY: https://github.com/elastic/kibana/issues/145477 + describe.skip('XJSON', function testXjson() { this.tags('includeFirefox'); before(async () => { await PageObjects.common.navigateToApp('console'); From cc32132539566bb921268fe5841553de9cff9673 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 27 Feb 2023 21:19:21 +0000 Subject: [PATCH 029/131] skip flaky suite (#145776) --- .../rule_execution_logic/machine_learning.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/machine_learning.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/machine_learning.ts index fe12454cf4591..099104ad411f7 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/machine_learning.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/machine_learning.ts @@ -64,7 +64,8 @@ export default ({ getService }: FtrProviderContext) => { rule_id: 'ml-rule-id', }; - describe('Machine learning type rules', () => { + // FLAKY: https://github.com/elastic/kibana/issues/145776 + describe.skip('Machine learning type rules', () => { before(async () => { // Order is critical here: auditbeat data must be loaded before attempting to start the ML job, // as the job looks for certain indices on start From ab9407294fe499d20494e0f1d1816749fff3e384 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Mon, 27 Feb 2023 21:22:29 +0000 Subject: [PATCH 030/131] skip flaky suite (#152267) --- .../sections/rules_list/components/rules_list_bulk_edit.test.tsx | 1 + 1 file changed, 1 insertion(+) 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 e059bab845116..271c12aa3f63b 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 @@ -157,6 +157,7 @@ describe('Rules list Bulk Edit', () => { }); // FLAKY: https://github.com/elastic/kibana/issues/152268 + // FLAKY: https://github.com/elastic/kibana/issues/152267 describe.skip('bulk actions', () => { beforeEach(async () => { renderWithProviders(); From 46dc8817d3437f32d7ae067f0bc553c8554b6ebf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:52:20 -0600 Subject: [PATCH 031/131] Update dependency terser to ^5.16.4 (main) (#152148) 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.3` -> `^5.16.4`](https://renovatebot.com/diffs/npm/terser/5.16.3/5.16.4) | [![age](https://badges.renovateapi.com/packages/npm/terser/5.16.4/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/terser/5.16.4/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/terser/5.16.4/compatibility-slim/5.16.3)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/terser/5.16.4/confidence-slim/5.16.3)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
terser/terser ### [`v5.16.4`](https://togithub.com/terser/terser/blob/HEAD/CHANGELOG.md#v5164) [Compare Source](https://togithub.com/terser/terser/compare/v5.16.3...v5.16.4) - Keep `(defaultArg = undefined) => ...`, because default args don't count for function length - Prevent inlining variables into `?.` optional chains - Avoid removing unused arguments while transforming - Optimize iterating AST node lists - Make sure `catch` and `finally` aren't children of `try` in the AST - Use modern unicode property escapes (`\p{...}`) to parse identifiers when available
--- ### 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 ec45d23c195e2..6a5dfee24609d 100644 --- a/package.json +++ b/package.json @@ -1446,7 +1446,7 @@ "svgo": "^2.8.0", "tape": "^5.0.1", "tempy": "^0.3.0", - "terser": "^5.16.3", + "terser": "^5.16.4", "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 c662b59d24299..49e9424aa8cec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27106,10 +27106,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.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== +terser@^5.14.1, terser@^5.16.4, terser@^5.3.4, terser@^5.9.0: + version "5.16.5" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.5.tgz#1c285ca0655f467f92af1bbab46ab72d1cb08e5a" + integrity sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg== dependencies: "@jridgewell/source-map" "^0.3.2" acorn "^8.5.0" From 3e5a9ab61511c45417ad26d4ec26c0aea21885d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:52:45 -0600 Subject: [PATCH 032/131] Update babel to ^7.21.0 (main) (#152249) 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/cli](https://babel.dev/docs/en/next/babel-cli) ([source](https://togithub.com/babel/babel)) | [`^7.20.7` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fcli/7.20.7/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fcli/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fcli/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fcli/7.21.0/compatibility-slim/7.20.7)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fcli/7.21.0/confidence-slim/7.20.7)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/core](https://babel.dev/docs/en/next/babel-core) ([source](https://togithub.com/babel/babel)) | [`^7.20.12` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fcore/7.20.12/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fcore/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fcore/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fcore/7.21.0/compatibility-slim/7.20.12)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fcore/7.21.0/confidence-slim/7.20.12)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/generator](https://babel.dev/docs/en/next/babel-generator) ([source](https://togithub.com/babel/babel)) | [`^7.20.14` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fgenerator/7.20.14/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.0/compatibility-slim/7.20.14)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.0/confidence-slim/7.20.14)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/parser](https://babel.dev/docs/en/next/babel-parser) ([source](https://togithub.com/babel/babel)) | [`^7.20.15` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fparser/7.20.15/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.0/compatibility-slim/7.20.15)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.0/confidence-slim/7.20.15)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/plugin-proposal-optional-chaining](https://babel.dev/docs/en/next/babel-plugin-proposal-optional-chaining) ([source](https://togithub.com/babel/babel)) | [`^7.20.7` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fplugin-proposal-optional-chaining/7.20.7/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-proposal-optional-chaining/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-proposal-optional-chaining/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-proposal-optional-chaining/7.21.0/compatibility-slim/7.20.7)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-proposal-optional-chaining/7.21.0/confidence-slim/7.20.7)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/plugin-transform-runtime](https://babel.dev/docs/en/next/babel-plugin-transform-runtime) ([source](https://togithub.com/babel/babel)) | [`^7.19.6` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fplugin-transform-runtime/7.19.6/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-transform-runtime/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-transform-runtime/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-transform-runtime/7.21.0/compatibility-slim/7.19.6)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fplugin-transform-runtime/7.21.0/confidence-slim/7.19.6)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/preset-typescript](https://babel.dev/docs/en/next/babel-preset-typescript) ([source](https://togithub.com/babel/babel)) | [`^7.18.6` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fpreset-typescript/7.18.6/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fpreset-typescript/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fpreset-typescript/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fpreset-typescript/7.21.0/compatibility-slim/7.18.6)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fpreset-typescript/7.21.0/confidence-slim/7.18.6)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/register](https://babel.dev/docs/en/next/babel-register) ([source](https://togithub.com/babel/babel)) | [`^7.18.9` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fregister/7.18.9/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fregister/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fregister/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fregister/7.21.0/compatibility-slim/7.18.9)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fregister/7.21.0/confidence-slim/7.18.9)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/runtime](https://babel.dev/docs/en/next/babel-runtime) ([source](https://togithub.com/babel/babel)) | [`^7.20.13` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2fruntime/7.20.13/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fruntime/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fruntime/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fruntime/7.21.0/compatibility-slim/7.20.13)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fruntime/7.21.0/confidence-slim/7.20.13)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/traverse](https://babel.dev/docs/en/next/babel-traverse) ([source](https://togithub.com/babel/babel)) | [`^7.20.13` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2ftraverse/7.20.13/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.0/compatibility-slim/7.20.13)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.0/confidence-slim/7.20.13)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/types](https://babel.dev/docs/en/next/babel-types) ([source](https://togithub.com/babel/babel)) | [`^7.20.7` -> `^7.21.0`](https://renovatebot.com/diffs/npm/@babel%2ftypes/7.20.7/7.21.0) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.0/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.0/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.0/compatibility-slim/7.20.7)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.0/confidence-slim/7.20.7)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
babel/babel (@​babel/cli) ### [`v7.21.0`](https://togithub.com/babel/babel/blob/HEAD/CHANGELOG.md#v7210-2023-02-20) [Compare Source](https://togithub.com/babel/babel/compare/v7.20.7...v7.21.0) ##### :rocket: New Feature - `babel-core`, `babel-helper-create-class-features-plugin`, `babel-plugin-proposal-class-properties`, `babel-plugin-proposal-private-methods`, `babel-plugin-proposal-private-property-in-object` - [#​15435](https://togithub.com/babel/babel/pull/15435) feat: Implement `privateFieldsAsSymbols` assumption for classes ([@​fwienber](https://togithub.com/fwienber)) - `babel-helper-create-regexp-features-plugin`, `babel-plugin-proposal-regexp-modifiers`, `babel-standalone` - [#​15226](https://togithub.com/babel/babel/pull/15226) feat: Support regexp modifiers proposal ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-cli`, `babel-core`, `babel-generator`, `babel-plugin-transform-destructuring`, `babel-plugin-transform-modules-commonjs`, `babel-plugin-transform-react-jsx`, `babel-traverse` - [#​15022](https://togithub.com/babel/babel/pull/15022) feat: Generate sourcemaps of friendly call frames ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-parser`, `babel-types` - [#​15384](https://togithub.com/babel/babel/pull/15384) \[ts] Support `const` modifier in type parameters ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) - `babel-generator`, `babel-helpers`, `babel-parser`, `babel-plugin-proposal-decorators`, `babel-plugin-syntax-decorators`, `babel-runtime-corejs2`, `babel-runtime-corejs3`, `babel-runtime` - [#​15405](https://togithub.com/babel/babel/pull/15405) Implement decorators as presented at `2023-01` TC39 meeting ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) - `babel-parser` - [#​15114](https://togithub.com/babel/babel/pull/15114) Parser option to allow `new.target` outside functions ([@​overlookmotel](https://togithub.com/overlookmotel)) - [#​15320](https://togithub.com/babel/babel/pull/15320) Add `annexb: false` parser option to disable Annex B ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) - `babel-core` - [#​15283](https://togithub.com/babel/babel/pull/15283) feat: Support `.cts` as configuration file ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-generator`, `babel-parser`, `babel-plugin-transform-typescript` - [#​15381](https://togithub.com/babel/babel/pull/15381) \[ts] Support `export type * from` ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) ##### :bug: Bug Fix - `babel-plugin-transform-typescript` - [#​15379](https://togithub.com/babel/babel/pull/15379) \[ts5.0] Better inlining of constants in enums ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-core` - [#​15366](https://togithub.com/babel/babel/pull/15366) handling circular/shared structures in deep-clone ([@​azizghuloum](https://togithub.com/azizghuloum)) - `babel-helper-create-class-features-plugin`, `babel-plugin-proposal-class-properties`, `babel-plugin-proposal-class-static-block`, `babel-plugin-proposal-private-methods`, `babel-plugin-transform-classes`, `babel-plugin-transform-new-target` - [#​15406](https://togithub.com/babel/babel/pull/15406) Preserve class elements comments in class transform ([@​JLHwung](https://togithub.com/JLHwung)) - `babel-parser`, `babel-plugin-transform-flow-comments`, `babel-plugin-transform-flow-strip-types`, `babel-types` - [#​15414](https://togithub.com/babel/babel/pull/15414) \[ts] Fix restrictions for optional parameters ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) ##### :nail_care: Polish - `babel-parser` - [#​15400](https://togithub.com/babel/babel/pull/15400) polish: improve "`await` as identifier" error in modules ([@​JLHwung](https://togithub.com/JLHwung)) ##### :house: Internal - `babel-core` - [#​15137](https://togithub.com/babel/babel/pull/15137) Improve CJS compat with ESM-based `@babel/core` ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) ##### :microscope: Output optimization - `babel-plugin-transform-typescript` - [#​15418](https://togithub.com/babel/babel/pull/15418) \[ts] Handle exponentiation operator in constant folding ([@​ehoogeveen-medweb](https://togithub.com/ehoogeveen-medweb))
babel/babel (@​babel/parser) ### [`v7.21.0`](https://togithub.com/babel/babel/releases/tag/v7.21.0) [Compare Source](https://togithub.com/babel/babel/compare/v7.20.15...v7.21.0) #### v7.21.0 (2023-02-20) Thanks [@​azizghuloum](https://togithub.com/azizghuloum), [@​ehoogeveen-medweb](https://togithub.com/ehoogeveen-medweb), [@​fwienber](https://togithub.com/fwienber), and [@​Lioness100](https://togithub.com/Lioness100) for your first PRs! ##### :rocket: New Feature - `babel-core`, `babel-helper-create-class-features-plugin`, `babel-plugin-proposal-class-properties`, `babel-plugin-proposal-private-methods`, `babel-plugin-proposal-private-property-in-object` - [#​15435](https://togithub.com/babel/babel/pull/15435) feat: Implement `privateFieldsAsSymbols` assumption for classes ([@​fwienber](https://togithub.com/fwienber)) - `babel-helper-create-regexp-features-plugin`, `babel-plugin-proposal-regexp-modifiers`, `babel-standalone` - [#​15226](https://togithub.com/babel/babel/pull/15226) feat: Support regexp modifiers proposal ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-cli`, `babel-core`, `babel-generator`, `babel-plugin-transform-destructuring`, `babel-plugin-transform-modules-commonjs`, `babel-plugin-transform-react-jsx`, `babel-traverse` - [#​15022](https://togithub.com/babel/babel/pull/15022) feat: Generate sourcemaps of friendly call frames ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-parser`, `babel-types` - [#​15384](https://togithub.com/babel/babel/pull/15384) \[ts] Support `const` modifier in type parameters ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) - `babel-generator`, `babel-helpers`, `babel-parser`, `babel-plugin-proposal-decorators`, `babel-plugin-syntax-decorators`, `babel-runtime-corejs2`, `babel-runtime-corejs3`, `babel-runtime` - [#​15405](https://togithub.com/babel/babel/pull/15405) Implement decorators as presented at `2023-01` TC39 meeting ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) - `babel-parser` - [#​15114](https://togithub.com/babel/babel/pull/15114) Parser option to allow `new.target` outside functions ([@​overlookmotel](https://togithub.com/overlookmotel)) - [#​15320](https://togithub.com/babel/babel/pull/15320) Add `annexb: false` parser option to disable Annex B ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) - `babel-core` - [#​15283](https://togithub.com/babel/babel/pull/15283) feat: Support `.cts` as configuration file ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-generator`, `babel-parser`, `babel-plugin-transform-typescript` - [#​15381](https://togithub.com/babel/babel/pull/15381) \[ts] Support `export type * from` ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) ##### :bug: Bug Fix - `babel-plugin-transform-typescript` - [#​15379](https://togithub.com/babel/babel/pull/15379) \[ts5.0] Better inlining of constants in enums ([@​liuxingbaoyu](https://togithub.com/liuxingbaoyu)) - `babel-core` - [#​15366](https://togithub.com/babel/babel/pull/15366) handling circular/shared structures in deep-clone ([@​azizghuloum](https://togithub.com/azizghuloum)) - `babel-helper-create-class-features-plugin`, `babel-plugin-proposal-class-properties`, `babel-plugin-proposal-class-static-block`, `babel-plugin-proposal-private-methods`, `babel-plugin-transform-classes`, `babel-plugin-transform-new-target` - [#​15406](https://togithub.com/babel/babel/pull/15406) Preserve class elements comments in class transform ([@​JLHwung](https://togithub.com/JLHwung)) - `babel-parser`, `babel-plugin-transform-flow-comments`, `babel-plugin-transform-flow-strip-types`, `babel-types` - [#​15414](https://togithub.com/babel/babel/pull/15414) \[ts] Fix restrictions for optional parameters ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) ##### :nail_care: Polish - `babel-parser` - [#​15400](https://togithub.com/babel/babel/pull/15400) polish: improve "`await` as identifier" error in modules ([@​JLHwung](https://togithub.com/JLHwung)) ##### :house: Internal - `babel-core` - [#​15137](https://togithub.com/babel/babel/pull/15137) Improve CJS compat with ESM-based `@babel/core` ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) ##### :microscope: Output optimization - `babel-plugin-transform-typescript` - [#​15418](https://togithub.com/babel/babel/pull/15418) \[ts] Handle exponentiation operator in constant folding ([@​ehoogeveen-medweb](https://togithub.com/ehoogeveen-medweb)) ##### Committers: 11 - Abdulaziz Ghuloum ([@​azizghuloum](https://togithub.com/azizghuloum)) - Babel Bot ([@​babel-bot](https://togithub.com/babel-bot)) - Emanuel Hoogeveen ([@​ehoogeveen-medweb](https://togithub.com/ehoogeveen-medweb)) - Frank Wienberg ([@​fwienber](https://togithub.com/fwienber)) - Huáng Jùnliàng ([@​JLHwung](https://togithub.com/JLHwung)) - Mateusz Burzyński ([@​Andarist](https://togithub.com/Andarist)) - Nicolò Ribaudo ([@​nicolo-ribaudo](https://togithub.com/nicolo-ribaudo)) - [@​Lioness100](https://togithub.com/Lioness100) - [@​liuxingbaoyu](https://togithub.com/liuxingbaoyu) - [@​overlookmotel](https://togithub.com/overlookmotel) - fisker Cheung ([@​fisker](https://togithub.com/fisker))
--- ### 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 these updates 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 | 22 ++--- yarn.lock | 274 +++++++++++++++++++++++++++------------------------ 2 files changed, 154 insertions(+), 142 deletions(-) diff --git a/package.json b/package.json index 6a5dfee24609d..ac0ec73c93437 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ }, "dependencies": { "@appland/sql-parser": "^1.5.1", - "@babel/runtime": "^7.20.13", + "@babel/runtime": "^7.21.0", "@dnd-kit/core": "^3.1.1", "@dnd-kit/sortable": "^4.0.0", "@dnd-kit/utilities": "^2.0.0", @@ -934,26 +934,26 @@ }, "devDependencies": { "@apidevtools/swagger-parser": "^10.0.3", - "@babel/cli": "^7.20.7", - "@babel/core": "^7.20.12", + "@babel/cli": "^7.21.0", + "@babel/core": "^7.21.0", "@babel/eslint-parser": "^7.19.1", "@babel/eslint-plugin": "^7.19.1", - "@babel/generator": "^7.20.14", + "@babel/generator": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", - "@babel/parser": "^7.20.15", + "@babel/parser": "^7.21.0", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/plugin-proposal-export-namespace-from": "^7.18.9", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", "@babel/plugin-proposal-object-rest-spread": "^7.20.7", - "@babel/plugin-proposal-optional-chaining": "^7.20.7", + "@babel/plugin-proposal-optional-chaining": "^7.21.0", "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-transform-runtime": "^7.19.6", + "@babel/plugin-transform-runtime": "^7.21.0", "@babel/preset-env": "^7.20.2", "@babel/preset-react": "^7.18.6", - "@babel/preset-typescript": "^7.18.6", - "@babel/register": "^7.18.9", - "@babel/traverse": "^7.20.13", - "@babel/types": "^7.20.7", + "@babel/preset-typescript": "^7.21.0", + "@babel/register": "^7.21.0", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0", "@bazel/ibazel": "^0.16.2", "@bazel/typescript": "4.6.2", "@cypress/code-coverage": "^3.10.0", diff --git a/yarn.lock b/yarn.lock index 49e9424aa8cec..739e766ef4794 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,12 +7,13 @@ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.0.1.tgz#b38b444ad3aa5fedbb15f2f746dcd934226a12dd" integrity sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g== -"@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== +"@ampproject/remapping@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: - "@jridgewell/trace-mapping" "^0.3.0" + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" "@apidevtools/json-schema-ref-parser@^9.0.6": version "9.0.9" @@ -56,12 +57,12 @@ resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.10.1.tgz#70e45678f06c72fa2e350e8553ec4a4d72b92e06" integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg== -"@babel/cli@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.20.7.tgz#8fc12e85c744a1a617680eacb488fab1fcd35b7c" - integrity sha512-WylgcELHB66WwQqItxNILsMlaTd8/SO6SgTTjMp4uCI7P4QyH1r3nqgFmO3BfM4AtfniHgFMH3EpYFj/zynBkQ== +"@babel/cli@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.21.0.tgz#1868eb70e9824b427fc607610cce8e9e7889e7e1" + integrity sha512-xi7CxyS8XjSyiwUGCfwf+brtJxjW1/ZTcBUkP10xawIEXLX5HzLn+3aXkgxozcP2UhRhtKTmQurw9Uaes7jZrA== dependencies: - "@jridgewell/trace-mapping" "^0.3.8" + "@jridgewell/trace-mapping" "^0.3.17" commander "^4.0.1" convert-source-map "^1.1.0" fs-readdir-recursive "^1.1.0" @@ -113,21 +114,21 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.20.12", "@babel/core@^7.7.2", "@babel/core@^7.7.5": - version "7.20.12" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" - integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== +"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.21.0", "@babel/core@^7.7.2", "@babel/core@^7.7.5": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.0.tgz#1341aefdcc14ccc7553fcc688dd8986a2daffc13" + integrity sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA== dependencies: - "@ampproject/remapping" "^2.1.0" + "@ampproject/remapping" "^2.2.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" + "@babel/generator" "^7.21.0" "@babel/helper-compilation-targets" "^7.20.7" - "@babel/helper-module-transforms" "^7.20.11" - "@babel/helpers" "^7.20.7" - "@babel/parser" "^7.20.7" + "@babel/helper-module-transforms" "^7.21.0" + "@babel/helpers" "^7.21.0" + "@babel/parser" "^7.21.0" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.12" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -150,13 +151,14 @@ dependencies: eslint-rule-composer "^0.3.0" -"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.20.14", "@babel/generator@^7.20.7", "@babel/generator@^7.7.2": - version "7.20.14" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.14.tgz#9fa772c9f86a46c6ac9b321039400712b96f64ce" - integrity sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg== +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.21.0", "@babel/generator@^7.21.1", "@babel/generator@^7.7.2": + version "7.21.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.1.tgz#951cc626057bc0af2c35cd23e9c64d384dea83dd" + integrity sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA== dependencies: - "@babel/types" "^7.20.7" + "@babel/types" "^7.21.0" "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.16.0", "@babel/helper-annotate-as-pure@^7.18.6": @@ -185,17 +187,18 @@ lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.19.0", "@babel/helper-create-class-features-plugin@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz#3c08a5b5417c7f07b5cf3dfb6dc79cbec682e8c2" - integrity sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA== +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2", "@babel/helper-create-class-features-plugin@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz#64f49ecb0020532f19b1d014b03bccaa1ab85fb9" + integrity sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" - "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-function-name" "^7.21.0" + "@babel/helper-member-expression-to-functions" "^7.21.0" "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-replace-supers" "^7.20.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": @@ -244,13 +247,13 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": - version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" - integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4" + integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg== dependencies: - "@babel/template" "^7.18.10" - "@babel/types" "^7.19.0" + "@babel/template" "^7.20.7" + "@babel/types" "^7.21.0" "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" @@ -259,12 +262,12 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-member-expression-to-functions@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" - integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== +"@babel/helper-member-expression-to-functions@^7.20.7", "@babel/helper-member-expression-to-functions@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz#319c6a940431a133897148515877d2f3269c3ba5" + integrity sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q== dependencies: - "@babel/types" "^7.18.9" + "@babel/types" "^7.21.0" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.0", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": version "7.18.6" @@ -273,10 +276,10 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.11": - version "7.20.11" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" - integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.21.0": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" + integrity sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" @@ -284,8 +287,8 @@ "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.19.1" "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.10" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.2" + "@babel/types" "^7.21.2" "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" @@ -314,16 +317,17 @@ "@babel/helper-wrap-function" "^7.18.9" "@babel/types" "^7.18.9" -"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": - version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" - integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1", "@babel/helper-replace-supers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" + integrity sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A== dependencies: "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.20.7" "@babel/helper-optimise-call-expression" "^7.18.6" - "@babel/traverse" "^7.19.1" - "@babel/types" "^7.19.0" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" "@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": version "7.20.2" @@ -356,10 +360,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== -"@babel/helper-validator-option@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" - integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== +"@babel/helper-validator-option@^7.18.6", "@babel/helper-validator-option@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" + integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== "@babel/helper-wrap-function@^7.18.9": version "7.19.0" @@ -371,14 +375,14 @@ "@babel/traverse" "^7.19.0" "@babel/types" "^7.19.0" -"@babel/helpers@^7.12.5", "@babel/helpers@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" - integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e" + integrity sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA== dependencies: "@babel/template" "^7.20.7" - "@babel/traverse" "^7.20.7" - "@babel/types" "^7.20.7" + "@babel/traverse" "^7.21.0" + "@babel/types" "^7.21.0" "@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": version "7.18.6" @@ -389,10 +393,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.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/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.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" + integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" @@ -532,10 +536,10 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.12.7", "@babel/plugin-proposal-optional-chaining@^7.18.9", "@babel/plugin-proposal-optional-chaining@^7.20.7": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz#49f2b372519ab31728cc14115bb0998b15bfda55" - integrity sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ== +"@babel/plugin-proposal-optional-chaining@^7.12.7", "@babel/plugin-proposal-optional-chaining@^7.18.9", "@babel/plugin-proposal-optional-chaining@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" + integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== dependencies: "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" @@ -968,13 +972,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-runtime@^7.19.6": - version "7.19.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz#9d2a9dbf4e12644d6f46e5e75bfbf02b5d6e9194" - integrity sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw== +"@babel/plugin-transform-runtime@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz#2a884f29556d0a68cd3d152dcc9e6c71dfb6eee8" + integrity sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg== dependencies: "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-plugin-utils" "^7.20.2" babel-plugin-polyfill-corejs2 "^0.3.3" babel-plugin-polyfill-corejs3 "^0.6.0" babel-plugin-polyfill-regenerator "^0.4.1" @@ -1016,13 +1020,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-typescript@^7.18.6": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.0.tgz#2c7ec62b8bfc21482f3748789ba294a46a375169" - integrity sha512-xOAsAFaun3t9hCwZ13Qe7gq423UgMZ6zAgmLxeGGapFqlT/X3L5qT2btjiVLlFn7gWtMaVyceS5VxGAuKbgizw== +"@babel/plugin-transform-typescript@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.0.tgz#f0956a153679e3b377ae5b7f0143427151e4c848" + integrity sha512-xo///XTPp3mDzTtrqXoBlK9eiAYW3wv9JXglcn/u1bi60RW11dEUxIgA8cbnDhutS1zacjMRmAwxE0gMklLnZg== dependencies: - "@babel/helper-create-class-features-plugin" "^7.19.0" - "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-create-class-features-plugin" "^7.21.0" + "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-typescript" "^7.20.0" "@babel/plugin-transform-unicode-escapes@^7.18.10": @@ -1153,19 +1157,19 @@ "@babel/plugin-transform-react-jsx-development" "^7.18.6" "@babel/plugin-transform-react-pure-annotations" "^7.18.6" -"@babel/preset-typescript@^7.12.7", "@babel/preset-typescript@^7.18.6": - version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" - integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== +"@babel/preset-typescript@^7.12.7", "@babel/preset-typescript@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.21.0.tgz#bcbbca513e8213691fe5d4b23d9251e01f00ebff" + integrity sha512-myc9mpoVA5m1rF8K8DgLEatOYFDpwC+RkMkjZ0Du6uI62YvDe8uxIEYVs/VCdSJ097nlALiU/yBC7//3nI+hNg== dependencies: - "@babel/helper-plugin-utils" "^7.18.6" - "@babel/helper-validator-option" "^7.18.6" - "@babel/plugin-transform-typescript" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-validator-option" "^7.21.0" + "@babel/plugin-transform-typescript" "^7.21.0" -"@babel/register@^7.12.1", "@babel/register@^7.18.9": - version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.18.9.tgz#1888b24bc28d5cc41c412feb015e9ff6b96e439c" - integrity sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw== +"@babel/register@^7.12.1", "@babel/register@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.21.0.tgz#c97bf56c2472e063774f31d344c592ebdcefa132" + integrity sha512-9nKsPmYDi5DidAqJaQooxIhsLJiNMkGr8ypQ8Uic7cIox7UCDsM7HuUGxdGT7mSDTYbqzIdsOWzfBton/YJrMw== dependencies: clone-deep "^4.0.1" find-cache-dir "^2.0.0" @@ -1181,10 +1185,10 @@ core-js-pure "^3.25.1" regenerator-runtime "^0.13.10" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.20.13" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.13.tgz#7055ab8a7cff2b8f6058bf6ae45ff84ad2aded4b" - integrity sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA== +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.21.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" + integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== dependencies: regenerator-runtime "^0.13.11" @@ -1197,26 +1201,26 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/traverse@^7.10.3", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.13", "@babel/traverse@^7.20.7", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.2": - version "7.20.13" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.13.tgz#817c1ba13d11accca89478bd5481b2d168d07473" - integrity sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ== +"@babel/traverse@^7.10.3", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.19.0", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.2": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.2.tgz#ac7e1f27658750892e815e60ae90f382a46d8e75" + integrity sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.7" + "@babel/generator" "^7.21.1" "@babel/helper-environment-visitor" "^7.18.9" - "@babel/helper-function-name" "^7.19.0" + "@babel/helper-function-name" "^7.21.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.13" - "@babel/types" "^7.20.7" + "@babel/parser" "^7.21.2" + "@babel/types" "^7.21.2" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.10.3", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.20.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" - integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== +"@babel/types@^7.0.0", "@babel/types@^7.10.3", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.21.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.2.tgz#92246f6e00f91755893c2876ad653db70c8310d1" + integrity sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" @@ -2680,6 +2684,14 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" @@ -2689,15 +2701,15 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c" - integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== -"@jridgewell/set-array@^1.0.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" - integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.2": version "0.3.2" @@ -2707,10 +2719,10 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -2720,13 +2732,13 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.0", "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" - integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" "@jsdevtools/ono@^7.1.3": version "7.1.3" From 8b3d2f7c176e309c43bbb89a048d73241cb56296 Mon Sep 17 00:00:00 2001 From: Kevin Logan <56395104+kevinlog@users.noreply.github.com> Date: Mon, 27 Feb 2023 15:42:31 -0800 Subject: [PATCH 033/131] [Security Solution] Fix bug where isolate fails on Alert associated with 0 Cases (#152297) ## Summary Fixes a bug where Isolate was failing in the isolate flyout from an Alert associated with 0 cases. The bug was that an empty array was being passed to `case_ids` parameter and it requires that there is at least 1 cases in the array. This PR makes sure that the flyout does not pass an empty array. We can now isolate in an Alert without any cases ![image](https://user-images.githubusercontent.com/56395104/221695149-bf865a82-748a-4d12-91be-deb96a20b61b.png) Isolate still works when there are cases present ![image](https://user-images.githubusercontent.com/56395104/221695198-492bcf17-6742-48f8-ab00-772d47bc0b93.png) --- .../public/detections/components/host_isolation/isolate.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/isolate.tsx b/x-pack/plugins/security_solution/public/detections/components/host_isolation/isolate.tsx index 1b47ec16714f8..044e893572151 100644 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/isolate.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/host_isolation/isolate.tsx @@ -38,7 +38,11 @@ export const IsolateHost = React.memo( return caseInfo.id; }); - const { loading, isolateHost } = useHostIsolation({ endpointId, comment, caseIds }); + const { loading, isolateHost } = useHostIsolation({ + endpointId, + comment, + caseIds: caseIds.length > 0 ? caseIds : undefined, + }); const confirmHostIsolation = useCallback(async () => { const hostIsolated = await isolateHost(); From 4aa0961613e55d6d0017631edb0e99c2bb17a065 Mon Sep 17 00:00:00 2001 From: Philippe Oberti Date: Mon, 27 Feb 2023 21:02:03 -0600 Subject: [PATCH 034/131] [Security Solution] expanded flyout (#150240) --- .github/CODEOWNERS | 1 + .i18nrc.json | 1 + package.json | 1 + packages/kbn-expandable-flyout/README.md | 66 +++ packages/kbn-expandable-flyout/index.ts | 13 + packages/kbn-expandable-flyout/jest.config.js | 13 + packages/kbn-expandable-flyout/kibana.jsonc | 5 + packages/kbn-expandable-flyout/package.json | 6 + packages/kbn-expandable-flyout/src/actions.ts | 58 +++ .../src/components/left_section.tsx | 37 ++ .../src/components/preview_section.test.tsx | 55 +++ .../src/components/preview_section.tsx | 124 ++++++ .../src/components/right_section.tsx | 40 ++ .../src/components/test_ids.ts | 17 + .../src/components/translations.ts | 17 + .../kbn-expandable-flyout/src/context.tsx | 172 ++++++++ .../kbn-expandable-flyout/src/index.test.tsx | 105 +++++ packages/kbn-expandable-flyout/src/index.tsx | 113 +++++ .../kbn-expandable-flyout/src/reducer.test.ts | 417 ++++++++++++++++++ packages/kbn-expandable-flyout/src/reducer.ts | 109 +++++ packages/kbn-expandable-flyout/src/types.ts | 43 ++ packages/kbn-expandable-flyout/tsconfig.json | 24 + tsconfig.base.json | 2 + .../common/experimental_features.ts | 4 + .../app/home/template_wrapper/index.tsx | 56 +-- .../control_columns/row_action/index.tsx | 25 +- .../public/common/mock/test_providers.tsx | 17 +- .../plugins/security_solution/tsconfig.json | 1 + yarn.lock | 4 + 29 files changed, 1504 insertions(+), 42 deletions(-) create mode 100644 packages/kbn-expandable-flyout/README.md create mode 100644 packages/kbn-expandable-flyout/index.ts create mode 100644 packages/kbn-expandable-flyout/jest.config.js create mode 100644 packages/kbn-expandable-flyout/kibana.jsonc create mode 100644 packages/kbn-expandable-flyout/package.json create mode 100644 packages/kbn-expandable-flyout/src/actions.ts create mode 100644 packages/kbn-expandable-flyout/src/components/left_section.tsx create mode 100644 packages/kbn-expandable-flyout/src/components/preview_section.test.tsx create mode 100644 packages/kbn-expandable-flyout/src/components/preview_section.tsx create mode 100644 packages/kbn-expandable-flyout/src/components/right_section.tsx create mode 100644 packages/kbn-expandable-flyout/src/components/test_ids.ts create mode 100644 packages/kbn-expandable-flyout/src/components/translations.ts create mode 100644 packages/kbn-expandable-flyout/src/context.tsx create mode 100644 packages/kbn-expandable-flyout/src/index.test.tsx create mode 100644 packages/kbn-expandable-flyout/src/index.tsx create mode 100644 packages/kbn-expandable-flyout/src/reducer.test.ts create mode 100644 packages/kbn-expandable-flyout/src/reducer.ts create mode 100644 packages/kbn-expandable-flyout/src/types.ts create mode 100644 packages/kbn-expandable-flyout/tsconfig.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f44a2e962f1fa..3d67d466db782 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -337,6 +337,7 @@ x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin src/plugins/event_annotation @elastic/kibana-visualizations x-pack/test/plugin_api_integration/plugins/event_log @elastic/response-ops x-pack/plugins/event_log @elastic/response-ops +packages/kbn-expandable-flyout @elastic/security-threat-hunting-investigations packages/kbn-expect @elastic/kibana-operations x-pack/examples/exploratory_view_example @elastic/uptime src/plugins/expression_error @elastic/kibana-presentation diff --git a/.i18nrc.json b/.i18nrc.json index d8a6b4689f78e..b7d7432551faa 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -25,6 +25,7 @@ "embeddableExamples": "examples/embeddable_examples", "esQuery": "packages/kbn-es-query/src", "esUi": "src/plugins/es_ui_shared", + "expandableFlyout": "packages/kbn-expandable-flyout", "expressionError": "src/plugins/expression_error", "expressionGauge": "src/plugins/chart_expressions/expression_gauge", "expressionHeatmap": "src/plugins/chart_expressions/expression_heatmap", diff --git a/package.json b/package.json index ac0ec73c93437..fcb6cffab0bf0 100644 --- a/package.json +++ b/package.json @@ -370,6 +370,7 @@ "@kbn/event-annotation-plugin": "link:src/plugins/event_annotation", "@kbn/event-log-fixture-plugin": "link:x-pack/test/plugin_api_integration/plugins/event_log", "@kbn/event-log-plugin": "link:x-pack/plugins/event_log", + "@kbn/expandable-flyout": "link:packages/kbn-expandable-flyout", "@kbn/exploratory-view-example-plugin": "link:x-pack/examples/exploratory_view_example", "@kbn/expression-error-plugin": "link:src/plugins/expression_error", "@kbn/expression-gauge-plugin": "link:src/plugins/chart_expressions/expression_gauge", diff --git a/packages/kbn-expandable-flyout/README.md b/packages/kbn-expandable-flyout/README.md new file mode 100644 index 0000000000000..8d21caba73a21 --- /dev/null +++ b/packages/kbn-expandable-flyout/README.md @@ -0,0 +1,66 @@ +# @kbn/expandable-flyout + +## Purpose + +This package offers an expandable flyout UI component and a way to manage the data displayed in it. The component leverages the [EuiFlyout](https://github.com/elastic/eui/tree/main/src/components/flyout) from the EUI library. + +The flyout is composed of 3 sections: +- a right section (primary section) that opens first +- a left wider section to show more details +- a preview section, that overlays the right section. This preview section can display multiple panels one after the other and displays a `Back` button + +At the moment, displaying more than one flyout within the same plugin might be complicated, unless there are in difference areas in the codebase and the contexts don't conflict with each other. + +## What the package offers + +The ExpandableFlyout [React component](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/index) that renders the UI. + +The ExpandableFlyout [React context](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/context) that exposes the following api: +- **openFlyout**: open the flyout with a set of panels +- **openFlyoutRightPanel**: open a right panel +- **openFlyoutLeftPanel**: open a left panel +- **openFlyoutPreviewPanel**: open a preview panel +- **closeFlyoutRightPanel**: close the right panel +- **closeFlyoutLeftPanel**: close the left panel +- **closeFlyoutPreviewPanel**: close the preview panels +- **previousFlyoutPreviewPanel**: navigate to the previous preview panel +- **closeFlyout**: close the flyout + +To retrieve the flyout's layout (left, right and preview panels), you can use the **panels** from the same [React context](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/context); + +- To have more details about how these above api work, see the code documentation [here](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/utils/helpers). + +## Usage + +To use the expandable flyout in your plugin, first you need wrap your code with the context provider at a high enough level as follows: +```typescript jsx + + + ... + + +``` + +Then use the React UI component where you need: + +```typescript jsx + +``` +where `myPanels` is a list of all the panels that can be rendered in the flyout (see interface [here](https://github.com/elastic/kibana/tree/main/packages/kbn-expandable-flyout/src/components/index)). + + +## Terminology + +### Section + +One of the 3 areas of the flyout (left, right or preview). + +### Panel + +A set of properties defining what's displayed in one of the flyout section. + +## Future work + +- currently the panels are aware of their width. This should be changed and the width of the left, right and preview sections should be handled by the flyout itself +- add the feature to save the flyout state (layout) to the url +- introduce the notion of scope to be able to handle more than one flyout per plugin?? \ No newline at end of file diff --git a/packages/kbn-expandable-flyout/index.ts b/packages/kbn-expandable-flyout/index.ts new file mode 100644 index 0000000000000..e2ce15d85a399 --- /dev/null +++ b/packages/kbn-expandable-flyout/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ExpandableFlyout } from './src'; +export { ExpandableFlyoutProvider, useExpandableFlyoutContext } from './src/context'; + +export type { ExpandableFlyoutProps } from './src'; +export type { FlyoutPanel } from './src/types'; diff --git a/packages/kbn-expandable-flyout/jest.config.js b/packages/kbn-expandable-flyout/jest.config.js new file mode 100644 index 0000000000000..f861f9b122fd5 --- /dev/null +++ b/packages/kbn-expandable-flyout/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/packages/kbn-expandable-flyout'], +}; diff --git a/packages/kbn-expandable-flyout/kibana.jsonc b/packages/kbn-expandable-flyout/kibana.jsonc new file mode 100644 index 0000000000000..b4f63cca6bf91 --- /dev/null +++ b/packages/kbn-expandable-flyout/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/expandable-flyout", + "owner": "@elastic/security-threat-hunting-investigations" +} diff --git a/packages/kbn-expandable-flyout/package.json b/packages/kbn-expandable-flyout/package.json new file mode 100644 index 0000000000000..a2e826c042842 --- /dev/null +++ b/packages/kbn-expandable-flyout/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/expandable-flyout", + "private": true, + "version": "1.0.0", + "license": "SSPL-1.0 OR Elastic License 2.0" +} \ No newline at end of file diff --git a/packages/kbn-expandable-flyout/src/actions.ts b/packages/kbn-expandable-flyout/src/actions.ts new file mode 100644 index 0000000000000..5709214394303 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/actions.ts @@ -0,0 +1,58 @@ +/* + * Copyright 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 { FlyoutPanel } from './types'; + +export enum ActionType { + openFlyout = 'open_flyout', + openRightPanel = 'open_right_panel', + openLeftPanel = 'open_left_panel', + openPreviewPanel = 'open_preview_panel', + closeRightPanel = 'close_right_panel', + closeLeftPanel = 'close_left_panel', + closePreviewPanel = 'close_preview_panel', + previousPreviewPanel = 'previous_preview_panel', + closeFlyout = 'close_flyout', +} + +export type Action = + | { + type: ActionType.openFlyout; + payload: { + right?: FlyoutPanel; + left?: FlyoutPanel; + preview?: FlyoutPanel; + }; + } + | { + type: ActionType.openRightPanel; + payload: FlyoutPanel; + } + | { + type: ActionType.openLeftPanel; + payload: FlyoutPanel; + } + | { + type: ActionType.openPreviewPanel; + payload: FlyoutPanel; + } + | { + type: ActionType.closeRightPanel; + } + | { + type: ActionType.closeLeftPanel; + } + | { + type: ActionType.closePreviewPanel; + } + | { + type: ActionType.previousPreviewPanel; + } + | { + type: ActionType.closeFlyout; + }; diff --git a/packages/kbn-expandable-flyout/src/components/left_section.tsx b/packages/kbn-expandable-flyout/src/components/left_section.tsx new file mode 100644 index 0000000000000..ddf53efbad2b8 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/components/left_section.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React from 'react'; +import { LEFT_SECTION } from './test_ids'; + +interface LeftSectionProps { + /** + * Component to be rendered + */ + component: React.ReactElement; + /** + * Width used when rendering the panel + */ + width: number; +} + +/** + * Left section of the expanded flyout rendering a panel + */ +export const LeftSection: React.FC = ({ component, width }: LeftSectionProps) => { + return ( + + + {component} + + + ); +}; + +LeftSection.displayName = 'LeftSection'; diff --git a/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx b/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx new file mode 100644 index 0000000000000..41926400e11f5 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/components/preview_section.test.tsx @@ -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 React from 'react'; +import { render } from '@testing-library/react'; +import { PreviewSection } from './preview_section'; +import { PREVIEW_SECTION_BACK_BUTTON, PREVIEW_SECTION_CLOSE_BUTTON } from './test_ids'; +import { ExpandableFlyoutContext } from '../context'; + +describe('PreviewSection', () => { + const context: ExpandableFlyoutContext = { + panels: { + right: {}, + left: {}, + preview: [ + { + id: 'key', + }, + ], + }, + } as unknown as ExpandableFlyoutContext; + + it('should render close button in header', () => { + const component =
{'component'}
; + const width = 500; + const showBackButton = false; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId(PREVIEW_SECTION_CLOSE_BUTTON)).toBeInTheDocument(); + }); + + it('should render back button in header', () => { + const component =
{'component'}
; + const width = 500; + const showBackButton = true; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId(PREVIEW_SECTION_BACK_BUTTON)).toBeInTheDocument(); + }); +}); diff --git a/packages/kbn-expandable-flyout/src/components/preview_section.tsx b/packages/kbn-expandable-flyout/src/components/preview_section.tsx new file mode 100644 index 0000000000000..e474d1204bf03 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/components/preview_section.tsx @@ -0,0 +1,124 @@ +/* + * Copyright 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 { + EuiButtonEmpty, + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + useEuiTheme, +} from '@elastic/eui'; +import React from 'react'; +import { css } from '@emotion/react'; +import { + PREVIEW_SECTION, + PREVIEW_SECTION_BACK_BUTTON, + PREVIEW_SECTION_CLOSE_BUTTON, +} from './test_ids'; +import { useExpandableFlyoutContext } from '../..'; +import { BACK_BUTTON, CLOSE_BUTTON } from './translations'; + +interface PreviewSectionProps { + /** + * Component to be rendered + */ + component: React.ReactElement; + /** + * Width used when rendering the panel + */ + width: number | undefined; + /** + * Display the back button in the header + */ + showBackButton: boolean; +} + +/** + * Preview section of the expanded flyout rendering one or multiple panels. + * Will display a back and close button in the header for the previous and close feature respectively. + */ +export const PreviewSection: React.FC = ({ + component, + showBackButton, + width, +}: PreviewSectionProps) => { + const { euiTheme } = useEuiTheme(); + const { closePreviewPanel, previousPreviewPanel } = useExpandableFlyoutContext(); + + const previewWith: string = width ? `${width}px` : '0px'; + + const closeButton = ( + + closePreviewPanel()} + data-test-subj={PREVIEW_SECTION_CLOSE_BUTTON} + aria-label={CLOSE_BUTTON} + /> + + ); + const header = showBackButton ? ( + + + previousPreviewPanel()} + data-test-subj={PREVIEW_SECTION_BACK_BUTTON} + aria-label={BACK_BUTTON} + > + {BACK_BUTTON} + + + {closeButton} + + ) : ( + {closeButton} + ); + + return ( + <> +
+
+ + {header} + {component} + +
+ + ); +}; + +PreviewSection.displayName = 'PreviewSection'; diff --git a/packages/kbn-expandable-flyout/src/components/right_section.tsx b/packages/kbn-expandable-flyout/src/components/right_section.tsx new file mode 100644 index 0000000000000..d018dd8721ee7 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/components/right_section.tsx @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React from 'react'; +import { RIGHT_SECTION } from './test_ids'; + +interface RightSectionProps { + /** + * Component to be rendered + */ + component: React.ReactElement; + /** + * Width used when rendering the panel + */ + width: number; +} + +/** + * Right section of the expanded flyout rendering a panel + */ +export const RightSection: React.FC = ({ + component, + width, +}: RightSectionProps) => { + return ( + + + {component} + + + ); +}; + +RightSection.displayName = 'RightSection'; diff --git a/packages/kbn-expandable-flyout/src/components/test_ids.ts b/packages/kbn-expandable-flyout/src/components/test_ids.ts new file mode 100644 index 0000000000000..38dd9231712c4 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/components/test_ids.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 const RIGHT_SECTION = 'rightSection'; + +export const LEFT_SECTION = 'leftSection'; + +export const PREVIEW_SECTION = 'previewSection'; + +export const PREVIEW_SECTION_CLOSE_BUTTON = 'previewSectionCloseButton'; + +export const PREVIEW_SECTION_BACK_BUTTON = 'previewSectionBackButton'; diff --git a/packages/kbn-expandable-flyout/src/components/translations.ts b/packages/kbn-expandable-flyout/src/components/translations.ts new file mode 100644 index 0000000000000..8b6646fa69df3 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/components/translations.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; + +export const BACK_BUTTON = i18n.translate('expandableFlyout.previewSection.backButton', { + defaultMessage: 'Back', +}); + +export const CLOSE_BUTTON = i18n.translate('expandableFlyout.previewSection.closeButton', { + defaultMessage: 'Close', +}); diff --git a/packages/kbn-expandable-flyout/src/context.tsx b/packages/kbn-expandable-flyout/src/context.tsx new file mode 100644 index 0000000000000..89e8210e9578f --- /dev/null +++ b/packages/kbn-expandable-flyout/src/context.tsx @@ -0,0 +1,172 @@ +/* + * Copyright 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, { createContext, useCallback, useContext, useMemo, useReducer } from 'react'; +import { ActionType } from './actions'; +import { reducer, State } from './reducer'; +import type { FlyoutPanel } from './types'; +import { initialState } from './reducer'; + +export interface ExpandableFlyoutContext { + /** + * Right, left and preview panels + */ + panels: State; + /** + * Open the flyout with left, right and/or preview panels + */ + openFlyout: (panels: { left?: FlyoutPanel; right?: FlyoutPanel; preview?: FlyoutPanel }) => void; + /** + * Replaces the current right panel with a new one + */ + openRightPanel: (panel: FlyoutPanel) => void; + /** + * Replaces the current left panel with a new one + */ + openLeftPanel: (panel: FlyoutPanel) => void; + /** + * Add a new preview panel to the list of current preview panels + */ + openPreviewPanel: (panel: FlyoutPanel) => void; + /** + * Closes right panel + */ + closeRightPanel: () => void; + /** + * Closes left panel + */ + closeLeftPanel: () => void; + /** + * Closes all preview panels + */ + closePreviewPanel: () => void; + /** + * Go back to previous preview panel + */ + previousPreviewPanel: () => void; + /** + * Close all panels and closes flyout + */ + closeFlyout: () => void; +} + +export const ExpandableFlyoutContext = createContext( + undefined +); + +export interface ExpandableFlyoutProviderProps { + /** + * React children + */ + children: React.ReactNode; +} + +/** + * Wrap your plugin with this context for the ExpandableFlyout React component. + */ +export const ExpandableFlyoutProvider = ({ children }: ExpandableFlyoutProviderProps) => { + const [state, dispatch] = useReducer(reducer, initialState); + + const openPanels = useCallback( + ({ + right, + left, + preview, + }: { + right?: FlyoutPanel; + left?: FlyoutPanel; + preview?: FlyoutPanel; + }) => dispatch({ type: ActionType.openFlyout, payload: { left, right, preview } }), + [dispatch] + ); + + const openRightPanel = useCallback( + (panel: FlyoutPanel) => dispatch({ type: ActionType.openRightPanel, payload: panel }), + [dispatch] + ); + + const openLeftPanel = useCallback( + (panel: FlyoutPanel) => dispatch({ type: ActionType.openLeftPanel, payload: panel }), + [dispatch] + ); + + const openPreviewPanel = useCallback( + (panel: FlyoutPanel) => dispatch({ type: ActionType.openPreviewPanel, payload: panel }), + [dispatch] + ); + + const closeRightPanel = useCallback( + () => dispatch({ type: ActionType.closeRightPanel }), + [dispatch] + ); + + const closeLeftPanel = useCallback( + () => dispatch({ type: ActionType.closeLeftPanel }), + [dispatch] + ); + + const closePreviewPanel = useCallback( + () => dispatch({ type: ActionType.closePreviewPanel }), + [dispatch] + ); + + const previousPreviewPanel = useCallback( + () => dispatch({ type: ActionType.previousPreviewPanel }), + [dispatch] + ); + + const closePanels = useCallback(() => dispatch({ type: ActionType.closeFlyout }), [dispatch]); + + const contextValue = useMemo( + () => ({ + panels: state, + openFlyout: openPanels, + openRightPanel, + openLeftPanel, + openPreviewPanel, + closeRightPanel, + closeLeftPanel, + closePreviewPanel, + closeFlyout: closePanels, + previousPreviewPanel, + }), + [ + state, + openPanels, + openRightPanel, + openLeftPanel, + openPreviewPanel, + closeRightPanel, + closeLeftPanel, + closePreviewPanel, + closePanels, + previousPreviewPanel, + ] + ); + + return ( + + {children} + + ); +}; + +/** + * Retrieve context's properties + */ +export const useExpandableFlyoutContext = (): ExpandableFlyoutContext => { + const contextValue = useContext(ExpandableFlyoutContext); + + if (!contextValue) { + throw new Error( + 'ExpandableFlyoutContext can only be used within ExpandableFlyoutContext provider' + ); + } + + return contextValue; +}; diff --git a/packages/kbn-expandable-flyout/src/index.test.tsx b/packages/kbn-expandable-flyout/src/index.test.tsx new file mode 100644 index 0000000000000..fd1d1990ffbad --- /dev/null +++ b/packages/kbn-expandable-flyout/src/index.test.tsx @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { Panel } from './types'; +import { ExpandableFlyout } from '.'; +import { LEFT_SECTION, PREVIEW_SECTION, RIGHT_SECTION } from './components/test_ids'; +import { ExpandableFlyoutContext } from './context'; + +describe('ExpandableFlyout', () => { + const registeredPanels: Panel[] = [ + { + key: 'key', + width: 500, + component: () =>
{'component'}
, + }, + ]; + const onClose = () => window.alert('closed'); + + it(`shouldn't render flyout if no panels`, () => { + const context: ExpandableFlyoutContext = { + panels: { + right: undefined, + left: undefined, + preview: [], + }, + } as unknown as ExpandableFlyoutContext; + + const result = render( + + + + ); + + expect(result.asFragment()).toMatchInlineSnapshot(``); + }); + + it('should render right section', () => { + const context: ExpandableFlyoutContext = { + panels: { + right: { + id: 'key', + }, + left: {}, + preview: [], + }, + } as unknown as ExpandableFlyoutContext; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId(RIGHT_SECTION)).toBeInTheDocument(); + }); + + it('should render left section', () => { + const context: ExpandableFlyoutContext = { + panels: { + right: {}, + left: { + id: 'key', + }, + preview: [], + }, + } as unknown as ExpandableFlyoutContext; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId(LEFT_SECTION)).toBeInTheDocument(); + }); + + it('should render preview section', () => { + const context: ExpandableFlyoutContext = { + panels: { + right: {}, + left: {}, + preview: [ + { + id: 'key', + }, + ], + }, + } as unknown as ExpandableFlyoutContext; + + const { getByTestId } = render( + + + + ); + + expect(getByTestId(PREVIEW_SECTION)).toBeInTheDocument(); + }); +}); diff --git a/packages/kbn-expandable-flyout/src/index.tsx b/packages/kbn-expandable-flyout/src/index.tsx new file mode 100644 index 0000000000000..80dd1d425f2a2 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/index.tsx @@ -0,0 +1,113 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useCallback, useMemo } from 'react'; +import { css } from '@emotion/react'; +import type { EuiFlyoutProps } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlyout } from '@elastic/eui'; +import { useExpandableFlyoutContext } from './context'; +import { PreviewSection } from './components/preview_section'; +import { RightSection } from './components/right_section'; +import type { FlyoutPanel, Panel } from './types'; +import { LeftSection } from './components/left_section'; + +export interface ExpandableFlyoutProps extends EuiFlyoutProps { + /** + * List of all registered panels available for render + */ + registeredPanels: Panel[]; + /** + * Propagate out EuiFlyout onClose event + */ + handleOnFlyoutClosed?: () => void; +} + +/** + * Expandable flyout UI React component. + * Displays 3 sections (right, left, preview) depending on the panels in the context. + */ +export const ExpandableFlyout: React.FC = ({ + registeredPanels, + handleOnFlyoutClosed, + ...flyoutProps +}) => { + const { panels, closeFlyout } = useExpandableFlyoutContext(); + const { left, right, preview } = panels; + + const onClose = useCallback(() => { + if (handleOnFlyoutClosed) handleOnFlyoutClosed(); + closeFlyout(); + }, [closeFlyout, handleOnFlyoutClosed]); + + const leftSection = useMemo( + () => registeredPanels.find((panel) => panel.key === left?.id), + [left, registeredPanels] + ); + + const rightSection = useMemo( + () => registeredPanels.find((panel) => panel.key === right?.id), + [right, registeredPanels] + ); + + // retrieve the last preview panel (most recent) + const mostRecentPreview = preview ? preview[preview.length - 1] : undefined; + const showBackButton = preview && preview.length > 1; + const previewSection = useMemo( + () => registeredPanels.find((panel) => panel.key === mostRecentPreview?.id), + [mostRecentPreview, registeredPanels] + ); + + // do not add the flyout to the dom if there aren't any panels to display + if (!left && !right && !preview.length) { + return <>; + } + + const width: number = (leftSection?.width ?? 0) + (rightSection?.width ?? 0); + + return ( + + + {leftSection && left ? ( + + ) : null} + {rightSection && right ? ( + + ) : null} + + + {previewSection && preview ? ( + + ) : null} + + ); +}; + +ExpandableFlyout.displayName = 'ExpandableFlyout'; diff --git a/packages/kbn-expandable-flyout/src/reducer.test.ts b/packages/kbn-expandable-flyout/src/reducer.test.ts new file mode 100644 index 0000000000000..21128ded7b58e --- /dev/null +++ b/packages/kbn-expandable-flyout/src/reducer.test.ts @@ -0,0 +1,417 @@ +/* + * Copyright 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 { FlyoutPanel } from './types'; +import { initialState, reducer, State } from './reducer'; +import { Action, ActionType } from './actions'; + +const rightPanel1: FlyoutPanel = { + id: 'right1', + path: ['path'], +}; +const leftPanel1: FlyoutPanel = { + id: 'left1', + params: { id: 'id' }, +}; +const previewPanel1: FlyoutPanel = { + id: 'preview1', + state: { id: 'state' }, +}; + +const rightPanel2: FlyoutPanel = { + id: 'right2', + path: ['path'], +}; +const leftPanel2: FlyoutPanel = { + id: 'left2', + params: { id: 'id' }, +}; +const previewPanel2: FlyoutPanel = { + id: 'preview2', + state: { id: 'state' }, +}; +describe('reducer', () => { + describe('should handle openFlyout action', () => { + it('should add panels to empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.openFlyout, + payload: { + right: rightPanel1, + left: leftPanel1, + preview: previewPanel1, + }, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }); + }); + + it('should override all panels in the state', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1, { id: 'preview' }], + }; + const action: Action = { + type: ActionType.openFlyout, + payload: { + right: rightPanel2, + left: leftPanel2, + preview: previewPanel2, + }, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel2, + right: rightPanel2, + preview: [previewPanel2], + }); + }); + + it('should remove all panels despite only passing a single section ', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.openFlyout, + payload: { + right: rightPanel2, + }, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: undefined, + right: rightPanel2, + preview: [], + }); + }); + }); + + describe('should handle openRightPanel action', () => { + it('should add right panel to empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.openRightPanel, + payload: rightPanel1, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: undefined, + right: rightPanel1, + preview: [], + }); + }); + + it('should replace right panel', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.openRightPanel, + payload: rightPanel2, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel1, + right: rightPanel2, + preview: [previewPanel1], + }); + }); + }); + + describe('should handle openLeftPanel action', () => { + it('should add left panel to empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.openLeftPanel, + payload: leftPanel1, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel1, + right: undefined, + preview: [], + }); + }); + + it('should replace only left panel', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.openLeftPanel, + payload: leftPanel2, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel2, + right: rightPanel1, + preview: [previewPanel1], + }); + }); + }); + + describe('should handle openPreviewPanel action', () => { + it('should add preview panel to empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.openPreviewPanel, + payload: previewPanel1, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: undefined, + right: undefined, + preview: [previewPanel1], + }); + }); + + it('should add preview panel to the list of preview panels', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.openPreviewPanel, + payload: previewPanel2, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1, previewPanel2], + }); + }); + }); + + describe('should handle closeRightPanel action', () => { + it('should return empty state when removing right panel from empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.closeRightPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it(`should return unmodified state when removing right panel when no right panel exist`, () => { + const state: State = { + left: leftPanel1, + right: undefined, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.closeRightPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it('should remove right panel', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.closeRightPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel1, + right: undefined, + preview: [previewPanel1], + }); + }); + }); + + describe('should handle closeLeftPanel action', () => { + it('should return empty state when removing left panel on empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.closeLeftPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it(`should return unmodified state when removing left panel when no left panel exist`, () => { + const state: State = { + left: undefined, + right: rightPanel1, + preview: [], + }; + const action: Action = { + type: ActionType.closeLeftPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it('should remove left panel', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.closeLeftPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: undefined, + right: rightPanel1, + preview: [previewPanel1], + }); + }); + }); + + describe('should handle closePreviewPanel action', () => { + it('should return empty state when removing preview panel on empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.closePreviewPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it(`should return unmodified state when removing preview panel when no preview panel exist`, () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [], + }; + const action: Action = { + type: ActionType.closePreviewPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it('should remove all preview panels', () => { + const state: State = { + left: rightPanel1, + right: leftPanel1, + preview: [previewPanel1, previewPanel2], + }; + const action: Action = { + type: ActionType.closePreviewPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: rightPanel1, + right: leftPanel1, + preview: [], + }); + }); + }); + + describe('should handle previousPreviewPanel action', () => { + it('should return empty state when previous preview panel on an empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.previousPreviewPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it(`should return unmodified state when previous preview panel when no preview panel exist`, () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [], + }; + const action: Action = { + type: ActionType.previousPreviewPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(state); + }); + + it('should remove only last preview panel', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1, previewPanel2], + }; + const action: Action = { + type: ActionType.previousPreviewPanel, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }); + }); + }); + + describe('should handle closeFlyout action', () => { + it('should return empty state when closing flyout on an empty state', () => { + const state: State = initialState; + const action: Action = { + type: ActionType.closeFlyout, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual(initialState); + }); + + it('should remove all panels', () => { + const state: State = { + left: leftPanel1, + right: rightPanel1, + preview: [previewPanel1], + }; + const action: Action = { + type: ActionType.closeFlyout, + }; + const newState: State = reducer(state, action); + + expect(newState).toEqual({ + left: undefined, + right: undefined, + preview: [], + }); + }); + }); +}); diff --git a/packages/kbn-expandable-flyout/src/reducer.ts b/packages/kbn-expandable-flyout/src/reducer.ts new file mode 100644 index 0000000000000..4901eccfc6bb4 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/reducer.ts @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { FlyoutPanel } from './types'; +import { Action, ActionType } from './actions'; + +export interface State { + /** + * Panel to render in the left section + */ + left: FlyoutPanel | undefined; + /** + * Panel to render in the right section + */ + right: FlyoutPanel | undefined; + /** + * Panels to render in the preview section + */ + preview: FlyoutPanel[]; +} + +export const initialState: State = { + left: undefined, + right: undefined, + preview: [], +}; + +export function reducer(state: State, action: Action) { + switch (action.type) { + /** + * Open the flyout by replacing the entire state with new panels. + */ + case ActionType.openFlyout: { + const { left, right, preview } = action.payload; + return { + left, + right, + preview: preview ? [preview] : [], + }; + } + + /** + * Opens a right section by replacing the previous right panel with the new one. + */ + case ActionType.openRightPanel: { + return { ...state, right: action.payload }; + } + + /** + * Opens a left section by replacing the previous left panel with the new one. + */ + case ActionType.openLeftPanel: { + return { ...state, left: action.payload }; + } + + /** + * Opens a preview section by adding to the array of preview panels. + */ + case ActionType.openPreviewPanel: { + return { ...state, preview: [...state.preview, action.payload] }; + } + + /** + * Closes the right section by removing the right panel. + */ + case ActionType.closeRightPanel: { + return { ...state, right: undefined }; + } + + /** + * Close the left section by removing the left panel. + */ + case ActionType.closeLeftPanel: { + return { ...state, left: undefined }; + } + + /** + * Closes the preview section by removing all the preview panels. + */ + case ActionType.closePreviewPanel: { + return { ...state, preview: [] }; + } + + /** + * Navigates to the previous preview panel by removing the last entry in the array of preview panels. + */ + case ActionType.previousPreviewPanel: { + const p: FlyoutPanel[] = [...state.preview]; + p.pop(); + return { ...state, preview: p }; + } + + /** + * Close the flyout by removing all the panels. + */ + case ActionType.closeFlyout: { + return { + left: undefined, + right: undefined, + preview: [], + }; + } + } +} diff --git a/packages/kbn-expandable-flyout/src/types.ts b/packages/kbn-expandable-flyout/src/types.ts new file mode 100644 index 0000000000000..f526832810900 --- /dev/null +++ b/packages/kbn-expandable-flyout/src/types.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; + +export interface FlyoutPanel { + /** + * Unique key to identify the panel + */ + id: string; + /** + * Any parameters necessary for the initial requests within the flyout + */ + params?: Record; + /** + * Tracks the path for what to show in a panel. We may have multiple tabs or details..., so easiest to just use a stack + */ + path?: string[]; + /** + * Tracks visual state such as whether the panel is collapsed + */ + state?: Record; +} + +export interface Panel { + /** + * Unique key used to identify the panel + */ + key?: string; + /** + * Component to be rendered + */ + component: (props: FlyoutPanel) => React.ReactElement; + /** + * Width used when rendering the panel + */ + width: number; // TODO remove this, the width shouldn't be a property of a panel, but handled at the flyout level +} diff --git a/packages/kbn-expandable-flyout/tsconfig.json b/packages/kbn-expandable-flyout/tsconfig.json new file mode 100644 index 0000000000000..d1755389bcddc --- /dev/null +++ b/packages/kbn-expandable-flyout/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node", + "react", + "@emotion/react/types/css-prop", + "@testing-library/jest-dom", + "@testing-library/react" + ] + }, + "include": [ + "**/*.ts", + "**/*.tsx" + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + "@kbn/i18n" + ] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 6a11e26dda7ac..dd09e8ed627e5 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -668,6 +668,8 @@ "@kbn/event-log-fixture-plugin/*": ["x-pack/test/plugin_api_integration/plugins/event_log/*"], "@kbn/event-log-plugin": ["x-pack/plugins/event_log"], "@kbn/event-log-plugin/*": ["x-pack/plugins/event_log/*"], + "@kbn/expandable-flyout": ["packages/kbn-expandable-flyout"], + "@kbn/expandable-flyout/*": ["packages/kbn-expandable-flyout/*"], "@kbn/expect": ["packages/kbn-expect"], "@kbn/expect/*": ["packages/kbn-expect/*"], "@kbn/exploratory-view-example-plugin": ["x-pack/examples/exploratory_view_example"], diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 5863d525ca0f8..1b6d0bb022f9b 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -90,6 +90,10 @@ export const allowedExperimentalValues = Object.freeze({ * Enables top charts on Alerts Page */ alertsPageChartsEnabled: true, + /** + * Enables the new security flyout over the current alert details flyout + */ + securityFlyoutEnabled: false, /** * Keep DEPRECATED experimental flags that are documented to prevent failed upgrades. diff --git a/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx b/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx index f194ef0e463eb..bda2e4d8d3629 100644 --- a/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx @@ -11,6 +11,7 @@ import { EuiThemeProvider, useEuiTheme } from '@elastic/eui'; import { IS_DRAGGING_CLASS_NAME } from '@kbn/securitysolution-t-grid'; import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; import type { KibanaPageTemplateProps } from '@kbn/shared-ux-page-kibana-template'; +import { ExpandableFlyout, ExpandableFlyoutProvider } from '@kbn/expandable-flyout'; import { useSecuritySolutionNavigation } from '../../../common/components/navigation/use_security_solution_navigation'; import { TimelineId } from '../../../../common/types/timeline'; import { getTimelineShowStatusByIdSelector } from '../../../timelines/components/flyout/selectors'; @@ -80,34 +81,35 @@ export const SecuritySolutionTemplateWrapper: React.FC - - - + - {children} - - - {isTimelineBottomBarVisible && ( - - - - - - )} - + + + {children} + + {isTimelineBottomBarVisible && ( + + + + + + )} + {}} /> + + ); }); diff --git a/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx b/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx index c41eaba862c9c..a7b3395c12c5a 100644 --- a/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/control_columns/row_action/index.tsx @@ -8,6 +8,7 @@ import type { EuiDataGridCellValueElementProps } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { useDispatch } from 'react-redux'; +import { useExpandableFlyoutContext } from '@kbn/expandable-flyout'; import type { SetEventsDeleted, SetEventsLoading, @@ -19,6 +20,7 @@ import { getMappedNonEcsValue } from '../../../../timelines/components/timeline/ import type { TimelineItem, TimelineNonEcsData } from '../../../../../common/search_strategy'; import type { ColumnHeaderOptions, OnRowSelected } from '../../../../../common/types/timeline'; import { dataTableActions } from '../../../store/data_table'; +import { useIsExperimentalFeatureEnabled } from '../../../hooks/use_experimental_features'; type Props = EuiDataGridCellValueElementProps & { columnHeaders: ColumnHeaderOptions[]; @@ -64,7 +66,10 @@ const RowActionComponent = ({ }: Props) => { const { data: timelineNonEcsData, ecs: ecsData, _id: eventId, _index: indexName } = data ?? {}; + const { openFlyout } = useExpandableFlyoutContext(); + const dispatch = useDispatch(); + const isSecurityFlyoutEnabled = useIsExperimentalFeatureEnabled('securityFlyoutEnabled'); const columnValues = useMemo( () => @@ -90,14 +95,18 @@ const RowActionComponent = ({ }, }; - dispatch( - dataTableActions.toggleDetailPanel({ - ...updatedExpandedDetail, - tabType, - id: tableId, - }) - ); - }, [dispatch, eventId, indexName, tabType, tableId]); + if (isSecurityFlyoutEnabled) { + openFlyout({}); + } else { + dispatch( + dataTableActions.toggleDetailPanel({ + ...updatedExpandedDetail, + tabType, + id: tableId, + }) + ); + } + }, [dispatch, eventId, indexName, isSecurityFlyoutEnabled, openFlyout, tabType, tableId]); const Action = controlColumn.rowCellRender; diff --git a/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx b/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx index 5761e98dbe366..d0901071063ab 100644 --- a/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/test_providers.tsx @@ -20,6 +20,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import type { Action } from '@kbn/ui-actions-plugin/public'; import { CellActionsProvider } from '@kbn/cell-actions'; +import { ExpandableFlyoutProvider } from '@kbn/expandable-flyout'; import { ConsoleManager } from '../../management/components/console'; import type { State } from '../store'; import { createStore } from '../store'; @@ -66,13 +67,15 @@ export const TestProvidersComponent: React.FC = ({ ({ eui: euiDarkVars, darkMode: true })}> - - Promise.resolve(cellActions)} - > - {children} - - + + + Promise.resolve(cellActions)} + > + {children} + + + diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index dada95f662bbd..373c561888a23 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -142,5 +142,6 @@ "@kbn/cell-actions", "@kbn/shared-ux-router", "@kbn/alerts-as-data-utils", + "@kbn/expandable-flyout", ] } diff --git a/yarn.lock b/yarn.lock index 739e766ef4794..d5aba9da63c76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4073,6 +4073,10 @@ version "0.0.0" uid "" +"@kbn/expandable-flyout@link:packages/kbn-expandable-flyout": + version "0.0.0" + uid "" + "@kbn/expect@link:packages/kbn-expect": version "0.0.0" uid "" From a9bcdaf77b48491c157ff4203dbf6f0f621ecb6d Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 28 Feb 2023 01:03:02 -0500 Subject: [PATCH 035/131] [api-docs] 2023-02-28 Daily api_docs build (#152312) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/262 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.devdocs.json | 189 ++ api_docs/alerting.mdx | 4 +- 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.devdocs.json | 6 +- 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.devdocs.json | 1196 ++++++------- api_docs/files.mdx | 10 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.devdocs.json | 27 + 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 +- .../kbn_alerts_as_data_utils.devdocs.json | 215 +++ api_docs/kbn_alerts_as_data_utils.mdx | 36 + 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 | 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.devdocs.json | 13 + api_docs/kbn_core_node_server.mdx | 4 +- ...kbn_core_node_server_internal.devdocs.json | 60 +- api_docs/kbn_core_node_server_internal.mdx | 7 +- .../kbn_core_node_server_mocks.devdocs.json | 4 +- 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 +- ...kbn_core_root_server_internal.devdocs.json | 38 +- api_docs/kbn_core_root_server_internal.mdx | 7 +- .../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 +- ..._objects_base_server_internal.devdocs.json | 16 +- ...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 +- ...cts_migration_server_internal.devdocs.json | 194 +- ...aved_objects_migration_server_internal.mdx | 4 +- ...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.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_expandable_flyout.devdocs.json | 273 +++ api_docs/kbn_expandable_flyout.mdx | 33 + 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.devdocs.json | 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.devdocs.json | 80 +- 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 +- .../kbn_shared_ux_file_context.devdocs.json | 8 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- .../kbn_shared_ux_file_image.devdocs.json | 8 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- .../kbn_shared_ux_file_mocks.devdocs.json | 8 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- .../kbn_shared_ux_file_picker.devdocs.json | 32 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- .../kbn_shared_ux_file_types.devdocs.json | 1581 +++++++++++++++++ api_docs/kbn_shared_ux_file_types.mdx | 33 + .../kbn_shared_ux_file_upload.devdocs.json | 8 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.devdocs.json | 16 +- 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.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.devdocs.json | 8 +- api_docs/observability.mdx | 2 +- api_docs/osquery.devdocs.json | 4 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 23 +- 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 | 16 +- 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.devdocs.json | 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.devdocs.json | 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 | 4 +- 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 +- 507 files changed, 3736 insertions(+), 1377 deletions(-) create mode 100644 api_docs/kbn_alerts_as_data_utils.devdocs.json create mode 100644 api_docs/kbn_alerts_as_data_utils.mdx create mode 100644 api_docs/kbn_expandable_flyout.devdocs.json create mode 100644 api_docs/kbn_expandable_flyout.mdx create mode 100644 api_docs/kbn_shared_ux_file_types.devdocs.json create mode 100644 api_docs/kbn_shared_ux_file_types.mdx diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 786d5ef0ebff9..0b8e633709e11 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-27 +date: 2023-02-28 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 6b5482bad9600..923c752e5b8ee 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-27 +date: 2023-02-28 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 6bf96b8b294b8..7570552b45d10 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-27 +date: 2023-02-28 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 0a9c5b5718503..016e965013dfe 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -867,6 +867,69 @@ } ], "functions": [ + { + "parentPluginId": "alerting", + "id": "def-server.getComponentTemplate", + "type": "Function", + "tags": [], + "label": "getComponentTemplate", + "description": [], + "signature": [ + "(fieldMap: ", + { + "pluginId": "@kbn/alerts-as-data-utils", + "scope": "common", + "docId": "kibKbnAlertsAsDataUtilsPluginApi", + "section": "def-common.FieldMap", + "text": "FieldMap" + }, + ", context?: string | undefined) => ", + "ClusterPutComponentTemplateRequest" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-server.getComponentTemplate.$1", + "type": "Object", + "tags": [], + "label": "fieldMap", + "description": [], + "signature": [ + { + "pluginId": "@kbn/alerts-as-data-utils", + "scope": "common", + "docId": "kibKbnAlertsAsDataUtilsPluginApi", + "section": "def-common.FieldMap", + "text": "FieldMap" + } + ], + "path": "x-pack/plugins/alerting/server/alerts_service/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "alerting", + "id": "def-server.getComponentTemplate.$2", + "type": "string", + "tags": [], + "label": "context", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-server.getEsErrorMessage", @@ -3239,6 +3302,33 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "alerting", + "id": "def-server.ECS_COMPONENT_TEMPLATE_NAME", + "type": "string", + "tags": [], + "label": "ECS_COMPONENT_TEMPLATE_NAME", + "description": [], + "path": "x-pack/plugins/alerting/server/alerts_service/alerts_service.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "alerting", + "id": "def-server.ECS_CONTEXT", + "type": "string", + "tags": [], + "label": "ECS_CONTEXT", + "description": [], + "signature": [ + "\"ecs\"" + ], + "path": "x-pack/plugins/alerting/server/alerts_service/alerts_service.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-server.ExecutorType", @@ -3938,6 +4028,42 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "alerting", + "id": "def-common.getComponentTemplateFromFieldMap", + "type": "Function", + "tags": [], + "label": "getComponentTemplateFromFieldMap", + "description": [], + "signature": [ + "({ name, fieldMap, fieldLimit, }: ", + "GetComponentTemplateFromFieldMapOpts", + ") => ", + "ClusterPutComponentTemplateRequest" + ], + "path": "x-pack/plugins/alerting/common/alert_schema/field_maps/component_template_from_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-common.getComponentTemplateFromFieldMap.$1", + "type": "Object", + "tags": [], + "label": "{\n name,\n fieldMap,\n fieldLimit,\n}", + "description": [], + "signature": [ + "GetComponentTemplateFromFieldMapOpts" + ], + "path": "x-pack/plugins/alerting/common/alert_schema/field_maps/component_template_from_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-common.getDurationNumberInItsUnit", @@ -4052,6 +4178,69 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "alerting", + "id": "def-common.mappingFromFieldMap", + "type": "Function", + "tags": [], + "label": "mappingFromFieldMap", + "description": [], + "signature": [ + "(fieldMap: ", + { + "pluginId": "@kbn/alerts-as-data-utils", + "scope": "common", + "docId": "kibKbnAlertsAsDataUtilsPluginApi", + "section": "def-common.FieldMap", + "text": "FieldMap" + }, + ", dynamic: boolean | \"strict\") => ", + "MappingTypeMapping" + ], + "path": "x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "alerting", + "id": "def-common.mappingFromFieldMap.$1", + "type": "Object", + "tags": [], + "label": "fieldMap", + "description": [], + "signature": [ + { + "pluginId": "@kbn/alerts-as-data-utils", + "scope": "common", + "docId": "kibKbnAlertsAsDataUtilsPluginApi", + "section": "def-common.FieldMap", + "text": "FieldMap" + } + ], + "path": "x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "alerting", + "id": "def-common.mappingFromFieldMap.$2", + "type": "CompoundType", + "tags": [], + "label": "dynamic", + "description": [], + "signature": [ + "boolean | \"strict\"" + ], + "path": "x-pack/plugins/alerting/common/alert_schema/field_maps/mapping_from_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "alerting", "id": "def-common.parseDuration", diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index be7ba2627c4d1..896d6335b1e48 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-27 +date: 2023-02-28 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 | |-------------------|-----------|------------------------|-----------------| -| 487 | 1 | 476 | 40 | +| 497 | 1 | 486 | 41 | ## Client diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 1be070da0fd6c..064ab9c52e28f 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-27 +date: 2023-02-28 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 404ec374f5d93..0d3965826809e 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-27 +date: 2023-02-28 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 5c2d6f7fd9abf..e742fdf8dfc18 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-27 +date: 2023-02-28 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 7caa2bc00fb8b..32b1952cafdd8 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-27 +date: 2023-02-28 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 3ab0fa50805ff..1ed8c149e896c 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-27 +date: 2023-02-28 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 122899a005d34..9d36327064aec 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-27 +date: 2023-02-28 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 b4e6fecfc3cca..659b85d1d7b28 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-27 +date: 2023-02-28 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 a470cd5439021..9f42c75ffb3e9 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-27 +date: 2023-02-28 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 a901c6b14ae16..3809b2b6a701f 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-27 +date: 2023-02-28 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 a75eaeb7a2b0b..da868144c7618 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-27 +date: 2023-02-28 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 ea6376cd43bee..4bb90591915e0 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-27 +date: 2023-02-28 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 f065f7c6053c8..284069b14370d 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-27 +date: 2023-02-28 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 e008179a519e2..e8e668d7e0993 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-27 +date: 2023-02-28 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 f14ff89397cde..7b367b913e7e1 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-27 +date: 2023-02-28 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 99a0b87121e18..92cff1862b49c 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-27 +date: 2023-02-28 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 f011348359e18..00fd8abf5d551 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-27 +date: 2023-02-28 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 b341979bce4f1..6f7f587f59345 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-27 +date: 2023-02-28 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 f84933f0b1b4e..2c0a9a906d5d2 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-27 +date: 2023-02-28 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 717733b31880f..1e4c203e60816 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-27 +date: 2023-02-28 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 2eb4ba583ca7d..5480e56f276a5 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-27 +date: 2023-02-28 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 55145af95934b..c2771042aa461 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-27 +date: 2023-02-28 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 2c803c9c2d839..75735009f549a 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-27 +date: 2023-02-28 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 79135b32e8e81..f1e63364df52b 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-27 +date: 2023-02-28 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 b685ec997b5d0..991044de8198b 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-27 +date: 2023-02-28 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 0ca6b88b3bb74..9d6efbcd459f6 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-27 +date: 2023-02-28 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 12a25580eb6e2..4f8549bfe3799 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-27 +date: 2023-02-28 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 ed6456585150b..a4f0482e3da88 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 90479084fc698..6a179d1e6e930 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index a4257edc748df..729cc3299b1a5 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index ccf63dda93828..c6ba017a7eea2 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-27 +date: 2023-02-28 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 ddef23b4a631e..928f2d7a7c7b2 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-27 +date: 2023-02-28 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 28887555fed58..e54cece7c8f15 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-27 +date: 2023-02-28 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 36b3d4dcf7acb..686c30001f9f2 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-27 +date: 2023-02-28 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 a86f88c5770a3..e073454315134 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-27 +date: 2023-02-28 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 c6159057905f2..6932c93c6692c 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-27 +date: 2023-02-28 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 915fbca25d243..eb2d18465b28d 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-27 +date: 2023-02-28 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 ac199094d61f5..b2441359f4430 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-27 +date: 2023-02-28 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 93f25aafbaab0..2001eb24562a0 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-27 +date: 2023-02-28 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 9dc9bbfad5134..b8fda3d5517fc 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_log.devdocs.json b/api_docs/event_log.devdocs.json index 960b7a226d30c..ef90f20d24aa0 100644 --- a/api_docs/event_log.devdocs.json +++ b/api_docs/event_log.devdocs.json @@ -1514,7 +1514,7 @@ "label": "data", "description": [], "signature": [ - "(Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; description?: string | undefined; category?: string | undefined; version?: string | undefined; uuid?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; rel?: string | undefined; namespace?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; id?: string | undefined; start?: string | undefined; end?: string | undefined; category?: string[] | undefined; outcome?: string | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; severity?: string | number | undefined; duration?: string | number | undefined; original?: string | undefined; dataset?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; } & {}> | undefined)[]" + "(Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; description?: string | undefined; category?: string | undefined; version?: string | undefined; uuid?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; rel?: string | undefined; namespace?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; id?: string | undefined; start?: string | undefined; end?: string | undefined; category?: string[] | undefined; outcome?: string | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; severity?: string | number | undefined; duration?: string | number | undefined; original?: string | undefined; dataset?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; } & {}> | undefined)[]" ], "path": "x-pack/plugins/event_log/server/es/cluster_client_adapter.ts", "deprecated": false, @@ -1534,7 +1534,7 @@ "label": "IEvent", "description": [], "signature": [ - "DeepPartial | undefined; error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; description?: string | undefined; category?: string | undefined; version?: string | undefined; uuid?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; rel?: string | undefined; namespace?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; id?: string | undefined; start?: string | undefined; end?: string | undefined; category?: string[] | undefined; outcome?: string | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; severity?: string | number | undefined; duration?: string | number | undefined; original?: string | undefined; dataset?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; } & {}>>> | undefined" + "DeepPartial | undefined; error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; description?: string | undefined; category?: string | undefined; version?: string | undefined; uuid?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; rel?: string | undefined; namespace?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; id?: string | undefined; start?: string | undefined; end?: string | undefined; category?: string[] | undefined; outcome?: string | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; severity?: string | number | undefined; duration?: string | number | undefined; original?: string | undefined; dataset?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; } & {}>>> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, @@ -1549,7 +1549,7 @@ "label": "IValidatedEvent", "description": [], "signature": [ - "Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; description?: string | undefined; category?: string | undefined; version?: string | undefined; uuid?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; rel?: string | undefined; namespace?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; id?: string | undefined; start?: string | undefined; end?: string | undefined; category?: string[] | undefined; outcome?: string | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; severity?: string | number | undefined; duration?: string | number | undefined; original?: string | undefined; dataset?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; } & {}> | undefined" + "Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ type?: string | undefined; id?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; description?: string | undefined; category?: string | undefined; version?: string | undefined; uuid?: string | undefined; license?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; status?: string | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; execution?: Readonly<{ uuid?: string | undefined; metrics?: Readonly<{ number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_searches?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; es_search_duration_ms?: string | number | undefined; total_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status?: string | undefined; status_order?: string | number | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; flapping?: boolean | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; saved_objects?: Readonly<{ type?: string | undefined; id?: string | undefined; rel?: string | undefined; namespace?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; id?: string | undefined; start?: string | undefined; end?: string | undefined; category?: string[] | undefined; outcome?: string | undefined; code?: string | undefined; url?: string | undefined; created?: string | undefined; severity?: string | number | undefined; duration?: string | number | undefined; original?: string | undefined; dataset?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score?: number | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; timezone?: string | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ name?: string | undefined; } & {}> | undefined; } & {}> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 77e029e48299c..dbada9b2dfca3 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-27 +date: 2023-02-28 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 d2cde25c51a23..6622e021130e7 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-27 +date: 2023-02-28 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 11d527ee9f30b..8b15b75e8abbd 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-27 +date: 2023-02-28 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 04dbccdf0997f..908f94186daf1 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-27 +date: 2023-02-28 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 286140f0d24b6..3765e915e81df 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-27 +date: 2023-02-28 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 95c8fae0e37c9..654925d8dc2ce 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-27 +date: 2023-02-28 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 692a945b7e667..668becba901ef 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-27 +date: 2023-02-28 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 a15b827070bde..b0dc76f0b6f76 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-27 +date: 2023-02-28 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 192785384e81e..fd80d1a9b4784 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-27 +date: 2023-02-28 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 73e7aa1f1b7e5..cc220ea04321b 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-27 +date: 2023-02-28 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 caf5c83c2ab06..fee9dda3d70c3 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-27 +date: 2023-02-28 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 7ea256e85e08d..bf5da43e550bc 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-27 +date: 2023-02-28 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 247988910c3e6..b982d403d0459 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-27 +date: 2023-02-28 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 b3424677d1306..6a3d62bd53b91 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-27 +date: 2023-02-28 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 fc26a51f9c653..5fa1a549697f1 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-27 +date: 2023-02-28 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 5ef6733937074..d8ac383049b86 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-27 +date: 2023-02-28 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 8bea1b1e8715d..c48d1e9a662a6 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-27 +date: 2023-02-28 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 e8f573925ec16..8e93da50c1e5a 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.devdocs.json b/api_docs/files.devdocs.json index 462d19625454f..3c2201044be35 100644 --- a/api_docs/files.devdocs.json +++ b/api_docs/files.devdocs.json @@ -16,7 +16,13 @@ "signature": [ "FilesClient", " extends ", - "BaseFilesClient", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.BaseFilesClient", + "text": "BaseFilesClient" + }, "" ], "path": "src/plugins/files/common/files_client.ts", @@ -203,17 +209,77 @@ "text": "FilesMetrics" }, "; publicDownload: any; find: { files: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "[]; total: number; }; bulkDelete: { succeeded: string[]; failed?: [id: string, reason: string][] | undefined; }; create: { file: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "; }; delete: { ok: true; }; getById: { file: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "; }; list: { files: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "[]; total: number; }; update: { file: ", - "FileJSON", - "; }; upload: { ok: true; size: number; }; download: any; getDownloadHref: string; share: any; unshare: { ok: true; }; getShare: { share: FileShareJSON; }; listShares: { shares: FileShareJSON[]; }; getFileKind: ", - "FileKind", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + "; }; upload: { ok: true; size: number; }; download: any; getDownloadHref: string; share: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" + }, + " & { token: string; }; unshare: { ok: true; }; getShare: { share: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" + }, + "; }; listShares: { shares: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" + }, + "[]; }; getFileKind: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBase", + "text": "FileKindBase" + }, "; }" ], "path": "src/plugins/files/common/files_client.ts", @@ -240,332 +306,222 @@ "text": "FilesMetrics" }, ">; publicDownload: (arg: Omit<{ token: string; fileName?: string | undefined; }, \"kind\">) => any; find: (arg: Omit<{ kind?: string | string[] | undefined; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", - "Pagination", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, " & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ files: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "[]; total: number; }>; bulkDelete: (arg: Omit<{ ids: string[]; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ succeeded: string[]; failed?: [id: string, reason: string][] | undefined; }>; create: (arg: Omit<{ name: string; meta?: M | undefined; alt?: string | undefined; mimeType?: string | undefined; kind: string; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ file: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "; }>; delete: (arg: Omit<{ id: string; kind: string; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ ok: true; }>; getById: (arg: Omit<{ id: string; kind: string; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ file: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "; }>; list: (arg?: Omit<{ kind: string; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", - "Pagination", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, " & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\"> | undefined) => Promise<{ files: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "[]; total: number; }>; update: (arg: Omit<{ id: string; kind: string; name?: string | undefined; meta?: M | undefined; alt?: string | undefined; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ file: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "; }>; upload: (arg: Omit<{ id: string; body: unknown; kind: string; abortSignal?: AbortSignal | undefined; contentType?: string | undefined; selfDestructOnAbort?: boolean | undefined; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ ok: true; size: number; }>; download: (arg: Omit<{ fileName?: string | undefined; id: string; kind: string; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise; getDownloadHref: (arg: Omit, \"id\" | \"fileKind\">, \"kind\">) => string; share: (arg: Omit<{ name?: string | undefined; validUntil?: number | undefined; fileId: string; kind: string; } & ", - "Abortable", - ", \"kind\">) => Promise; unshare: (arg: Omit<{ id: string; kind: string; } & ", - "Abortable", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ", \"kind\">) => Promise<", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSONWithToken", + "text": "FileShareJSONWithToken" + }, + ">; unshare: (arg: Omit<{ id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, ", \"kind\">) => Promise<{ ok: true; }>; getShare: (arg: Omit<{ id: string; kind: string; } & ", - "Abortable", - ", \"kind\">) => Promise<{ share: FileShareJSON; }>; listShares: (arg: Omit<{ forFileId?: string | undefined; kind: string; } & ", - "Pagination", - " & ", - "Abortable", - ", \"kind\">) => Promise<{ shares: FileShareJSON[]; }>; getFileKind: (arg: Omit) => ", - "FileKind", - "; }" - ], - "path": "src/plugins/files/common/files_client.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], - "objects": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind", - "type": "Object", - "tags": [], - "label": "defaultImageFileKind", - "description": [ - "\nA file kind that is available to all plugins to use for uploading images\nintended to be reused across Kibana." - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "signature": [ - "\"defaultImage\"" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" }, + ", \"kind\">) => Promise<{ share: ", { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.maxSizeBytes", - "type": "number", - "tags": [], - "label": "maxSizeBytes", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" }, + "; }>; listShares: (arg: Omit<{ forFileId?: string | undefined; kind: string; } & ", { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.blobStoreSettings", - "type": "Object", - "tags": [], - "label": "blobStoreSettings", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [] + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" }, + " & ", { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.allowedMimeTypes", - "type": "Array", - "tags": [], - "label": "allowedMimeTypes", - "description": [ - "// tried using \"image/*\" but it did not work with the HTTP endpoint (got 415 Unsupported Media Type)" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" }, + ", \"kind\">) => Promise<{ shares: ", { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.create", - "type": "Object", - "tags": [], - "label": "create", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.create.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.delete", - "type": "Object", - "tags": [], - "label": "delete", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.delete.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.download", - "type": "Object", - "tags": [], - "label": "download", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.download.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.getById", - "type": "Object", - "tags": [], - "label": "getById", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.getById.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.list", - "type": "Object", - "tags": [], - "label": "list", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.list.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.share", - "type": "Object", - "tags": [], - "label": "share", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.share.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.update", - "type": "Object", - "tags": [], - "label": "update", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-public.defaultImageFileKind.http.update.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ] - } + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" + }, + "[]; }>; getFileKind: (arg: Omit) => ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBase", + "text": "FileKindBase" + }, + "; }" ], + "path": "src/plugins/files/common/files_client.ts", + "deprecated": false, + "trackAdoption": false, "initialIsOpen": false } ], + "objects": [], "setup": { "parentPluginId": "files", "id": "def-public.FilesSetup", @@ -588,7 +544,7 @@ ], "label": "filesClientFactory", "description": [ - "\nA factory for creating an {@link FilesClient} instance. This requires a\nregistered {@link FileKind}.\n" + "\nA factory for creating an {@link FilesClient} instance. This requires a\nregistered {@link FileKindBrowser}.\n" ], "signature": [ "FilesClientFactory" @@ -618,7 +574,13 @@ ], "signature": [ "(fileKind: ", - "FileKind", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBrowser", + "text": "FileKindBrowser" + }, ") => void" ], "path": "src/plugins/files/public/plugin.ts", @@ -635,7 +597,13 @@ "- the file kind to register" ], "signature": [ - "FileKind" + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBrowser", + "text": "FileKindBrowser" + } ], "path": "src/plugins/files/public/plugin.ts", "deprecated": false, @@ -779,7 +747,7 @@ "tags": [], "label": "elasticsearchClient", "description": [ - "\nAn elasticsearch client that will be used to interact with the cluster" + "\nAn elasticsearch client that will be used to interact with the cluster." ], "signature": [ "{ create: { (this: That, params: ", @@ -1981,7 +1949,7 @@ "tags": [], "label": "maxSizeBytes", "description": [ - "\nThe maximum file size to be write" + "\nThe maximum file size to be written." ], "signature": [ "number | undefined" @@ -1997,7 +1965,7 @@ "tags": [], "label": "logger", "description": [ - "\nA logger for debuggin purposes" + "\nA logger for debugging purposes." ], "signature": [ { @@ -2615,9 +2583,9 @@ "ShareArgs", ") => Promise<", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSONWithToken", "text": "FileShareJSONWithToken" }, @@ -2706,9 +2674,9 @@ }, ") => Promise<{ shares: ", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSON", "text": "FileShareJSON" }, @@ -2793,9 +2761,21 @@ ], "signature": [ "Required> & ", - "BaseFileMetadata", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.BaseFileMetadata", + "text": "BaseFileMetadata" + }, " & { FileKind: string; Meta?: M | undefined; }" ], "path": "src/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", @@ -3514,7 +3494,13 @@ "text": "FindFileArgs" }, ") => Promise<{ files: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "[]; total: number; }>" ], "path": "src/plugins/files/server/file_service/file_service.ts", @@ -3559,9 +3545,9 @@ "signature": [ "(arg: IdArg) => Promise<", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSON", "text": "FileShareJSON" }, @@ -3610,9 +3596,9 @@ }, ") => Promise<{ shares: ", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSON", "text": "FileShareJSON" }, @@ -3667,9 +3653,9 @@ }, ") => Promise<", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShare", "text": "FileShare" }, @@ -3837,9 +3823,9 @@ "signature": [ "(arg: IdArg) => Promise<", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSON", "text": "FileShareJSON" }, @@ -3889,9 +3875,9 @@ }, ") => Promise<{ shares: ", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSON", "text": "FileShareJSON" }, @@ -3947,9 +3933,9 @@ }, ") => Promise<", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShare", "text": "FileShare" }, @@ -4404,7 +4390,13 @@ ], "signature": [ "{ name?: string | undefined; created?: string | undefined; Status?: \"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\" | undefined; Updated?: string | undefined; mime_type?: string | undefined; size?: number | undefined; hash?: { [hashName: string]: string | undefined; md5?: string | undefined; sha1?: string | undefined; sha256?: string | undefined; sha384?: string | undefined; sha512?: string | undefined; ssdeep?: string | undefined; tlsh?: string | undefined; } | undefined; user?: { name?: string | undefined; id?: string | undefined; } | undefined; extension?: string | undefined; Alt?: string | undefined; ChunkSize?: number | undefined; Compression?: ", - "FileCompression", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileCompression", + "text": "FileCompression" + }, " | undefined; FileKind?: string | undefined; Meta?: M | undefined; }" ], "path": "src/plugins/files/server/file_client/file_metadata_client/file_metadata_client.ts", @@ -4569,7 +4561,13 @@ ], "signature": [ "(fileKind: ", - "FileKind", + { + "pluginId": "files", + "scope": "common", + "docId": "kibFilesPluginApi", + "section": "def-common.FileKind", + "text": "FileKind" + }, ") => void" ], "path": "src/plugins/files/server/types.ts", @@ -4587,7 +4585,13 @@ "- the file kind to register" ], "signature": [ - "FileKind" + { + "pluginId": "files", + "scope": "common", + "docId": "kibFilesPluginApi", + "section": "def-common.FileKind", + "text": "FileKind" + } ], "path": "src/plugins/files/server/types.ts", "deprecated": false, @@ -4726,7 +4730,13 @@ "\nFile metadata in camelCase form." ], "signature": [ - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "" ], "path": "src/plugins/files/common/types.ts", @@ -4921,9 +4931,9 @@ }, " | undefined) => Promise<", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSONWithToken", "text": "FileShareJSONWithToken" }, @@ -4972,9 +4982,9 @@ "signature": [ "() => Promise<", { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSON", "text": "FileShareJSON" }, @@ -5047,7 +5057,13 @@ ], "signature": [ "() => ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "" ], "path": "src/plugins/files/common/types.ts", @@ -5069,10 +5085,16 @@ "\nAttributes of a file that represent a serialised version of the file." ], "signature": [ - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -5085,7 +5107,7 @@ "description": [ "\nUnique file ID." ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5098,7 +5120,7 @@ "description": [ "\nISO string of when this file was created" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5111,7 +5133,7 @@ "description": [ "\nISO string of when the file was updated" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5126,7 +5148,7 @@ "description": [ "\nFile name.\n" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5142,7 +5164,7 @@ "signature": [ "string | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5158,7 +5180,7 @@ "signature": [ "number | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5176,7 +5198,7 @@ "signature": [ "string | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5192,7 +5214,7 @@ "signature": [ "Meta | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5208,7 +5230,7 @@ "signature": [ "string | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5223,7 +5245,7 @@ "description": [ "\nA unique kind that governs various aspects of the file. A consumer of the\nfiles service must register a file kind and link their files to a specific\nkind.\n" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5239,7 +5261,7 @@ "signature": [ "\"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\"" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false }, @@ -5255,7 +5277,7 @@ "signature": [ "{ name?: string | undefined; id?: string | undefined; } | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false } @@ -5269,72 +5291,73 @@ "tags": [], "label": "FileKind", "description": [], - "path": "packages/shared-ux/file/types/index.d.ts", + "signature": [ + { + "pluginId": "files", + "scope": "common", + "docId": "kibFilesPluginApi", + "section": "def-common.FileKind", + "text": "FileKind" + }, + " extends ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBase", + "text": "FileKindBase" + } + ], + "path": "src/plugins/files/common/types.ts", "deprecated": false, "trackAdoption": false, "children": [ - { - "parentPluginId": "files", - "id": "def-common.FileKind.id", - "type": "string", - "tags": [], - "label": "id", - "description": [ - "\nUnique file kind ID" - ], - "path": "packages/shared-ux/file/types/index.d.ts", - "deprecated": false, - "trackAdoption": false - }, { "parentPluginId": "files", "id": "def-common.FileKind.maxSizeBytes", - "type": "number", + "type": "CompoundType", "tags": [ "default" ], "label": "maxSizeBytes", "description": [ - "\nMaximum size, in bytes, a file of this kind can be.\n" + "\nMax file contents size, in bytes. Can be customized per file using the\n{@link FileJSON} object. This is enforced on the server-side as well as\nin the upload React component.\n" ], "signature": [ - "number | undefined" - ], - "path": "packages/shared-ux/file/types/index.d.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "files", - "id": "def-common.FileKind.allowedMimeTypes", - "type": "Array", - "tags": [ - "default" - ], - "label": "allowedMimeTypes", - "description": [ - "\nThe MIME type of the file content.\n" - ], - "signature": [ - "string[] | undefined" + "number | ((file: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + ") => number) | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "src/plugins/files/common/types.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "files", "id": "def-common.FileKind.blobStoreSettings", - "type": "Any", + "type": "Object", "tags": [], "label": "blobStoreSettings", "description": [ "\nBlob store specific settings that enable configuration of storage\ndetails." ], "signature": [ - "any" + { + "pluginId": "files", + "scope": "common", + "docId": "kibFilesPluginApi", + "section": "def-common.BlobStorageSettings", + "text": "BlobStorageSettings" + }, + " | undefined" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "src/plugins/files/common/types.ts", "deprecated": false, "trackAdoption": false }, @@ -5352,7 +5375,56 @@ "signature": [ "{ create?: HttpEndpointDefinition | undefined; update?: HttpEndpointDefinition | undefined; delete?: HttpEndpointDefinition | undefined; getById?: HttpEndpointDefinition | undefined; list?: HttpEndpointDefinition | undefined; download?: HttpEndpointDefinition | undefined; share?: HttpEndpointDefinition | undefined; }" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "src/plugins/files/common/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "files", + "id": "def-common.FileKindBrowser", + "type": "Interface", + "tags": [], + "label": "FileKindBrowser", + "description": [], + "signature": [ + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBrowser", + "text": "FileKindBrowser" + }, + " extends ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBase", + "text": "FileKindBase" + } + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "files", + "id": "def-common.FileKindBrowser.maxSizeBytes", + "type": "number", + "tags": [ + "default" + ], + "label": "maxSizeBytes", + "description": [ + "\nMax file contents size, in bytes, enforced for this file kind in the upload\ncomponent.\n" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false } @@ -5368,7 +5440,7 @@ "description": [ "\nAttributes of a file that represent a serialised version of the file." ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false, "children": [ @@ -5381,7 +5453,7 @@ "description": [ "\nUnique ID share instance" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false }, @@ -5394,7 +5466,7 @@ "description": [ "\nISO timestamp the share was created" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false }, @@ -5407,7 +5479,7 @@ "description": [ "\nUnix timestamp (in milliseconds) of when this share expires" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false }, @@ -5423,7 +5495,7 @@ "signature": [ "string | undefined" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false }, @@ -5436,7 +5508,7 @@ "description": [ "\nThe ID of the file this share is linked to" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false } @@ -5648,12 +5720,24 @@ ], "signature": [ "{ name?: string | undefined; mime_type?: string | undefined; created?: string | undefined; size?: number | undefined; hash?: { [hashName: string]: string | undefined; md5?: string | undefined; sha1?: string | undefined; sha256?: string | undefined; sha384?: string | undefined; sha512?: string | undefined; ssdeep?: string | undefined; tlsh?: string | undefined; } | undefined; user?: { name?: string | undefined; id?: string | undefined; } | undefined; extension?: string | undefined; Alt?: string | undefined; Updated?: string | undefined; Status?: ", - "FileStatus", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileStatus", + "text": "FileStatus" + }, " | undefined; ChunkSize?: number | undefined; Compression?: ", - "FileCompression", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileCompression", + "text": "FileCompression" + }, " | undefined; }" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -5704,7 +5788,7 @@ "signature": [ "\"none\" | \"br\" | \"gzip\" | \"deflate\"" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -5720,12 +5804,24 @@ ], "signature": [ "Required> & ", - "BaseFileMetadata", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.BaseFileMetadata", + "text": "BaseFileMetadata" + }, " & { FileKind: string; Meta?: Meta | undefined; }" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -5748,7 +5844,13 @@ "text": "SavedObject" }, "<", - "FileMetadata", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileMetadata", + "text": "FileMetadata" + }, ">" ], "path": "src/plugins/files/common/types.ts", @@ -5768,7 +5870,7 @@ "signature": [ "{ created: string; token: string; name?: string | undefined; valid_until: number; }" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -5786,15 +5888,15 @@ ], "signature": [ { - "pluginId": "files", + "pluginId": "@kbn/shared-ux-file-types", "scope": "common", - "docId": "kibFilesPluginApi", + "docId": "kibKbnSharedUxFileTypesPluginApi", "section": "def-common.FileShareJSON", "text": "FileShareJSON" }, " & { token: string; }" ], - "path": "src/plugins/files/common/types.ts", + "path": "packages/shared-ux/file/types/sharing.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -5809,7 +5911,7 @@ "signature": [ "\"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\"" ], - "path": "packages/shared-ux/file/types/index.d.ts", + "path": "packages/shared-ux/file/types/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -5883,278 +5985,6 @@ "initialIsOpen": false } ], - "objects": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind", - "type": "Object", - "tags": [], - "label": "defaultImageFileKind", - "description": [ - "\nA file kind that is available to all plugins to use for uploading images\nintended to be reused across Kibana." - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.id", - "type": "string", - "tags": [], - "label": "id", - "description": [], - "signature": [ - "\"defaultImage\"" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.maxSizeBytes", - "type": "number", - "tags": [], - "label": "maxSizeBytes", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.blobStoreSettings", - "type": "Object", - "tags": [], - "label": "blobStoreSettings", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [] - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.allowedMimeTypes", - "type": "Array", - "tags": [], - "label": "allowedMimeTypes", - "description": [ - "// tried using \"image/*\" but it did not work with the HTTP endpoint (got 415 Unsupported Media Type)" - ], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http", - "type": "Object", - "tags": [], - "label": "http", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.create", - "type": "Object", - "tags": [], - "label": "create", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.create.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.delete", - "type": "Object", - "tags": [], - "label": "delete", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.delete.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.download", - "type": "Object", - "tags": [], - "label": "download", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.download.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.getById", - "type": "Object", - "tags": [], - "label": "getById", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.getById.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.list", - "type": "Object", - "tags": [], - "label": "list", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.list.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.share", - "type": "Object", - "tags": [], - "label": "share", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.share.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.update", - "type": "Object", - "tags": [], - "label": "update", - "description": [], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "files", - "id": "def-common.defaultImageFileKind.http.update.tags", - "type": "Array", - "tags": [], - "label": "tags", - "description": [], - "signature": [ - "string[]" - ], - "path": "src/plugins/files/common/default_image_file_kind.ts", - "deprecated": false, - "trackAdoption": false - } - ] - } - ] - } - ], - "initialIsOpen": false - } - ] + "objects": [] } } \ No newline at end of file diff --git a/api_docs/files.mdx b/api_docs/files.mdx index 5b94fadff8259..681850c64b442 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.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 | |-------------------|-----------|------------------------|-----------------| -| 254 | 1 | 45 | 5 | +| 214 | 0 | 10 | 5 | ## Client @@ -31,9 +31,6 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh ### Start -### Objects - - ### Interfaces @@ -59,9 +56,6 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh ## Common -### Objects - - ### Interfaces diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index b916774dbdb67..da7e5cf17aa8b 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-27 +date: 2023-02-28 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 f9a49b8123b49..6b022a38b7bd6 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -25180,6 +25180,17 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "fleet", + "id": "def-common.EPM_API_ROUTES.VERIFICATION_KEY_ID", + "type": "string", + "tags": [], + "label": "VERIFICATION_KEY_ID", + "description": [], + "path": "x-pack/plugins/fleet/common/constants/routes.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "fleet", "id": "def-common.EPM_API_ROUTES.STATS_PATTERN", @@ -25238,6 +25249,22 @@ "deprecated": false, "trackAdoption": false, "children": [ + { + "parentPluginId": "fleet", + "id": "def-common.epmRouteService.getVerificationKeyIdPath", + "type": "Function", + "tags": [], + "label": "getVerificationKeyIdPath", + "description": [], + "signature": [ + "() => string" + ], + "path": "x-pack/plugins/fleet/common/services/routes.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-common.epmRouteService.getCategoriesPath", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 75c2497452fab..e605c7ee935e0 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-27 +date: 2023-02-28 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 | |-------------------|-----------|------------------------|-----------------| -| 1087 | 3 | 982 | 27 | +| 1089 | 3 | 984 | 27 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 63bc515caf0ed..4cd3f5543c815 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-27 +date: 2023-02-28 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 062c0047405d4..ccd8dc54f268d 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-27 +date: 2023-02-28 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 768a848a4aab2..6e9c53480fdae 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-27 +date: 2023-02-28 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 4780f3b4c14be..fa1b8a61ad548 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-27 +date: 2023-02-28 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 c97553b7c1299..bb61d5ca51b3f 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-27 +date: 2023-02-28 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 3a58461fc3584..5dc3493807348 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-27 +date: 2023-02-28 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 18968689e11dd..1bce234957b6d 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-27 +date: 2023-02-28 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 d439b28ace1d2..894e811cb6f8f 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-27 +date: 2023-02-28 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 626a3739cfdc0..d575dd2ad8d69 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-27 +date: 2023-02-28 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 0fa12f26cf43e..6daa5009ec5ce 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-27 +date: 2023-02-28 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 4824f734f9101..938b5bd49c8b0 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-27 +date: 2023-02-28 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 dc8cac3bee834..15a61db6deb96 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-27 +date: 2023-02-28 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 d42a9f6a264a9..317fbd1e1da7c 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.devdocs.json b/api_docs/kbn_alerts_as_data_utils.devdocs.json new file mode 100644 index 0000000000000..b5390c5044148 --- /dev/null +++ b/api_docs/kbn_alerts_as_data_utils.devdocs.json @@ -0,0 +1,215 @@ +{ + "id": "@kbn/alerts-as-data-utils", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.FieldMap", + "type": "Interface", + "tags": [], + "label": "FieldMap", + "description": [], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.FieldMap.Unnamed", + "type": "IndexSignature", + "tags": [], + "label": "[key: string]: { type: string; required: boolean; array?: boolean | undefined; doc_values?: boolean | undefined; enabled?: boolean | undefined; format?: string | undefined; ignore_above?: number | undefined; ... 4 more ...; dynamic?: boolean | ... 1 more ... | undefined; }", + "description": [], + "signature": [ + "[key: string]: { type: string; required: boolean; array?: boolean | undefined; doc_values?: boolean | undefined; enabled?: boolean | undefined; format?: string | undefined; ignore_above?: number | undefined; multi_fields?: ", + { + "pluginId": "@kbn/alerts-as-data-utils", + "scope": "common", + "docId": "kibKbnAlertsAsDataUtilsPluginApi", + "section": "def-common.MultiField", + "text": "MultiField" + }, + "[] | undefined; index?: boolean | undefined; path?: string | undefined; scaling_factor?: number | undefined; dynamic?: boolean | \"strict\" | undefined; }" + ], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.MultiField", + "type": "Interface", + "tags": [], + "label": "MultiField", + "description": [], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.MultiField.flat_name", + "type": "string", + "tags": [], + "label": "flat_name", + "description": [], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.MultiField.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.MultiField.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.AlertFieldMap", + "type": "Type", + "tags": [], + "label": "AlertFieldMap", + "description": [], + "signature": [ + "{ readonly \"kibana.alert.action_group\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.case_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.duration.us\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping\": { readonly type: \"boolean\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping_history\": { readonly type: \"boolean\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.instance.id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.last_detected\": { readonly type: \"date\"; readonly required: false; readonly array: false; }; readonly \"kibana.alert.reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.category\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.consumer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.execution.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.name\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.parameters\": { readonly array: false; readonly type: \"flattened\"; readonly ignore_above: 4096; readonly required: false; }; readonly \"kibana.alert.rule.producer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_type_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.status\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.time_range\": { readonly type: \"date_range\"; readonly format: \"epoch_millis||strict_date_optional_time\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.workflow_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.space_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: true; }; readonly \"@timestamp\": { readonly type: \"date\"; readonly required: true; readonly array: false; }; readonly \"kibana.version\": { readonly type: \"version\"; readonly array: false; readonly required: false; }; }" + ], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.EcsFieldMap", + "type": "Type", + "tags": [], + "label": "EcsFieldMap", + "description": [], + "signature": [ + { + "pluginId": "@kbn/alerts-as-data-utils", + "scope": "common", + "docId": "kibKbnAlertsAsDataUtilsPluginApi", + "section": "def-common.FieldMap", + "text": "FieldMap" + } + ], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/ecs_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.LegacyAlertFieldMap", + "type": "Type", + "tags": [], + "label": "LegacyAlertFieldMap", + "description": [], + "signature": [ + "{ readonly \"kibana.alert.risk_score\": { readonly type: \"float\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.author\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.description\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.enabled\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.from\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.interval\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.license\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.note\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.references\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.rule_name_override\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.to\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.type\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.severity\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.docs_count\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.field\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.suppression.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.value\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.system_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_user\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"ecs.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"event.action\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"event.kind\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly tags: { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; }" + ], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/legacy_alert_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.alertFieldMap", + "type": "Object", + "tags": [], + "label": "alertFieldMap", + "description": [], + "signature": [ + "{ readonly \"kibana.alert.action_group\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.case_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.duration.us\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping\": { readonly type: \"boolean\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.flapping_history\": { readonly type: \"boolean\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.instance.id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.last_detected\": { readonly type: \"date\"; readonly required: false; readonly array: false; }; readonly \"kibana.alert.reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.category\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.consumer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.execution.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.name\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.parameters\": { readonly array: false; readonly type: \"flattened\"; readonly ignore_above: 4096; readonly required: false; }; readonly \"kibana.alert.rule.producer\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.tags\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_type_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.rule.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.status\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.time_range\": { readonly type: \"date_range\"; readonly format: \"epoch_millis||strict_date_optional_time\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.uuid\": { readonly type: \"keyword\"; readonly array: false; readonly required: true; }; readonly \"kibana.alert.workflow_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.space_ids\": { readonly type: \"keyword\"; readonly array: true; readonly required: true; }; readonly \"@timestamp\": { readonly type: \"date\"; readonly required: true; readonly array: false; }; readonly \"kibana.version\": { readonly type: \"version\"; readonly array: false; readonly required: false; }; }" + ], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/alert_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.ecsFieldMap", + "type": "Object", + "tags": [], + "label": "ecsFieldMap", + "description": [], + "signature": [ + { + "pluginId": "@kbn/alerts-as-data-utils", + "scope": "common", + "docId": "kibKbnAlertsAsDataUtilsPluginApi", + "section": "def-common.FieldMap", + "text": "FieldMap" + } + ], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/ecs_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/alerts-as-data-utils", + "id": "def-common.legacyAlertFieldMap", + "type": "Object", + "tags": [], + "label": "legacyAlertFieldMap", + "description": [], + "signature": [ + "{ readonly \"kibana.alert.risk_score\": { readonly type: \"float\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.author\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.created_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.description\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.enabled\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.from\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.interval\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.license\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.note\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.references\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.rule.rule_id\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.rule_name_override\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.to\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.type\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_at\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.updated_by\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.rule.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.severity\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.docs_count\": { readonly type: \"long\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.end\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.field\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.suppression.start\": { readonly type: \"date\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.suppression.terms.value\": { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; readonly \"kibana.alert.system_status\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_reason\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"kibana.alert.workflow_user\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"ecs.version\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"event.action\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly \"event.kind\": { readonly type: \"keyword\"; readonly array: false; readonly required: false; }; readonly tags: { readonly type: \"keyword\"; readonly array: true; readonly required: false; }; }" + ], + "path": "packages/kbn-alerts-as-data-utils/src/field_maps/legacy_alert_field_map.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] + } +} \ No newline at end of file diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx new file mode 100644 index 0000000000000..992e51d5ca374 --- /dev/null +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnAlertsAsDataUtilsPluginApi +slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils +title: "@kbn/alerts-as-data-utils" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/alerts-as-data-utils plugin +date: 2023-02-28 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] +--- +import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; + + + +Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 12 | 0 | 12 | 0 | + +## Common + +### Objects + + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 4feef26b61869..0182fb114a71d 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-27 +date: 2023-02-28 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 b43b2e542aa7a..9684fb67be844 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-27 +date: 2023-02-28 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 83c0c9326f5e9..1ba2bd42b6394 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-27 +date: 2023-02-28 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 8444fb1c70527..6d48a60192c3c 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-27 +date: 2023-02-28 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 5598eab2e267c..b4a362286f94b 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-27 +date: 2023-02-28 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 89b4d27e88db7..6cc59522d9f39 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-27 +date: 2023-02-28 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 7ed85b3e2a725..004b9f13a4dee 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-27 +date: 2023-02-28 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 3d976b803011c..a0ab0a9f8c901 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-27 +date: 2023-02-28 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 293ec377ece5b..10fe54398cb26 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-27 +date: 2023-02-28 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 220c4d0eff04c..2513fff6c64fd 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-27 +date: 2023-02-28 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 ea59a115a467f..ff0b1e2cf64e5 100644 --- a/api_docs/kbn_apm_synthtrace_client.devdocs.json +++ b/api_docs/kbn_apm_synthtrace_client.devdocs.json @@ -2299,7 +2299,7 @@ "section": "def-common.ApmFields", "text": "ApmFields" }, - ", \"@timestamp\" | \"metricset.name\" | \"ecs.version\" | \"event.ingested\" | \"observer.type\" | \"observer.version\" | \"observer.version_major\" | \"processor.event\" | \"processor.name\"> & Partial<{ 'labels.etag': string; agent_config_applied: number; 'event.agent_id_status': string; }>" + ", \"@timestamp\" | \"metricset.name\" | \"ecs.version\" | \"event.ingested\" | \"observer.type\" | \"observer.version_major\" | \"observer.version\" | \"processor.event\" | \"processor.name\"> & Partial<{ 'labels.etag': string; agent_config_applied: number; 'event.agent_id_status': string; }>" ], "path": "packages/kbn-apm-synthtrace-client/src/lib/agent_config/agent_config_fields.ts", "deprecated": false, diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 375c04442cbc2..72c107abb92cb 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-27 +date: 2023-02-28 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 b8ef3faac8e19..49e481e6ae3f9 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-27 +date: 2023-02-28 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 ddf1730e45ac9..368f913d5c27e 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-27 +date: 2023-02-28 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 3511b505e0e2f..c74cd3217452b 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-27 +date: 2023-02-28 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 02061af2d14dd..c793d1c5a5c10 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-27 +date: 2023-02-28 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 deb309320b4bb..4daaf41d72959 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-27 +date: 2023-02-28 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 bf64afd743b3b..dccd9a9031be5 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-27 +date: 2023-02-28 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 746317a3feac4..eab94ac6595e4 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-27 +date: 2023-02-28 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 b3a7d25e34933..07ae40b17946c 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-27 +date: 2023-02-28 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 c2ae9b8a179bc..73a06511196e7 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-27 +date: 2023-02-28 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 c7dfe9733b1e1..3787f059786a8 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-27 +date: 2023-02-28 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 92cc1a4550224..2178f170966fc 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-27 +date: 2023-02-28 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 86b1ef2ecb1a1..09a047af41856 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-27 +date: 2023-02-28 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 849cc7d107d55..620e35d139390 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-27 +date: 2023-02-28 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 cb251ab0c54fe..e28a6f5f0959e 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-27 +date: 2023-02-28 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 3239215bb6adf..d3c4cd303f272 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-27 +date: 2023-02-28 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 711b3e8bd807a..7d646114fb442 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-27 +date: 2023-02-28 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 09e4ce4f3836f..2172cd92ee114 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-27 +date: 2023-02-28 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 9ab4d41b30e87..a7f6b6fb80369 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-27 +date: 2023-02-28 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 3a3df328dc8d7..fe9deb4b585ac 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-27 +date: 2023-02-28 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 81db7f3f0ab31..38fb24b930ca7 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-27 +date: 2023-02-28 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 15cfcda31f131..432774cbff830 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-27 +date: 2023-02-28 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 eb94716c82be0..9c3b01c84d7de 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-27 +date: 2023-02-28 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 1535727bc8d26..c142aabd9a321 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-27 +date: 2023-02-28 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 7347a63bc8e23..f868c799f5928 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-27 +date: 2023-02-28 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 072e69f42cab8..6f8e2526177fa 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-27 +date: 2023-02-28 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 bd3b0383bc332..8f4d90f1df324 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-27 +date: 2023-02-28 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 993b94c6655ce..b0c74a42b25ac 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-27 +date: 2023-02-28 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 068e2faf47ed6..f194c2065f746 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-27 +date: 2023-02-28 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 721be4c216c89..7ddaa26562b22 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-27 +date: 2023-02-28 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 0a109d63443f6..27b03ed3a1a21 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-27 +date: 2023-02-28 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 c2bc58640090a..aa9b5e329e9e8 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-27 +date: 2023-02-28 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 b975c09f45aaf..26dbd86f7ff30 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-27 +date: 2023-02-28 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 c7e8c5b615357..50a40e42e8f38 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-27 +date: 2023-02-28 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 f1571949332a2..b8f1c44efe947 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-27 +date: 2023-02-28 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 e9f1270cf71fb..2ebce3e9b4460 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-27 +date: 2023-02-28 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 0ebeda8790a7c..0093670745c9d 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-27 +date: 2023-02-28 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 4c206c74f1a8d..2d97c57d5a937 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-27 +date: 2023-02-28 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 bcc107a33368f..f6998d9b6f6bd 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-27 +date: 2023-02-28 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 01a7e68610e7c..a5164a238b129 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-27 +date: 2023-02-28 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 1de0023acef2e..40a0b78ba18ea 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-27 +date: 2023-02-28 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 3ed282bbfd36e..9adcd8599792f 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-27 +date: 2023-02-28 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 c101b8c201c2c..3c464b4c79406 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-27 +date: 2023-02-28 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 580ff5a3b57fe..3065855251657 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-27 +date: 2023-02-28 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 cda93ff8286cd..8ec8f5a3543ce 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-27 +date: 2023-02-28 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 20ec492830d9b..347beed689407 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-27 +date: 2023-02-28 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 d3df38b317fe0..85b0225e69aea 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-27 +date: 2023-02-28 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 e8f9159b959a9..6f6646157d997 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-27 +date: 2023-02-28 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 8cf17e8a59c8b..f94be732c56bb 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-27 +date: 2023-02-28 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 8cf281aa41042..1e6dddce80d5a 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-27 +date: 2023-02-28 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 1cf9cc03fd97c..04072fdc8bbfe 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-27 +date: 2023-02-28 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 ad46c1edd9657..95222a6ac1824 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-27 +date: 2023-02-28 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 33f157f2a212b..0f1e4720014ac 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-27 +date: 2023-02-28 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 042e4b04bcf52..c497ffb4366d2 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-27 +date: 2023-02-28 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 f8d49d314c606..fb218b43f4269 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-27 +date: 2023-02-28 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 3857af8276b4a..0d095d6f7c53d 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-27 +date: 2023-02-28 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 ea2ea178cf45d..e2ea45eb55375 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-27 +date: 2023-02-28 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 7d97ab37e707c..bb0d0cc31bead 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-27 +date: 2023-02-28 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 cf86951be6012..2cee9209cdbef 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-27 +date: 2023-02-28 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 baeb86012fd03..7a30a0bed12ef 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-27 +date: 2023-02-28 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 15c05311a73a5..b815a71f4dea4 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-27 +date: 2023-02-28 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 9281ef198f2ee..24e0983a06988 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-27 +date: 2023-02-28 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 c9ea75a6c3b23..8940205ac39e7 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-27 +date: 2023-02-28 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 a4086757492e5..09cf5a04b533b 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-27 +date: 2023-02-28 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 a707b2a011962..a89837fea7fa1 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-27 +date: 2023-02-28 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 c00e6c8f19b53..32bca8361a9f2 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-27 +date: 2023-02-28 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 62d29a36829ee..dd94662c3b9a4 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-27 +date: 2023-02-28 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 df6cdd92bf87e..c2260e5150dd2 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-27 +date: 2023-02-28 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 05859ea24e9e8..5035a999507ef 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-27 +date: 2023-02-28 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 e62babd649cbf..32c3f93a2147d 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-27 +date: 2023-02-28 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 df4f5446a3094..9e817bea42692 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-27 +date: 2023-02-28 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 d32765fbcfc14..38992012702e3 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-27 +date: 2023-02-28 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 0ec13c09b40dc..997277de0992c 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-27 +date: 2023-02-28 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 6d07e121f437f..590a32f7b6804 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-27 +date: 2023-02-28 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 7be2d7332e660..0a2e946d0ef46 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-27 +date: 2023-02-28 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 c9a614378a360..6b4a94c7a65c0 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-27 +date: 2023-02-28 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 14a37f5004d02..9a009a36d14b0 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-27 +date: 2023-02-28 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 93e0fb83aae93..b71faf9a8d6ce 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-27 +date: 2023-02-28 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 6fdb476db5757..dcbda996bb75e 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-27 +date: 2023-02-28 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 04d6d8654db89..62c46d3b36627 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-27 +date: 2023-02-28 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 f0fe8987be77a..198ef483d2837 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-27 +date: 2023-02-28 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 bd1b8d72dbcb9..7f339abb6cb8a 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-27 +date: 2023-02-28 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 ff966b3d52166..8c04ac064bebe 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-27 +date: 2023-02-28 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 d2e0cc08f2eb4..82dea39db37f3 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-27 +date: 2023-02-28 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 2bae75d9a5c77..c7f2baee7037c 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-27 +date: 2023-02-28 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 6daa81af7f719..5c962b28d9886 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-27 +date: 2023-02-28 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 5abfd211d3f55..cce44307af439 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-27 +date: 2023-02-28 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 9c6b7735df4fd..b7547349d8917 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-27 +date: 2023-02-28 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 7132683763250..d65a953512a37 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-27 +date: 2023-02-28 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 974f85a8b55f7..96aadf2d16be1 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-27 +date: 2023-02-28 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 0bfca6e59b368..489443cba0e0b 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-27 +date: 2023-02-28 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 47db66b5ecc84..f50069c3f3d4a 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-27 +date: 2023-02-28 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 c27bfbd37feac..d634637079eca 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-27 +date: 2023-02-28 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 09dae1b2abf1b..ef3c68b517d8c 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-27 +date: 2023-02-28 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 6d56e08c115c5..8b3b165d647b1 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-27 +date: 2023-02-28 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 9ae37a90003a0..46b7c178fcc81 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-27 +date: 2023-02-28 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 a1f7cb96252a7..67f4789cf12a7 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-27 +date: 2023-02-28 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 80e25386fc84b..4b3c13625ec7b 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-27 +date: 2023-02-28 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 1011becb38e39..ea11c4da9c361 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-27 +date: 2023-02-28 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 610ccc9db4916..3f09d5bddec53 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-27 +date: 2023-02-28 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 035371808b5f4..8c504dfc42433 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-27 +date: 2023-02-28 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 2ed4f5fef2db3..6e1ad00dc2109 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-27 +date: 2023-02-28 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 562f7f28c60f8..8866307025a39 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-27 +date: 2023-02-28 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 1eb48afd95a2b..f8f39b499356f 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-27 +date: 2023-02-28 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 327d6e7a3ce5a..546977f0811d0 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-27 +date: 2023-02-28 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 83d8ea5c57490..0b0c961bc0b74 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-27 +date: 2023-02-28 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 c1d2cb23e5972..0e38ee4bee9cb 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-27 +date: 2023-02-28 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 a4b7482bfe9e8..477dc6dcfbfae 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-27 +date: 2023-02-28 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 92b8f41da6d32..16858dd741c08 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-27 +date: 2023-02-28 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 af3e01e6ece08..cd7556995b5b1 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-27 +date: 2023-02-28 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 0e40b26c24c4c..a1e3c4bcf55e3 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-27 +date: 2023-02-28 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 6e00b954efbb7..b4382c5f92369 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-27 +date: 2023-02-28 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 a238d378d5c79..5301a90c90b28 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-27 +date: 2023-02-28 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 9c0ab3290114f..4f6bf040660eb 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_core_node_server.devdocs.json index 9b0d9eed398dd..92ce832afbc4e 100644 --- a/api_docs/kbn_core_node_server.devdocs.json +++ b/api_docs/kbn_core_node_server.devdocs.json @@ -96,6 +96,19 @@ "path": "packages/core/node/core-node-server/src/types.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-node-server", + "id": "def-common.NodeRoles.migrator", + "type": "boolean", + "tags": [], + "label": "migrator", + "description": [ + "\nStart Kibana with the specific purpose of completing the migrations phase then shutting down." + ], + "path": "packages/core/node/core-node-server/src/types.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 278c9eddb7fc4..972b3c1597f3c 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 5 | 0 | 0 | 0 | +| 6 | 0 | 0 | 0 | ## Common diff --git a/api_docs/kbn_core_node_server_internal.devdocs.json b/api_docs/kbn_core_node_server_internal.devdocs.json index 8db2a68da0239..435988185b457 100644 --- a/api_docs/kbn_core_node_server_internal.devdocs.json +++ b/api_docs/kbn_core_node_server_internal.devdocs.json @@ -87,64 +87,6 @@ ], "enums": [], "misc": [], - "objects": [ - { - "parentPluginId": "@kbn/core-node-server-internal", - "id": "def-common.nodeConfig", - "type": "Object", - "tags": [], - "label": "nodeConfig", - "description": [], - "path": "packages/core/node/core-node-server-internal/src/node_config.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/core-node-server-internal", - "id": "def-common.nodeConfig.path", - "type": "string", - "tags": [], - "label": "path", - "description": [], - "signature": [ - "\"node\"" - ], - "path": "packages/core/node/core-node-server-internal/src/node_config.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/core-node-server-internal", - "id": "def-common.nodeConfig.schema", - "type": "Object", - "tags": [], - "label": "schema", - "description": [], - "signature": [ - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.ObjectType", - "text": "ObjectType" - }, - "<{ roles: ", - { - "pluginId": "@kbn/config-schema", - "scope": "common", - "docId": "kibKbnConfigSchemaPluginApi", - "section": "def-common.Type", - "text": "Type" - }, - "<\"*\"[] | (\"ui\" | \"background_tasks\")[]>; }>" - ], - "path": "packages/core/node/core-node-server-internal/src/node_config.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - } - ] + "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 681584152552f..965ec4d1acd3e 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; @@ -21,13 +21,10 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 7 | 0 | 6 | 1 | +| 4 | 0 | 3 | 1 | ## Common -### Objects - - ### Interfaces diff --git a/api_docs/kbn_core_node_server_mocks.devdocs.json b/api_docs/kbn_core_node_server_mocks.devdocs.json index f2d7ca94bf8cf..7997492fa90e4 100644 --- a/api_docs/kbn_core_node_server_mocks.devdocs.json +++ b/api_docs/kbn_core_node_server_mocks.devdocs.json @@ -76,7 +76,7 @@ "label": "createInternalStartContract", "description": [], "signature": [ - "({ ui, backgroundTasks, }?: { ui: boolean; backgroundTasks: boolean; }) => jest.Mocked<", + "({ ui, backgroundTasks, migrator, }?: { ui: boolean; backgroundTasks: boolean; migrator: boolean; }) => jest.Mocked<", { "pluginId": "@kbn/core-node-server-internal", "scope": "common", @@ -99,7 +99,7 @@ "label": "__0", "description": [], "signature": [ - "{ ui: boolean; backgroundTasks: boolean; }" + "{ ui: boolean; backgroundTasks: boolean; migrator: boolean; }" ], "path": "packages/core/node/core-node-server-mocks/src/node_service.mock.ts", "deprecated": false, diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index af63729ff7af0..ba8bd02cacbc1 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-27 +date: 2023-02-28 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 f232dc1095c47..fa35561e301dc 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-27 +date: 2023-02-28 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 704727e17650c..1401f5adcf067 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-27 +date: 2023-02-28 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 7302144640fee..ab530789c88d6 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-27 +date: 2023-02-28 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 f3f74033f0690..67fbc659c9ed1 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-27 +date: 2023-02-28 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 dae2144fd0091..f4a4ac81b9b4e 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-27 +date: 2023-02-28 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 bde023a91ebb5..19a6cecb35764 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-27 +date: 2023-02-28 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 36b8d050f77d5..a75e5e40ce83b 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-27 +date: 2023-02-28 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 019e64ab0b420..5ca8c83b6ce61 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-27 +date: 2023-02-28 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 bff0a2571ea11..2f22103dbf192 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-27 +date: 2023-02-28 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 e9e97ad4ac7ba..3c4c88afbd8a5 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-27 +date: 2023-02-28 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 be617032639b4..94fbe3c381272 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-27 +date: 2023-02-28 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 e99e6c1cb1a3e..4bb4a6293a868 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-27 +date: 2023-02-28 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 fd4876fb7217e..f5f81a45db236 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-27 +date: 2023-02-28 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 05083a9379a4d..aa0d29f8cd612 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-27 +date: 2023-02-28 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 9a1b0c18751f7..ca6bc8c89dbf2 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_core_root_server_internal.devdocs.json index 765f11e6ad76e..c5af081041ed3 100644 --- a/api_docs/kbn_core_root_server_internal.devdocs.json +++ b/api_docs/kbn_core_root_server_internal.devdocs.json @@ -417,7 +417,43 @@ "initialIsOpen": false } ], - "functions": [], + "functions": [ + { + "parentPluginId": "@kbn/core-root-server-internal", + "id": "def-common.registerServiceConfig", + "type": "Function", + "tags": [], + "label": "registerServiceConfig", + "description": [], + "signature": [ + "(configService: ", + "ConfigService", + ") => void" + ], + "path": "packages/core/root/core-root-server-internal/src/register_service_config.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-root-server-internal", + "id": "def-common.registerServiceConfig.$1", + "type": "Object", + "tags": [], + "label": "configService", + "description": [], + "signature": [ + "ConfigService" + ], + "path": "packages/core/root/core-root-server-internal/src/register_service_config.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], "interfaces": [], "enums": [], "misc": [], diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index cc1550490e12f..d33764a007ee1 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; @@ -21,10 +21,13 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 23 | 1 | 22 | 0 | +| 25 | 1 | 24 | 0 | ## Common +### Functions + + ### Classes diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 5a6fe5d1dc482..9925c7d54e924 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-27 +date: 2023-02-28 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 3eedd0bf046a0..371aec9bdd901 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-27 +date: 2023-02-28 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 26e8db451e83a..52030b02bde3d 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-27 +date: 2023-02-28 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 eec7b798a06c1..297fa858fc441 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_core_saved_objects_base_server_internal.devdocs.json index 89b711814980d..7e50fa4187ed5 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_base_server_internal.devdocs.json @@ -70,7 +70,7 @@ "label": "migration", "description": [], "signature": [ - "{ readonly discardUnknownObjects?: string | undefined; readonly discardCorruptObjects?: string | undefined; readonly skip: boolean; readonly pollInterval: number; readonly batchSize: number; readonly maxBatchSizeBytes: ", + "{ readonly discardUnknownObjects?: string | undefined; readonly discardCorruptObjects?: string | undefined; readonly skip: boolean; readonly pollInterval: number; readonly algorithm: \"v2\" | \"zdt\"; readonly batchSize: number; readonly maxBatchSizeBytes: ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -129,7 +129,7 @@ "label": "rawMigrationConfig", "description": [], "signature": [ - "Readonly<{ discardUnknownObjects?: string | undefined; discardCorruptObjects?: string | undefined; } & { skip: boolean; pollInterval: number; batchSize: number; maxBatchSizeBytes: ", + "Readonly<{ discardUnknownObjects?: string | undefined; discardCorruptObjects?: string | undefined; } & { skip: boolean; pollInterval: number; algorithm: \"v2\" | \"zdt\"; batchSize: number; maxBatchSizeBytes: ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -755,7 +755,7 @@ "label": "SavedObjectsMigrationConfigType", "description": [], "signature": [ - "{ readonly discardUnknownObjects?: string | undefined; readonly discardCorruptObjects?: string | undefined; readonly skip: boolean; readonly pollInterval: number; readonly batchSize: number; readonly maxBatchSizeBytes: ", + "{ readonly discardUnknownObjects?: string | undefined; readonly discardCorruptObjects?: string | undefined; readonly skip: boolean; readonly pollInterval: number; readonly algorithm: \"v2\" | \"zdt\"; readonly batchSize: number; readonly maxBatchSizeBytes: ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -887,7 +887,15 @@ "section": "def-common.ObjectType", "text": "ObjectType" }, - "<{ batchSize: ", + "<{ algorithm: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<\"v2\" | \"zdt\">; batchSize: ", { "pluginId": "@kbn/config-schema", "scope": "common", 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 1f86a3cecacdc..5b47d36f7b4e3 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-27 +date: 2023-02-28 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 d36afdadf0cbd..08754e85a429e 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-27 +date: 2023-02-28 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 36259efd2ef5a..3f72172ad2624 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-27 +date: 2023-02-28 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 f84981449ddf2..0e2f1a128dc24 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-27 +date: 2023-02-28 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 5228ef48d73d9..e9cad4c0e296d 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-27 +date: 2023-02-28 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 5db946fd1fc84..abdd31b8265e9 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-27 +date: 2023-02-28 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 66ce8098c17c7..e2eacb6b852ff 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-27 +date: 2023-02-28 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 e7695de2d2b2f..c386a8bac46dd 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json index 68bab1e33dbd5..0134af64ddd5c 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json @@ -599,6 +599,57 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.buildTypesMappings", + "type": "Function", + "tags": [], + "label": "buildTypesMappings", + "description": [ + "\nMerge mappings from all registered saved object types." + ], + "signature": [ + "(types: ", + { + "pluginId": "@kbn/core-saved-objects-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsServerPluginApi", + "section": "def-common.SavedObjectsType", + "text": "SavedObjectsType" + }, + "[]) => ", + "SavedObjectsTypeMappingDefinitions" + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/build_types_mappings.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.buildTypesMappings.$1", + "type": "Array", + "tags": [], + "label": "types", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsServerPluginApi", + "section": "def-common.SavedObjectsType", + "text": "SavedObjectsType" + }, + "[]" + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/build_types_mappings.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", "id": "def-common.bulkOverwriteTransformedDocuments", @@ -609,7 +660,7 @@ "\nWrite the up-to-date transformed documents to the index, overwriting any\ndocuments that are still on their outdated version." ], "signature": [ - "({ client, index, transformedDocs, refresh, }: ", + "({ client, index, operations, refresh, }: ", "BulkOverwriteTransformedDocumentsParams", ") => ", "TaskEither", @@ -632,7 +683,7 @@ "id": "def-common.bulkOverwriteTransformedDocuments.$1", "type": "Object", "tags": [], - "label": "{\n client,\n index,\n transformedDocs,\n refresh = false,\n }", + "label": "{\n client,\n index,\n operations,\n refresh = false,\n }", "description": [], "signature": [ "BulkOverwriteTransformedDocumentsParams" @@ -816,6 +867,92 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.createBulkDeleteOperationBody", + "type": "Function", + "tags": [], + "label": "createBulkDeleteOperationBody", + "description": [ + "\nGiven a document id, creates a valid body to delete the document using the Bulk API." + ], + "signature": [ + "(_id: string) => ", + "BulkOperationContainer" + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.createBulkDeleteOperationBody.$1", + "type": "string", + "tags": [], + "label": "_id", + "description": [], + "signature": [ + "string" + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.createBulkIndexOperationTuple", + "type": "Function", + "tags": [], + "label": "createBulkIndexOperationTuple", + "description": [ + "\nGiven a document, creates a valid body to index the document using the Bulk API." + ], + "signature": [ + "(doc: ", + { + "pluginId": "@kbn/core-saved-objects-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsServerPluginApi", + "section": "def-common.SavedObjectsRawDoc", + "text": "SavedObjectsRawDoc" + }, + ") => ", + "BulkIndexOperationTuple" + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", + "id": "def-common.createBulkIndexOperationTuple.$1", + "type": "Object", + "tags": [], + "label": "doc", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-saved-objects-server", + "scope": "common", + "docId": "kibKbnCoreSavedObjectsServerPluginApi", + "section": "def-common.SavedObjectsRawDoc", + "text": "SavedObjectsRawDoc" + } + ], + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", "id": "def-common.createIndex", @@ -1091,57 +1228,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", - "id": "def-common.mergeTypes", - "type": "Function", - "tags": [], - "label": "mergeTypes", - "description": [ - "\nMerges savedObjectMappings properties into a single object, verifying that\nno mappings are redefined." - ], - "signature": [ - "(types: ", - { - "pluginId": "@kbn/core-saved-objects-server", - "scope": "common", - "docId": "kibKbnCoreSavedObjectsServerPluginApi", - "section": "def-common.SavedObjectsType", - "text": "SavedObjectsType" - }, - "[]) => ", - "SavedObjectsTypeMappingDefinitions" - ], - "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", - "id": "def-common.mergeTypes.$1", - "type": "Array", - "tags": [], - "label": "types", - "description": [], - "signature": [ - { - "pluginId": "@kbn/core-saved-objects-server", - "scope": "common", - "docId": "kibKbnCoreSavedObjectsServerPluginApi", - "section": "def-common.SavedObjectsType", - "text": "SavedObjectsType" - }, - "[]" - ], - "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", "id": "def-common.openPit", @@ -3335,7 +3421,7 @@ "label": "soMigrationsConfig", "description": [], "signature": [ - "{ readonly discardUnknownObjects?: string | undefined; readonly discardCorruptObjects?: string | undefined; readonly skip: boolean; readonly pollInterval: number; readonly batchSize: number; readonly maxBatchSizeBytes: ", + "{ readonly discardUnknownObjects?: string | undefined; readonly discardCorruptObjects?: string | undefined; readonly skip: boolean; readonly pollInterval: number; readonly algorithm: \"v2\" | \"zdt\"; readonly batchSize: number; readonly maxBatchSizeBytes: ", { "pluginId": "@kbn/config-schema", "scope": "common", 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 aaa6da1d1ce75..da9c17cfc84dc 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 112 | 0 | 79 | 45 | +| 116 | 0 | 81 | 46 | ## Common 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 190de89e284e3..b7ff18bfe97db 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-27 +date: 2023-02-28 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 1997dd7e500a1..3708f94bd910b 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-27 +date: 2023-02-28 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 ad88d3434c93b..2af33c48974f5 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-27 +date: 2023-02-28 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 e019befaf4778..c63669a42313a 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-27 +date: 2023-02-28 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 a3cdd465231a2..30311cf44a269 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-27 +date: 2023-02-28 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 db13569fc15a5..c4464831aa731 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-27 +date: 2023-02-28 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 e98ac07a6eb86..967ee90a4af04 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-27 +date: 2023-02-28 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 184613b2bd134..36ab7c3c06d35 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-27 +date: 2023-02-28 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 8ee1bcb32622d..294abb3b0c19a 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-27 +date: 2023-02-28 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 a72c75b0a892c..844f75cab333a 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-27 +date: 2023-02-28 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 e16d7583efcd8..5639a6c086857 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-27 +date: 2023-02-28 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 1a08b1250ecf2..5c0b770e2c434 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-27 +date: 2023-02-28 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 7fc2878ad1206..d9e9ac63049ae 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-27 +date: 2023-02-28 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 eda623498db60..d9fbb1ee32328 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-27 +date: 2023-02-28 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 447c495ff4ccd..a0448c7fa78bf 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-27 +date: 2023-02-28 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 175e1ed9bab85..04bfe87b1f780 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-27 +date: 2023-02-28 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 35c6273c61213..1eb0414dd45c8 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-27 +date: 2023-02-28 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 3b22b27f1997a..8c09095a3e3b5 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-27 +date: 2023-02-28 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 f3406378d00d4..822f2d74702df 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-27 +date: 2023-02-28 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 76e920393bb73..28564e1638de5 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-27 +date: 2023-02-28 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 66666a05ffe19..14a983d39a21d 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-27 +date: 2023-02-28 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 927468797587b..e7e4dc709985f 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-27 +date: 2023-02-28 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 71cb58aad9b56..f1f131ca9ae40 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-27 +date: 2023-02-28 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 56d22396db1b6..322a944c92407 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-27 +date: 2023-02-28 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 78bad8c43e148..972e4fea27a2b 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-27 +date: 2023-02-28 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 9c2262467058a..ad1a2af0c26dd 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-27 +date: 2023-02-28 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 588d770ab0f57..7986cb3e189ac 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-27 +date: 2023-02-28 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 d5dda260a906e..948602f8b16ce 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-27 +date: 2023-02-28 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 02386cdf929e1..a1939bcf16477 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-27 +date: 2023-02-28 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 d7193bced5849..3e6ba58a589e0 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-27 +date: 2023-02-28 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 53c2e496b6b2e..cd7c5ec1315f8 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-27 +date: 2023-02-28 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 2e5a072cf7495..dc4e0302a3840 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-27 +date: 2023-02-28 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 b08d3e2f1a0eb..7701ace42bb65 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-27 +date: 2023-02-28 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 658fd80529198..ee43d20b0961e 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-27 +date: 2023-02-28 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 1513bbc31f7a0..3d9236ee8431d 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-27 +date: 2023-02-28 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 5e9fb3d83fde2..a4503d762f0c2 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-27 +date: 2023-02-28 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 415e48f690346..690befe3cbb83 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-27 +date: 2023-02-28 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 a9f89a9888a86..0399b4f8c746f 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-27 +date: 2023-02-28 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 21787f427307a..4657ed79be42d 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-27 +date: 2023-02-28 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 552ef1cd7001e..bd5b4c146878d 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-27 +date: 2023-02-28 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 5c8cc814ac584..8fe18eca0bc56 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-27 +date: 2023-02-28 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 fecb21184b8a1..ba011e6bbf167 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-27 +date: 2023-02-28 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 784763e15d41d..9421f34bd8b83 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-27 +date: 2023-02-28 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 ba77b55460365..fe513e762d0e9 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-27 +date: 2023-02-28 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 8234d3212999f..e0903de48be62 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-27 +date: 2023-02-28 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 273601e75d946..847febd25c24d 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-27 +date: 2023-02-28 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 eaa59a2eea258..d399dc95f270c 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.devdocs.json b/api_docs/kbn_expandable_flyout.devdocs.json new file mode 100644 index 0000000000000..9658f381fd343 --- /dev/null +++ b/api_docs/kbn_expandable_flyout.devdocs.json @@ -0,0 +1,273 @@ +{ + "id": "@kbn/expandable-flyout", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.ExpandableFlyout", + "type": "Function", + "tags": [], + "label": "ExpandableFlyout", + "description": [ + "\nExpandable flyout UI React component.\nDisplays 3 sections (right, left, preview) depending on the panels in the context." + ], + "signature": [ + "{ ({ registeredPanels, handleOnFlyoutClosed, ...flyoutProps }: React.PropsWithChildren<", + { + "pluginId": "@kbn/expandable-flyout", + "scope": "common", + "docId": "kibKbnExpandableFlyoutPluginApi", + "section": "def-common.ExpandableFlyoutProps", + "text": "ExpandableFlyoutProps" + }, + ">): JSX.Element; displayName: string | undefined; }" + ], + "path": "packages/kbn-expandable-flyout/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.ExpandableFlyout.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n registeredPanels,\n handleOnFlyoutClosed,\n ...flyoutProps\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "@kbn/expandable-flyout", + "scope": "common", + "docId": "kibKbnExpandableFlyoutPluginApi", + "section": "def-common.ExpandableFlyoutProps", + "text": "ExpandableFlyoutProps" + }, + ">" + ], + "path": "packages/kbn-expandable-flyout/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.ExpandableFlyoutProvider", + "type": "Function", + "tags": [], + "label": "ExpandableFlyoutProvider", + "description": [ + "\nWrap your plugin with this context for the ExpandableFlyout React component." + ], + "signature": [ + "({ children }: ", + "ExpandableFlyoutProviderProps", + ") => JSX.Element" + ], + "path": "packages/kbn-expandable-flyout/src/context.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.ExpandableFlyoutProvider.$1", + "type": "Object", + "tags": [], + "label": "{ children }", + "description": [], + "signature": [ + "ExpandableFlyoutProviderProps" + ], + "path": "packages/kbn-expandable-flyout/src/context.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.useExpandableFlyoutContext", + "type": "Function", + "tags": [], + "label": "useExpandableFlyoutContext", + "description": [ + "\nRetrieve context's properties" + ], + "signature": [ + "() => ", + "ExpandableFlyoutContext" + ], + "path": "packages/kbn-expandable-flyout/src/context.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.ExpandableFlyoutProps", + "type": "Interface", + "tags": [], + "label": "ExpandableFlyoutProps", + "description": [], + "signature": [ + { + "pluginId": "@kbn/expandable-flyout", + "scope": "common", + "docId": "kibKbnExpandableFlyoutPluginApi", + "section": "def-common.ExpandableFlyoutProps", + "text": "ExpandableFlyoutProps" + }, + " extends ", + "EuiFlyoutProps", + "<\"div\">" + ], + "path": "packages/kbn-expandable-flyout/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.ExpandableFlyoutProps.registeredPanels", + "type": "Array", + "tags": [], + "label": "registeredPanels", + "description": [ + "\nList of all registered panels available for render" + ], + "signature": [ + "Panel", + "[]" + ], + "path": "packages/kbn-expandable-flyout/src/index.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.ExpandableFlyoutProps.handleOnFlyoutClosed", + "type": "Function", + "tags": [], + "label": "handleOnFlyoutClosed", + "description": [ + "\nPropagate out EuiFlyout onClose event" + ], + "signature": [ + "(() => void) | undefined" + ], + "path": "packages/kbn-expandable-flyout/src/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.FlyoutPanel", + "type": "Interface", + "tags": [], + "label": "FlyoutPanel", + "description": [], + "path": "packages/kbn-expandable-flyout/src/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.FlyoutPanel.id", + "type": "string", + "tags": [], + "label": "id", + "description": [ + "\nUnique key to identify the panel" + ], + "path": "packages/kbn-expandable-flyout/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.FlyoutPanel.params", + "type": "Object", + "tags": [], + "label": "params", + "description": [ + "\nAny parameters necessary for the initial requests within the flyout" + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/kbn-expandable-flyout/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.FlyoutPanel.path", + "type": "Array", + "tags": [], + "label": "path", + "description": [ + "\nTracks the path for what to show in a panel. We may have multiple tabs or details..., so easiest to just use a stack" + ], + "signature": [ + "string[] | undefined" + ], + "path": "packages/kbn-expandable-flyout/src/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/expandable-flyout", + "id": "def-common.FlyoutPanel.state", + "type": "Object", + "tags": [], + "label": "state", + "description": [ + "\nTracks visual state such as whether the panel is collapsed" + ], + "signature": [ + "Record | undefined" + ], + "path": "packages/kbn-expandable-flyout/src/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx new file mode 100644 index 0000000000000..22fbc24cf88a1 --- /dev/null +++ b/api_docs/kbn_expandable_flyout.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnExpandableFlyoutPluginApi +slug: /kibana-dev-docs/api/kbn-expandable-flyout +title: "@kbn/expandable-flyout" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/expandable-flyout plugin +date: 2023-02-28 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] +--- +import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; + + + +Contact [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 13 | 0 | 4 | 3 | + +## Common + +### Functions + + +### Interfaces + + diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 0287d21eb53df..e6ea6c2915b92 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-27 +date: 2023-02-28 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 8d3dbec5ef1d4..67f7f707c8648 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-27 +date: 2023-02-28 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 17c629d017633..9ac919b0a22a4 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-27 +date: 2023-02-28 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 aee0d8aa6d524..938c566cab0ad 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-27 +date: 2023-02-28 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 27c485203f114..15e3f4473cc4d 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.devdocs.json b/api_docs/kbn_handlebars.devdocs.json index 0c3d26cf1c175..84069ecfa5b9c 100644 --- a/api_docs/kbn_handlebars.devdocs.json +++ b/api_docs/kbn_handlebars.devdocs.json @@ -420,7 +420,7 @@ "\nSupported Handlebars compile options.\n\nThis is a subset of all the compile options supported by the upstream\nHandlebars module." ], "signature": [ - "{ data?: boolean | undefined; strict?: boolean | undefined; knownHelpers?: KnownHelpers | undefined; knownHelpersOnly?: boolean | undefined; noEscape?: boolean | undefined; assumeObjects?: boolean | undefined; preventIndent?: boolean | undefined; explicitPartialContext?: boolean | undefined; }" + "{ strict?: boolean | undefined; data?: boolean | undefined; knownHelpers?: KnownHelpers | undefined; knownHelpersOnly?: boolean | undefined; noEscape?: boolean | undefined; assumeObjects?: boolean | undefined; preventIndent?: boolean | undefined; explicitPartialContext?: boolean | undefined; }" ], "path": "packages/kbn-handlebars/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index adb6e8aa995fd..d52887d5f386a 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-27 +date: 2023-02-28 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 508e8edcf7812..2f6f53b29bcc8 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-27 +date: 2023-02-28 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 65fe99bcf0fd6..3c704dc1082d2 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-27 +date: 2023-02-28 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 cb682ae4f9900..d2449d916ce71 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-27 +date: 2023-02-28 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 9d5c6575fdd70..2b2abfa098b6b 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-27 +date: 2023-02-28 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 093991e202a75..ccc93fbc3ff29 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-27 +date: 2023-02-28 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 f3147c2dfe769..2c78806ed6e46 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-27 +date: 2023-02-28 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 021576539dda5..72bd7cf1cb0f0 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-27 +date: 2023-02-28 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 9a26721488b93..50d4412ff5b81 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-27 +date: 2023-02-28 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 2f4a023579df9..20a8be80b5c93 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-27 +date: 2023-02-28 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 a3c25d75910b4..93621cf47e0aa 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-27 +date: 2023-02-28 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 78c93dc47e995..d742be4326672 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-27 +date: 2023-02-28 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 23162fdbcb8a0..610d8fc4a18f5 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-27 +date: 2023-02-28 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 7ab510e97ac36..ff7cb5480240d 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-27 +date: 2023-02-28 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 5a4aac9574156..94f433a05f257 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-27 +date: 2023-02-28 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 406cfb327294e..4e0fcbffc46f9 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-27 +date: 2023-02-28 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 8aa1631ce53a0..4d5f32f707390 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-27 +date: 2023-02-28 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 c13e84f344705..6d92d1ead30b5 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-27 +date: 2023-02-28 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 53359db3b93a4..7a15ccfa87ed5 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-27 +date: 2023-02-28 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 8bb33f2663dc2..3a50b4adcfb53 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-27 +date: 2023-02-28 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 2f2cd5efe78bc..dfeeb1510c9f7 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-27 +date: 2023-02-28 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 ebd371fa39360..6874332a26f30 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-27 +date: 2023-02-28 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 1d634f80ec520..6670e94eb4eee 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-27 +date: 2023-02-28 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 1691190226d46..bbd025fe1fa5a 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-27 +date: 2023-02-28 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 bcee4b75b6c2a..c0554041a68a5 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-27 +date: 2023-02-28 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 09ed1ad02393c..be947c303ff24 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-27 +date: 2023-02-28 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 f9c4d29869a7f..12f3acbcf3dd9 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-27 +date: 2023-02-28 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 d804c533e1b09..6a6b54987f4c0 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-27 +date: 2023-02-28 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 3638a55e2ad02..78a9557f3a8e2 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-27 +date: 2023-02-28 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 8f216afa89398..796787cdff114 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-27 +date: 2023-02-28 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 5de6feece7499..4c2ced69cd354 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-27 +date: 2023-02-28 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 1701080c152a4..fcd4299d7dec6 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-27 +date: 2023-02-28 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 c89cd61bfdc71..8735a6ebf7771 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-27 +date: 2023-02-28 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 db2b66505446a..2fe0e395a926a 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-27 +date: 2023-02-28 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 3f547dc9a9278..b42e4ff694c8e 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-27 +date: 2023-02-28 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 ab6126edfa1d0..26651728d35af 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-27 +date: 2023-02-28 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 2ce4e25fe73dd..97902ffe415b4 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-27 +date: 2023-02-28 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 27117caad1c2a..90bce3b337ef4 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-27 +date: 2023-02-28 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 07dcc95444a77..ea301fcb7bf65 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-27 +date: 2023-02-28 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 da2e98c4fb0fa..f027a5abaee44 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-27 +date: 2023-02-28 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 1656d07cb758c..67b113801852c 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.devdocs.json b/api_docs/kbn_rule_data_utils.devdocs.json index 51429bd28d4a4..0b4f41adabbdc 100644 --- a/api_docs/kbn_rule_data_utils.devdocs.json +++ b/api_docs/kbn_rule_data_utils.devdocs.json @@ -218,7 +218,7 @@ "signature": [ "\"kibana.alert.case_ids\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/default_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -300,13 +300,13 @@ }, { "parentPluginId": "@kbn/rule-data-utils", - "id": "def-common.ALERT_ID", + "id": "def-common.ALERT_FLAPPING_HISTORY", "type": "string", "tags": [], - "label": "ALERT_ID", + "label": "ALERT_FLAPPING_HISTORY", "description": [], "signature": [ - "\"kibana.alert.id\"" + "\"kibana.alert.flapping_history\"" ], "path": "packages/kbn-rule-data-utils/src/default_alerts_as_data.ts", "deprecated": false, @@ -323,7 +323,7 @@ "signature": [ "\"kibana.alert.instance.id\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/default_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -383,7 +383,7 @@ "signature": [ "\"kibana.alert.risk_score\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -398,7 +398,7 @@ "signature": [ "\"kibana.alert.rule.author\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -443,7 +443,7 @@ "signature": [ "\"kibana.alert.rule.created_at\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -458,7 +458,7 @@ "signature": [ "\"kibana.alert.rule.created_by\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -473,7 +473,7 @@ "signature": [ "\"kibana.alert.rule.description\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -488,7 +488,7 @@ "signature": [ "\"kibana.alert.rule.enabled\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -533,7 +533,7 @@ "signature": [ "\"kibana.alert.rule.from\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -548,7 +548,7 @@ "signature": [ "\"kibana.alert.rule.interval\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -563,7 +563,7 @@ "signature": [ "\"kibana.alert.rule.license\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -623,7 +623,7 @@ "signature": [ "\"kibana.alert.rule.note\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -668,7 +668,7 @@ "signature": [ "\"kibana.alert.rule.references\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -683,7 +683,7 @@ "signature": [ "\"kibana.alert.rule.rule_id\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -698,7 +698,7 @@ "signature": [ "\"kibana.alert.rule.rule_name_override\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -728,7 +728,7 @@ "signature": [ "\"kibana.alert.rule.to\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -743,7 +743,7 @@ "signature": [ "\"kibana.alert.rule.type\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -773,7 +773,7 @@ "signature": [ "\"kibana.alert.rule.updated_at\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -788,7 +788,7 @@ "signature": [ "\"kibana.alert.rule.updated_by\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -818,7 +818,7 @@ "signature": [ "\"kibana.alert.rule.version\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -833,7 +833,7 @@ "signature": [ "\"kibana.alert.severity\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -938,7 +938,7 @@ "signature": [ "\"kibana.alert.suppression.docs_count\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -953,7 +953,7 @@ "signature": [ "\"kibana.alert.suppression.end\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -968,7 +968,7 @@ "signature": [ "\"kibana.alert.suppression.terms.field\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -983,7 +983,7 @@ "signature": [ "\"kibana.alert.suppression.start\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -998,7 +998,7 @@ "signature": [ "\"kibana.alert.suppression.terms\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1013,7 +1013,7 @@ "signature": [ "\"kibana.alert.suppression.terms.value\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1028,7 +1028,7 @@ "signature": [ "\"kibana.alert.system_status\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1223,7 +1223,7 @@ "signature": [ "\"kibana.alert.workflow_reason\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1253,7 +1253,7 @@ "signature": [ "\"kibana.alert.workflow_user\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1311,7 +1311,7 @@ "label": "DefaultAlertFieldName", "description": [], "signature": [ - "\"kibana\" | \"kibana.alert.rule.rule_type_id\" | \"kibana.alert.rule.consumer\" | \"kibana.alert.rule.execution.uuid\" | \"kibana.alert\" | \"kibana.alert.rule\" | \"kibana.alert.rule.parameters\" | \"kibana.alert.rule.producer\" | \"kibana.space_ids\" | \"kibana.alert.uuid\" | \"kibana.alert.start\" | \"kibana.alert.time_range\" | \"kibana.alert.end\" | \"kibana.alert.duration.us\" | \"kibana.alert.status\" | \"kibana.alert.flapping\" | \"kibana.version\" | \"kibana.alert.workflow_status\" | \"kibana.alert.action_group\" | \"kibana.alert.reason\" | \"kibana.alert.rule.category\" | \"kibana.alert.rule.uuid\" | \"kibana.alert.rule.name\" | \"kibana.alert.rule.tags\" | \"kibana.alert.last_detected\" | \"kibana.alert.id\"" + "\"@timestamp\" | \"kibana\" | \"kibana.alert.rule.rule_type_id\" | \"kibana.alert.rule.consumer\" | \"kibana.alert.rule.execution.uuid\" | \"kibana.alert\" | \"kibana.alert.action_group\" | \"kibana.alert.case_ids\" | \"kibana.alert.duration.us\" | \"kibana.alert.end\" | \"kibana.alert.flapping\" | \"kibana.alert.flapping_history\" | \"kibana.alert.instance.id\" | \"kibana.alert.last_detected\" | \"kibana.alert.reason\" | \"kibana.alert.rule\" | \"kibana.alert.rule.category\" | \"kibana.alert.rule.name\" | \"kibana.alert.rule.parameters\" | \"kibana.alert.rule.producer\" | \"kibana.alert.rule.tags\" | \"kibana.alert.rule.uuid\" | \"kibana.alert.start\" | \"kibana.alert.status\" | \"kibana.alert.time_range\" | \"kibana.alert.uuid\" | \"kibana.alert.workflow_status\" | \"kibana.space_ids\" | \"kibana.version\"" ], "path": "packages/kbn-rule-data-utils/src/default_alerts_as_data.ts", "deprecated": false, @@ -1328,7 +1328,7 @@ "signature": [ "\"ecs.version\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1343,7 +1343,7 @@ "signature": [ "\"event.action\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1358,7 +1358,7 @@ "signature": [ "\"event.kind\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1463,7 +1463,7 @@ "signature": [ "\"tags\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/legacy_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -1476,7 +1476,7 @@ "label": "TechnicalRuleDataFieldName", "description": [], "signature": [ - "\"@timestamp\" | \"event.action\" | \"tags\" | \"kibana\" | \"kibana.alert.rule.rule_type_id\" | \"kibana.alert.rule.consumer\" | \"kibana.alert.rule.execution.uuid\" | \"kibana.alert\" | \"kibana.alert.rule\" | \"kibana.alert.rule.parameters\" | \"kibana.alert.rule.producer\" | \"kibana.space_ids\" | \"kibana.alert.uuid\" | \"kibana.alert.instance.id\" | \"kibana.alert.start\" | \"kibana.alert.time_range\" | \"kibana.alert.end\" | \"kibana.alert.duration.us\" | \"kibana.alert.severity\" | \"kibana.alert.status\" | \"kibana.alert.flapping\" | \"kibana.version\" | \"ecs.version\" | \"kibana.alert.risk_score\" | \"kibana.alert.workflow_status\" | \"kibana.alert.workflow_user\" | \"kibana.alert.workflow_reason\" | \"kibana.alert.system_status\" | \"kibana.alert.action_group\" | \"kibana.alert.reason\" | \"kibana.alert.case_ids\" | \"kibana.alert.rule.author\" | \"kibana.alert.rule.category\" | \"kibana.alert.rule.uuid\" | \"kibana.alert.rule.created_at\" | \"kibana.alert.rule.created_by\" | \"kibana.alert.rule.description\" | \"kibana.alert.rule.enabled\" | \"kibana.alert.rule.from\" | \"kibana.alert.rule.interval\" | \"kibana.alert.rule.license\" | \"kibana.alert.rule.name\" | \"kibana.alert.rule.note\" | \"kibana.alert.rule.references\" | \"kibana.alert.rule.rule_id\" | \"kibana.alert.rule.rule_name_override\" | \"kibana.alert.rule.tags\" | \"kibana.alert.rule.to\" | \"kibana.alert.rule.type\" | \"kibana.alert.rule.updated_at\" | \"kibana.alert.rule.updated_by\" | \"kibana.alert.rule.version\" | \"kibana.alert.suppression.terms\" | \"kibana.alert.suppression.terms.field\" | \"kibana.alert.suppression.terms.value\" | \"kibana.alert.suppression.start\" | \"kibana.alert.suppression.end\" | \"kibana.alert.suppression.docs_count\" | \"event.kind\" | \"event.module\" | \"kibana.alert.evaluation.threshold\" | \"kibana.alert.evaluation.value\" | \"kibana.alert.building_block_type\" | \"kibana.alert.rule.exceptions_list\" | \"kibana.alert.rule.namespace\" | \"kibana.alert.rule.threat.framework\" | \"kibana.alert.rule.threat.tactic.id\" | \"kibana.alert.rule.threat.tactic.name\" | \"kibana.alert.rule.threat.tactic.reference\" | \"kibana.alert.rule.threat.technique.id\" | \"kibana.alert.rule.threat.technique.name\" | \"kibana.alert.rule.threat.technique.reference\" | \"kibana.alert.rule.threat.technique.subtechnique.id\" | \"kibana.alert.rule.threat.technique.subtechnique.name\" | \"kibana.alert.rule.threat.technique.subtechnique.reference\"" + "\"@timestamp\" | \"event.action\" | \"tags\" | \"kibana\" | \"kibana.alert.rule.rule_type_id\" | \"kibana.alert.rule.consumer\" | \"kibana.alert.rule.execution.uuid\" | \"kibana.alert\" | \"kibana.alert.action_group\" | \"kibana.alert.case_ids\" | \"kibana.alert.duration.us\" | \"kibana.alert.end\" | \"kibana.alert.flapping\" | \"kibana.alert.instance.id\" | \"kibana.alert.reason\" | \"kibana.alert.rule\" | \"kibana.alert.rule.category\" | \"kibana.alert.rule.name\" | \"kibana.alert.rule.parameters\" | \"kibana.alert.rule.producer\" | \"kibana.alert.rule.tags\" | \"kibana.alert.rule.uuid\" | \"kibana.alert.start\" | \"kibana.alert.status\" | \"kibana.alert.time_range\" | \"kibana.alert.uuid\" | \"kibana.alert.workflow_status\" | \"kibana.space_ids\" | \"kibana.version\" | \"kibana.alert.risk_score\" | \"kibana.alert.rule.author\" | \"kibana.alert.rule.created_at\" | \"kibana.alert.rule.created_by\" | \"kibana.alert.rule.description\" | \"kibana.alert.rule.enabled\" | \"kibana.alert.rule.from\" | \"kibana.alert.rule.interval\" | \"kibana.alert.rule.license\" | \"kibana.alert.rule.note\" | \"kibana.alert.rule.references\" | \"kibana.alert.rule.rule_id\" | \"kibana.alert.rule.rule_name_override\" | \"kibana.alert.rule.to\" | \"kibana.alert.rule.type\" | \"kibana.alert.rule.updated_at\" | \"kibana.alert.rule.updated_by\" | \"kibana.alert.rule.version\" | \"kibana.alert.severity\" | \"kibana.alert.suppression.docs_count\" | \"kibana.alert.suppression.end\" | \"kibana.alert.suppression.terms\" | \"kibana.alert.suppression.terms.field\" | \"kibana.alert.suppression.start\" | \"kibana.alert.suppression.terms.value\" | \"kibana.alert.system_status\" | \"kibana.alert.workflow_reason\" | \"kibana.alert.workflow_user\" | \"ecs.version\" | \"event.kind\" | \"kibana.alert.evaluation.threshold\" | \"kibana.alert.evaluation.value\" | \"event.module\" | \"kibana.alert.building_block_type\" | \"kibana.alert.rule.exceptions_list\" | \"kibana.alert.rule.namespace\" | \"kibana.alert.rule.threat.framework\" | \"kibana.alert.rule.threat.tactic.id\" | \"kibana.alert.rule.threat.tactic.name\" | \"kibana.alert.rule.threat.tactic.reference\" | \"kibana.alert.rule.threat.technique.id\" | \"kibana.alert.rule.threat.technique.name\" | \"kibana.alert.rule.threat.technique.reference\" | \"kibana.alert.rule.threat.technique.subtechnique.id\" | \"kibana.alert.rule.threat.technique.subtechnique.name\" | \"kibana.alert.rule.threat.technique.subtechnique.reference\"" ], "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", "deprecated": false, @@ -1493,7 +1493,7 @@ "signature": [ "\"@timestamp\"" ], - "path": "packages/kbn-rule-data-utils/src/technical_field_names.ts", + "path": "packages/kbn-rule-data-utils/src/default_alerts_as_data.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 24bbcf7806d47..314a0e7da1a48 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-27 +date: 2023-02-28 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 280afbc3028e4..5a8bc014bed9c 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-27 +date: 2023-02-28 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 b52227497982a..5ee5d919296b0 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-27 +date: 2023-02-28 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 5e2dbdeb7c034..bd64b1db81bfc 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-27 +date: 2023-02-28 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 d610a4cd3eb85..85aceb9690e36 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-27 +date: 2023-02-28 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 50ca1b14e44a3..5bc067d5e6340 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-27 +date: 2023-02-28 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 dcb989b2881ad..9864d4070a64f 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-27 +date: 2023-02-28 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 35b7b45d54e6f..f2095245ff1ac 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-27 +date: 2023-02-28 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 085842ffd707e..5668e299d77f0 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-27 +date: 2023-02-28 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 7e355cc10b8dc..d8d0c9c9871d8 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-27 +date: 2023-02-28 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 cd458e3bd8070..82a67efe6b38a 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-27 +date: 2023-02-28 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 27628ddca800f..e0f50cd3efed4 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-27 +date: 2023-02-28 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 b33fa79e75be6..cf55a63421c8d 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-27 +date: 2023-02-28 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 85723f920c3b1..73199675135f7 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-27 +date: 2023-02-28 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 8d1de91435814..d8cc6bdea546d 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-27 +date: 2023-02-28 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 58f76d4772be0..be04da8990108 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-27 +date: 2023-02-28 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 919c81d834263..b870995270f14 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-27 +date: 2023-02-28 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 e069f4f2a258f..e2f2fa7144b85 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-27 +date: 2023-02-28 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 c1ea8d74f6da6..733dda4175166 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-27 +date: 2023-02-28 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 4673569b1f4e1..e58c594bf32bf 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-27 +date: 2023-02-28 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 bc065cf2a4cba..2269ceb340140 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-27 +date: 2023-02-28 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 d553b227b1143..8e47740cb12e6 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-27 +date: 2023-02-28 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 4a39bf9fb3c9e..07e493a7cb81a 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-27 +date: 2023-02-28 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 c7deece2ea113..0c681b7541cb9 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-27 +date: 2023-02-28 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 fa35a43514eeb..606d8505db64b 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-27 +date: 2023-02-28 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 3586f053ac47f..168ffd1305214 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-27 +date: 2023-02-28 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 2e1bffe344d14..df21948c046b9 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_shared_ux_file_context.devdocs.json index 02025b778807c..a48e1addf9ede 100644 --- a/api_docs/kbn_shared_ux_file_context.devdocs.json +++ b/api_docs/kbn_shared_ux_file_context.devdocs.json @@ -99,7 +99,13 @@ "\nA files client that will be used process uploads." ], "signature": [ - "BaseFilesClient", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.BaseFilesClient", + "text": "BaseFilesClient" + }, "" ], "path": "packages/shared-ux/file/context/src/index.tsx", diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index bae037be686b5..17a197cb50150 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_shared_ux_file_image.devdocs.json index 5d3350f6cf444..4dfade1406167 100644 --- a/api_docs/kbn_shared_ux_file_image.devdocs.json +++ b/api_docs/kbn_shared_ux_file_image.devdocs.json @@ -83,7 +83,13 @@ "description": [], "signature": [ "{ meta?: ", - "FileImageMetadata", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileImageMetadata", + "text": "FileImageMetadata" + }, " | undefined; } & ", "EuiImageProps" ], diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index 4dffa9c1aef61..4ca4a262aac6c 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-27 +date: 2023-02-28 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 69bfe48a537c0..3bd8feca9cc06 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_shared_ux_file_mocks.devdocs.json index ecdb910452dba..1a16eeed01e56 100644 --- a/api_docs/kbn_shared_ux_file_mocks.devdocs.json +++ b/api_docs/kbn_shared_ux_file_mocks.devdocs.json @@ -36,7 +36,13 @@ "text": "DeeplyMockedKeys" }, "<", - "BaseFilesClient", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.BaseFilesClient", + "text": "BaseFilesClient" + }, ">" ], "path": "packages/shared-ux/file/mocks/index.ts", diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index 6ffefddd67b1e..14e59f85eee8b 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_shared_ux_file_picker.devdocs.json index 0838853073257..1ecf0fc909e4e 100644 --- a/api_docs/kbn_shared_ux_file_picker.devdocs.json +++ b/api_docs/kbn_shared_ux_file_picker.devdocs.json @@ -117,7 +117,13 @@ ], "signature": [ "((file: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, ") => boolean) | undefined" ], "path": "packages/shared-ux/file/file_picker/impl/src/file_picker.tsx", @@ -132,7 +138,13 @@ "label": "file", "description": [], "signature": [ - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "" ], "path": "packages/shared-ux/file/file_picker/impl/src/file_picker.tsx", @@ -172,7 +184,13 @@ ], "signature": [ "(files: ", - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "[]) => void" ], "path": "packages/shared-ux/file/file_picker/impl/src/file_picker.tsx", @@ -187,7 +205,13 @@ "label": "files", "description": [], "signature": [ - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "[]" ], "path": "packages/shared-ux/file/file_picker/impl/src/file_picker.tsx", diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index c84800f82883a..f4abb5309c5e6 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-27 +date: 2023-02-28 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_types.devdocs.json b/api_docs/kbn_shared_ux_file_types.devdocs.json new file mode 100644 index 0000000000000..de6c162159d55 --- /dev/null +++ b/api_docs/kbn_shared_ux_file_types.devdocs.json @@ -0,0 +1,1581 @@ +{ + "id": "@kbn/shared-ux-file-types", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.Abortable", + "type": "Interface", + "tags": [], + "label": "Abortable", + "description": [], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.Abortable.abortSignal", + "type": "Object", + "tags": [], + "label": "abortSignal", + "description": [], + "signature": [ + "AbortSignal | undefined" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient", + "type": "Interface", + "tags": [], + "label": "BaseFilesClient", + "description": [], + "signature": [ + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.BaseFilesClient", + "text": "BaseFilesClient" + }, + "" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.find", + "type": "Function", + "tags": [], + "label": "find", + "description": [ + "\nFind a set of files given some filters.\n" + ], + "signature": [ + "(args: { kind?: string | string[] | undefined; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, + " & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ files: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + "[]; total: number; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.find.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- File filters" + ], + "signature": [ + "{ kind?: string | string[] | undefined; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, + " & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.bulkDelete", + "type": "Function", + "tags": [], + "label": "bulkDelete", + "description": [ + "\nBulk a delete a set of files given their IDs.\n" + ], + "signature": [ + "(args: { ids: string[]; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ succeeded: string[]; failed?: [id: string, reason: string][] | undefined; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.bulkDelete.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- Bulk delete args" + ], + "signature": [ + "{ ids: string[]; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [ + "\nCreate a new file object with the provided metadata.\n" + ], + "signature": [ + "(args: { name: string; meta?: M | undefined; alt?: string | undefined; mimeType?: string | undefined; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ file: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + "; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.create.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- create file args" + ], + "signature": [ + "{ name: string; meta?: M | undefined; alt?: string | undefined; mimeType?: string | undefined; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.delete", + "type": "Function", + "tags": [], + "label": "delete", + "description": [ + "\nDelete a file object and all associated share and content objects.\n" + ], + "signature": [ + "(args: { id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ ok: true; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.delete.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- delete file args" + ], + "signature": [ + "{ id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getById", + "type": "Function", + "tags": [], + "label": "getById", + "description": [ + "\nGet a file object by ID.\n" + ], + "signature": [ + "(args: { id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ file: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + "; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getById.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- get file by ID args" + ], + "signature": [ + "{ id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.list", + "type": "Function", + "tags": [], + "label": "list", + "description": [ + "\nList all file objects, of a given {@link FileKindBrowser}.\n" + ], + "signature": [ + "(args: { kind: string; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, + " & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ files: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + "[]; total: number; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.list.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- list files args" + ], + "signature": [ + "{ kind: string; status?: string | string[] | undefined; extension?: string | string[] | undefined; name?: string | string[] | undefined; meta?: M | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, + " & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.update", + "type": "Function", + "tags": [], + "label": "update", + "description": [ + "\nUpdate a set of of metadata values of the file object.\n" + ], + "signature": [ + "(args: { id: string; kind: string; name?: string | undefined; meta?: M | undefined; alt?: string | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ file: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + "; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.update.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- update file args" + ], + "signature": [ + "{ id: string; kind: string; name?: string | undefined; meta?: M | undefined; alt?: string | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.upload", + "type": "Function", + "tags": [], + "label": "upload", + "description": [ + "\nStream the contents of the file to Kibana server for storage.\n" + ], + "signature": [ + "(args: { id: string; body: unknown; kind: string; abortSignal?: AbortSignal | undefined; contentType?: string | undefined; selfDestructOnAbort?: boolean | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ ok: true; size: number; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.upload.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- upload file args" + ], + "signature": [ + "{ id: string; body: unknown; kind: string; abortSignal?: AbortSignal | undefined; contentType?: string | undefined; selfDestructOnAbort?: boolean | undefined; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.download", + "type": "Function", + "tags": [], + "label": "download", + "description": [ + "\nStream a download of the file object's content.\n" + ], + "signature": [ + "(args: { fileName?: string | undefined; id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.download.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- download file args" + ], + "signature": [ + "{ fileName?: string | undefined; id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getDownloadHref", + "type": "Function", + "tags": [], + "label": "getDownloadHref", + "description": [ + "\nGet a string for downloading a file that can be passed to a button element's\nhref for download.\n" + ], + "signature": [ + "(args: Pick<", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + ", \"id\" | \"fileKind\">) => string" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getDownloadHref.$1", + "type": "Object", + "tags": [], + "label": "args", + "description": [ + "- get download URL args" + ], + "signature": [ + "Pick<", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + ", \"id\" | \"fileKind\">" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.share", + "type": "Function", + "tags": [ + "note" + ], + "label": "share", + "description": [ + "\nShare a file by creating a new file share instance.\n" + ], + "signature": [ + "(args: { name?: string | undefined; validUntil?: number | undefined; fileId: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSONWithToken", + "text": "FileShareJSONWithToken" + }, + ">" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.share.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- File share arguments" + ], + "signature": [ + "{ name?: string | undefined; validUntil?: number | undefined; fileId: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.unshare", + "type": "Function", + "tags": [], + "label": "unshare", + "description": [ + "\nDelete a file share instance.\n" + ], + "signature": [ + "(args: { id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ ok: true; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.unshare.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- File unshare arguments" + ], + "signature": [ + "{ id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getShare", + "type": "Function", + "tags": [], + "label": "getShare", + "description": [ + "\nGet a file share instance.\n" + ], + "signature": [ + "(args: { id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ share: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" + }, + "; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getShare.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- Get file share arguments" + ], + "signature": [ + "{ id: string; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.listShares", + "type": "Function", + "tags": [], + "label": "listShares", + "description": [ + "\nList all file shares. Optionally scoping to a specific\nfile.\n" + ], + "signature": [ + "(args: { forFileId?: string | undefined; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, + " & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + }, + ") => Promise<{ shares: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" + }, + "[]; }>" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.listShares.$1", + "type": "CompoundType", + "tags": [], + "label": "args", + "description": [ + "- Get file share arguments" + ], + "signature": [ + "{ forFileId?: string | undefined; kind: string; } & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Pagination", + "text": "Pagination" + }, + " & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.Abortable", + "text": "Abortable" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getFileKind", + "type": "Function", + "tags": [], + "label": "getFileKind", + "description": [ + "\nGet a file kind" + ], + "signature": [ + "(id: string) => ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBase", + "text": "FileKindBase" + } + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFilesClient.getFileKind.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [ + "The id of the file kind" + ], + "signature": [ + "string" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileImageMetadata", + "type": "Interface", + "tags": [], + "label": "FileImageMetadata", + "description": [ + "\nSet of metadata captured for every image uploaded via the file services'\npublic components." + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileImageMetadata.blurhash", + "type": "string", + "tags": [], + "label": "blurhash", + "description": [ + "\nThe blurhash that can be displayed while the image is loading" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileImageMetadata.width", + "type": "number", + "tags": [], + "label": "width", + "description": [ + "\nWidth, in px, of the original image" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileImageMetadata.height", + "type": "number", + "tags": [], + "label": "height", + "description": [ + "\nHeight, in px, of the original image" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON", + "type": "Interface", + "tags": [], + "label": "FileJSON", + "description": [ + "\nAttributes of a file that represent a serialised version of the file." + ], + "signature": [ + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, + "" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.id", + "type": "string", + "tags": [], + "label": "id", + "description": [ + "\nUnique file ID." + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.created", + "type": "string", + "tags": [], + "label": "created", + "description": [ + "\nISO string of when this file was created" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.updated", + "type": "string", + "tags": [], + "label": "updated", + "description": [ + "\nISO string of when the file was updated" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.name", + "type": "string", + "tags": [ + "note" + ], + "label": "name", + "description": [ + "\nFile name.\n" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.mimeType", + "type": "string", + "tags": [], + "label": "mimeType", + "description": [ + "\nMIME type of the file's contents." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.size", + "type": "number", + "tags": [], + "label": "size", + "description": [ + "\nThe size, in bytes, of the file content." + ], + "signature": [ + "number | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.extension", + "type": "string", + "tags": [ + "note" + ], + "label": "extension", + "description": [ + "\nThe file extension (dot suffix).\n" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.meta", + "type": "Uncategorized", + "tags": [], + "label": "meta", + "description": [ + "\nA consumer defined set of attributes.\n\nConsumers of the file service can add their own tags and identifiers to\na file using the \"meta\" object." + ], + "signature": [ + "Meta | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.alt", + "type": "string", + "tags": [], + "label": "alt", + "description": [ + "\nUse this text to describe the file contents for display and accessibility." + ], + "signature": [ + "string | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.fileKind", + "type": "string", + "tags": [ + "note" + ], + "label": "fileKind", + "description": [ + "\nA unique kind that governs various aspects of the file. A consumer of the\nfiles service must register a file kind and link their files to a specific\nkind.\n" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.status", + "type": "CompoundType", + "tags": [], + "label": "status", + "description": [ + "\nThe current status of the file.\n\nSee {@link FileStatus} for more details." + ], + "signature": [ + "\"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\"" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileJSON.user", + "type": "Object", + "tags": [], + "label": "user", + "description": [ + "\nUser data associated with this file" + ], + "signature": [ + "{ name?: string | undefined; id?: string | undefined; } | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileKindBase", + "type": "Interface", + "tags": [], + "label": "FileKindBase", + "description": [], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileKindBase.id", + "type": "string", + "tags": [], + "label": "id", + "description": [ + "\nUnique file kind ID" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileKindBase.allowedMimeTypes", + "type": "Array", + "tags": [ + "default" + ], + "label": "allowedMimeTypes", + "description": [ + "\nThe MIME type of the file content.\n" + ], + "signature": [ + "string[] | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileKindBrowser", + "type": "Interface", + "tags": [], + "label": "FileKindBrowser", + "description": [], + "signature": [ + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBrowser", + "text": "FileKindBrowser" + }, + " extends ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileKindBase", + "text": "FileKindBase" + } + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileKindBrowser.maxSizeBytes", + "type": "number", + "tags": [ + "default" + ], + "label": "maxSizeBytes", + "description": [ + "\nMax file contents size, in bytes, enforced for this file kind in the upload\ncomponent.\n" + ], + "signature": [ + "number | undefined" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShareJSON", + "type": "Interface", + "tags": [], + "label": "FileShareJSON", + "description": [ + "\nAttributes of a file that represent a serialised version of the file." + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShareJSON.id", + "type": "string", + "tags": [], + "label": "id", + "description": [ + "\nUnique ID share instance" + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShareJSON.created", + "type": "string", + "tags": [], + "label": "created", + "description": [ + "\nISO timestamp the share was created" + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShareJSON.validUntil", + "type": "number", + "tags": [], + "label": "validUntil", + "description": [ + "\nUnix timestamp (in milliseconds) of when this share expires" + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShareJSON.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "\nA user-friendly name for the file share" + ], + "signature": [ + "string | undefined" + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShareJSON.fileId", + "type": "string", + "tags": [], + "label": "fileId", + "description": [ + "\nThe ID of the file this share is linked to" + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.Pagination", + "type": "Interface", + "tags": [], + "label": "Pagination", + "description": [], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.Pagination.page", + "type": "number", + "tags": [], + "label": "page", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.Pagination.perPage", + "type": "number", + "tags": [], + "label": "perPage", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/shared-ux/file/types/base_file_client.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.BaseFileMetadata", + "type": "Type", + "tags": [], + "label": "BaseFileMetadata", + "description": [ + "\nFile metadata fields are defined per the ECS specification:\n\nhttps://www.elastic.co/guide/en/ecs/current/ecs-file.html\n\nCustom fields are named according to the custom field convention: \"CustomFieldName\"." + ], + "signature": [ + "{ name?: string | undefined; mime_type?: string | undefined; created?: string | undefined; size?: number | undefined; hash?: { [hashName: string]: string | undefined; md5?: string | undefined; sha1?: string | undefined; sha256?: string | undefined; sha384?: string | undefined; sha512?: string | undefined; ssdeep?: string | undefined; tlsh?: string | undefined; } | undefined; user?: { name?: string | undefined; id?: string | undefined; } | undefined; extension?: string | undefined; Alt?: string | undefined; Updated?: string | undefined; Status?: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileStatus", + "text": "FileStatus" + }, + " | undefined; ChunkSize?: number | undefined; Compression?: ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileCompression", + "text": "FileCompression" + }, + " | undefined; }" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileCompression", + "type": "Type", + "tags": [], + "label": "FileCompression", + "description": [ + "\nSupported file compression algorithms" + ], + "signature": [ + "\"none\" | \"br\" | \"gzip\" | \"deflate\"" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileMetadata", + "type": "Type", + "tags": [], + "label": "FileMetadata", + "description": [ + "\nExtra metadata on a file object specific to Kibana implementation." + ], + "signature": [ + "Required> & ", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.BaseFileMetadata", + "text": "BaseFileMetadata" + }, + " & { FileKind: string; Meta?: Meta | undefined; }" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShare", + "type": "Type", + "tags": [], + "label": "FileShare", + "description": [ + "\nData stored with a file share object" + ], + "signature": [ + "{ created: string; token: string; name?: string | undefined; valid_until: number; }" + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileShareJSONWithToken", + "type": "Type", + "tags": [ + "note" + ], + "label": "FileShareJSONWithToken", + "description": [ + "\nA version of the file share with a token included.\n" + ], + "signature": [ + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileShareJSON", + "text": "FileShareJSON" + }, + " & { token: string; }" + ], + "path": "packages/shared-ux/file/types/sharing.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/shared-ux-file-types", + "id": "def-common.FileStatus", + "type": "Type", + "tags": [], + "label": "FileStatus", + "description": [], + "signature": [ + "\"AWAITING_UPLOAD\" | \"UPLOADING\" | \"READY\" | \"UPLOAD_ERROR\" | \"DELETED\"" + ], + "path": "packages/shared-ux/file/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx new file mode 100644 index 0000000000000..8209bfcad95c2 --- /dev/null +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSharedUxFileTypesPluginApi +slug: /kibana-dev-docs/api/kbn-shared-ux-file-types +title: "@kbn/shared-ux-file-types" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/shared-ux-file-types plugin +date: 2023-02-28 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] +--- +import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; + + + +Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 70 | 0 | 9 | 0 | + +## Common + +### Interfaces + + +### Consts, variables and types + + diff --git a/api_docs/kbn_shared_ux_file_upload.devdocs.json b/api_docs/kbn_shared_ux_file_upload.devdocs.json index 143e11c571ef2..82ccfb8816f4f 100644 --- a/api_docs/kbn_shared_ux_file_upload.devdocs.json +++ b/api_docs/kbn_shared_ux_file_upload.devdocs.json @@ -119,7 +119,13 @@ "label": "fileJSON", "description": [], "signature": [ - "FileJSON", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileJSON", + "text": "FileJSON" + }, "" ], "path": "packages/shared-ux/file/file_upload/impl/src/upload_state.ts", diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 613cc2d6800b4..4a7f1131800f7 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-27 +date: 2023-02-28 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.devdocs.json b/api_docs/kbn_shared_ux_file_util.devdocs.json index c471a74aeec8e..bf89b1d3e11a3 100644 --- a/api_docs/kbn_shared_ux_file_util.devdocs.json +++ b/api_docs/kbn_shared_ux_file_util.devdocs.json @@ -144,7 +144,13 @@ ], "signature": [ "(file: Blob | File) => Promise<", - "FileImageMetadata", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileImageMetadata", + "text": "FileImageMetadata" + }, " | undefined>" ], "path": "packages/shared-ux/file/util/src/image_metadata.ts", @@ -264,7 +270,13 @@ "description": [], "signature": [ "(file: Blob | File) => Promise<", - "FileImageMetadata", + { + "pluginId": "@kbn/shared-ux-file-types", + "scope": "common", + "docId": "kibKbnSharedUxFileTypesPluginApi", + "section": "def-common.FileImageMetadata", + "text": "FileImageMetadata" + }, " | undefined>" ], "path": "packages/shared-ux/file/util/src/image_metadata.ts", diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 49cba5b2b6b35..b769fcf74f510 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-27 +date: 2023-02-28 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 bc4cd4bb296af..3e784736600a3 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-27 +date: 2023-02-28 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 a1832fbd6b9d0..fc64a58d11b5b 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-27 +date: 2023-02-28 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 69a7fadee3a7c..940644b3fd59d 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-27 +date: 2023-02-28 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 7d39cc8ff942d..b202f9f8b5870 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-27 +date: 2023-02-28 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 4d299d8c283c8..156eda71b5a8c 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-27 +date: 2023-02-28 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 1b96b08fa1505..0d4be286761e6 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-27 +date: 2023-02-28 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 41e4b50335f26..c6f9fc4ef80ad 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-27 +date: 2023-02-28 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 0b5f529b6fc2e..ae05839415131 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-27 +date: 2023-02-28 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 c092d3a7327e9..250d876c321e9 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-27 +date: 2023-02-28 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 5d3e545e34a9a..724150dcc5ac9 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-27 +date: 2023-02-28 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 e99ba437ea181..7b1b989ba6cee 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-27 +date: 2023-02-28 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 e473873e76f9c..5727efb34acce 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-27 +date: 2023-02-28 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 24adfbf9bab9a..c6af6866069c9 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-27 +date: 2023-02-28 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 f374066c21e10..87981ddb8777f 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-27 +date: 2023-02-28 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 b8c62ed4bc494..5ba46cdcc14c4 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-27 +date: 2023-02-28 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 c84c8dd68cbdb..4a0264e15a351 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-27 +date: 2023-02-28 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 6a617b21a10a9..f8f479bc82736 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-27 +date: 2023-02-28 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 e7c675c73947d..e71df0240d9a5 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-27 +date: 2023-02-28 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 287c4f3b7c580..c36b9563d5951 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-27 +date: 2023-02-28 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 52347ab66f141..060a5d9374f60 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-27 +date: 2023-02-28 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 d8a7f1f9b7677..7aa8b9b5469d8 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-27 +date: 2023-02-28 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 570ef34b459c4..302f019a118b7 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-27 +date: 2023-02-28 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 2d2152989cec8..61068adab2e94 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-27 +date: 2023-02-28 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 3d2fba338fcd2..a725bef6d1dfd 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-27 +date: 2023-02-28 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 926afb71749c5..26d5e2905557a 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-27 +date: 2023-02-28 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 783c0f7c701e2..ebaaad4fe200f 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-27 +date: 2023-02-28 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 e053e5ac872b2..bc9fc88083646 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-27 +date: 2023-02-28 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 9f9241b66735f..8d729da1d0c13 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-27 +date: 2023-02-28 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 b5bfc34bfffce..af4f7c3196754 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-27 +date: 2023-02-28 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 e2558983fbebe..8ac5a54019cef 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-27 +date: 2023-02-28 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 d843cfc415389..2e5cc062ce04f 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-27 +date: 2023-02-28 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 557f0858d2f54..01ab9a6025585 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-27 +date: 2023-02-28 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 bf45f0616677f..b87d54e58c159 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-27 +date: 2023-02-28 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 8fd07a8394192..db3164da08dfc 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-27 +date: 2023-02-28 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 30c08ee3d477b..458810012a7dd 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-27 +date: 2023-02-28 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 b7972e4cee4f9..d58966203073b 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-27 +date: 2023-02-28 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 8b66ee98cff48..68704c5518edc 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-27 +date: 2023-02-28 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 b21e5ef9bd09d..125fb40ae685c 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-27 +date: 2023-02-28 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 7434590f401f9..6e7c773415301 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-27 +date: 2023-02-28 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 bf7caa13eda59..0c7dc2488443a 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-27 +date: 2023-02-28 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 76e3f26b7df27..0d8c7b33c2bd6 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-27 +date: 2023-02-28 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 eb3497195d0ae..3e65e26219007 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-27 +date: 2023-02-28 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 070ac1c4a6068..f78260916241f 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-27 +date: 2023-02-28 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 73eda7bda3a96..6c0fb6464f98c 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-27 +date: 2023-02-28 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 6bf0149dfebb0..f381f2825210d 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-27 +date: 2023-02-28 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 2e54a482ecfa0..58fc492ba9ca5 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-27 +date: 2023-02-28 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 072f6b890c97f..dccc3f7001254 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-27 +date: 2023-02-28 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 ee4da3c15af13..c33e99100df1e 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-27 +date: 2023-02-28 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 9ca9dc4debbbe..23daa345f6194 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-27 +date: 2023-02-28 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 49b8bee6aea9c..2d3259a4aee8b 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-27 +date: 2023-02-28 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 9ba9e133f0eba..3038e387bec74 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-27 +date: 2023-02-28 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 9e7a02cf6a059..d25c61a4e27c9 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-27 +date: 2023-02-28 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 b8a6b1c234a32..d416a6004f48d 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-27 +date: 2023-02-28 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 2de6fd928dbb4..18079ba00f748 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-27 +date: 2023-02-28 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 6ca708031eb71..4615a906a1cd7 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-27 +date: 2023-02-28 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 84d73e1cc383c..fbfca60b77b13 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-27 +date: 2023-02-28 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 38b9c7b4b4a02..886a4ce48b798 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-27 +date: 2023-02-28 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 56d67962cddb2..f3b8c8d1be282 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-27 +date: 2023-02-28 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 cfad19cb77150..838c42c39dbb3 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-27 +date: 2023-02-28 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 4300df9620dfa..75c74e1f19b30 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-27 +date: 2023-02-28 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 f5423d859c0c8..4d8591294aa9b 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-27 +date: 2023-02-28 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 1229afb3755be..15c641bc7406a 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -4679,7 +4679,7 @@ "label": "format", "description": [], "signature": [ - "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", @@ -4698,7 +4698,7 @@ "label": "options", "description": [], "signature": [ - "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", @@ -6236,7 +6236,7 @@ "label": "ObservabilityRuleTypeFormatter", "description": [], "signature": [ - "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "(options: { fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", @@ -6255,7 +6255,7 @@ "label": "options", "description": [], "signature": [ - "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", + "{ fields: OutputOf> & Record; formatters: { asDuration: (value: ", "Maybe", ", { defaultValue, extended }?: FormatterOptions) => string; asPercent: (numerator: ", "Maybe", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index ad380f21e8a89..d2af532fc95fe 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/osquery.devdocs.json b/api_docs/osquery.devdocs.json index 29b2b564836a6..6232998bcc0ea 100644 --- a/api_docs/osquery.devdocs.json +++ b/api_docs/osquery.devdocs.json @@ -262,7 +262,7 @@ "label": "osqueryCreateAction", "description": [], "signature": [ - "(payload: { agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }, alertData?: OutputOf> | undefined) => void" + "(payload: { agent_ids?: string[] | undefined; agent_all?: boolean | undefined; agent_platforms?: string[] | undefined; agent_policy_ids?: string[] | undefined; query?: string | undefined; queries?: { id: string; query: string; ecs_mapping: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; version: string | undefined; platform: string | undefined; removed: boolean | undefined; snapshot: boolean | undefined; }[] | undefined; saved_query_id?: string | undefined; ecs_mapping?: { [x: string]: { field?: string | undefined; value?: string | string[] | undefined; }; } | undefined; pack_id?: string | undefined; alert_ids?: string[] | undefined; case_ids?: string[] | undefined; event_ids?: string[] | undefined; metadata?: object | undefined; }, alertData?: OutputOf> | undefined) => void" ], "path": "x-pack/plugins/osquery/server/types.ts", "deprecated": false, @@ -291,7 +291,7 @@ "label": "alertData", "description": [], "signature": [ - "OutputOf> | undefined" + "OutputOf> | undefined" ], "path": "x-pack/plugins/osquery/server/types.ts", "deprecated": false, diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index b3e3702b98a01..04f0bad23e2fe 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-27 +date: 2023-02-28 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 241f72e86a5f0..e548f18220b28 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-27 +date: 2023-02-28 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 | |--------------|----------|------------------------| -| 574 | 469 | 38 | +| 576 | 472 | 38 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 67704 | 515 | 58526 | 1238 | +| 67775 | 514 | 58529 | 1233 | ## Plugin Directory @@ -30,7 +30,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 256 | 8 | 251 | 24 | | | [@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) | - | 487 | 1 | 476 | 40 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 497 | 1 | 486 | 41 | | | [@elastic/apm-ui](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 42 | 0 | 42 | 65 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 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 | @@ -88,9 +88,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 236 | 0 | 100 | 2 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Index pattern fields and ambiguous values formatters | 288 | 26 | 249 | 3 | | | [@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) | File upload, download, sharing, and serving over HTTP implementation in Kibana. | 214 | 0 | 10 | 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) | - | 1087 | 3 | 982 | 27 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1089 | 3 | 984 | 27 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -199,6 +199,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 6 | 0 | 6 | 0 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | - | 53 | 0 | 22 | 0 | | | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 9 | 1 | 9 | 0 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 12 | 0 | 12 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 5 | 0 | 4 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 73 | 0 | 73 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 98 | 0 | 0 | 0 | @@ -323,8 +324,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@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) | - | 11 | 0 | 11 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 5 | 0 | 0 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 6 | 1 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 0 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 3 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 5 | 0 | 5 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 35 | 4 | 23 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 32 | 0 | 11 | 2 | @@ -341,7 +342,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2 | 0 | 2 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2 | 0 | 2 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 1 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 23 | 1 | 22 | 0 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 25 | 1 | 24 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 107 | 1 | 0 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 334 | 1 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 75 | 0 | 54 | 1 | @@ -354,7 +355,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 71 | 0 | 39 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 25 | 0 | 23 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 4 | 0 | 4 | 0 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 112 | 0 | 79 | 45 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 116 | 0 | 81 | 46 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 12 | 0 | 12 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 489 | 1 | 98 | 4 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 69 | 0 | 69 | 4 | @@ -402,6 +403,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 251 | 1 | 193 | 15 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 12 | 0 | 12 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 1 | 0 | +| | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 13 | 0 | 4 | 3 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 20 | 0 | 16 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 2 | 0 | 0 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 29 | 0 | 29 | 1 | @@ -480,6 +482,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 1 | 0 | 1 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 14 | 0 | 6 | 0 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 70 | 0 | 9 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 7 | 0 | 7 | 1 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 17 | 0 | 15 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 17 | 0 | 9 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 2e4c690bdfde2..a9ab65763cfb8 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-27 +date: 2023-02-28 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 4e7eff9bad9ea..deba0cdcd5085 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-27 +date: 2023-02-28 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 50384f02b70fd..aaab91fddc3a4 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-27 +date: 2023-02-28 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 d22bdb346e94b..9dfd0ab61a8ae 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-27 +date: 2023-02-28 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 9b051aa152030..a2a19da59470f 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-27 +date: 2023-02-28 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 e9bed596ec7e7..e0588585ba405 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -107,7 +107,7 @@ "label": "get", "description": [], "signature": [ - "({ id, index }: GetAlertParams) => Promise> | undefined>" + "({ id, index }: GetAlertParams) => Promise> | undefined>" ], "path": "x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts", "deprecated": false, @@ -325,7 +325,7 @@ "SortOptions", "[] | undefined; track_total_hits?: boolean | undefined; _source?: string[] | undefined; }) => Promise<", "SearchResponse", - ">, Record>, Record>>" ], @@ -1901,7 +1901,7 @@ "RuleTypeParamsValidator", " | undefined; } | undefined; cancelAlertsOnRuleTimeout?: boolean | undefined; alerts?: ", "IRuleTypeAlerts", - " | undefined; actionGroups: ", + " | undefined; producer: string; actionGroups: ", { "pluginId": "alerting", "scope": "common", @@ -1917,7 +1917,7 @@ "section": "def-common.ActionGroup", "text": "ActionGroup" }, - " | undefined; producer: string; actionVariables?: { context?: ", + " | undefined; actionVariables?: { context?: ", { "pluginId": "alerting", "scope": "common", @@ -2573,7 +2573,7 @@ "signature": [ "> & OutputOf>>>(request: TSearchRequest) => Promise<", + ", TAlertDoc = Partial> & OutputOf>>>(request: TSearchRequest) => Promise<", { "pluginId": "@kbn/es-types", "scope": "common", @@ -3210,7 +3210,7 @@ "label": "getAlertByAlertUuid", "description": [], "signature": [ - "(alertUuid: string) => Promise> & OutputOf>> | null> | null" + "(alertUuid: string) => Promise> & OutputOf>> | null> | null" ], "path": "x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts", "deprecated": false, @@ -4603,7 +4603,7 @@ "label": "parseTechnicalFields", "description": [], "signature": [ - "(input: unknown, partial?: boolean) => OutputOf>" + "(input: unknown, partial?: boolean) => OutputOf>" ], "path": "x-pack/plugins/rule_registry/common/parse_technical_fields.ts", "deprecated": false, @@ -4979,7 +4979,7 @@ "label": "ParsedTechnicalFields", "description": [], "signature": [ - "{ readonly '@timestamp': string; readonly \"kibana.alert.rule.rule_type_id\": string; readonly \"kibana.alert.rule.consumer\": string; readonly \"kibana.alert.rule.producer\": string; readonly \"kibana.space_ids\": string[]; readonly \"kibana.alert.uuid\": string; readonly \"kibana.alert.instance.id\": string; readonly \"kibana.alert.status\": string; readonly \"kibana.alert.rule.category\": string; readonly \"kibana.alert.rule.uuid\": string; readonly \"kibana.alert.rule.name\": string; readonly 'event.action'?: string | undefined; readonly tags?: string[] | undefined; readonly \"kibana.alert.rule.execution.uuid\"?: string | undefined; readonly \"kibana.alert.rule.parameters\"?: { [key: string]: unknown; } | undefined; readonly \"kibana.alert.start\"?: string | undefined; readonly \"kibana.alert.time_range\"?: unknown; readonly \"kibana.alert.end\"?: string | undefined; readonly \"kibana.alert.duration.us\"?: number | undefined; readonly \"kibana.alert.severity\"?: string | undefined; readonly \"kibana.alert.flapping\"?: boolean | undefined; readonly \"kibana.version\"?: string | undefined; readonly \"ecs.version\"?: string | undefined; readonly \"kibana.alert.risk_score\"?: number | undefined; readonly \"kibana.alert.workflow_status\"?: string | undefined; readonly \"kibana.alert.workflow_user\"?: string | undefined; readonly \"kibana.alert.workflow_reason\"?: string | undefined; readonly \"kibana.alert.system_status\"?: string | undefined; readonly \"kibana.alert.action_group\"?: string | undefined; readonly \"kibana.alert.reason\"?: string | undefined; readonly \"kibana.alert.case_ids\"?: string[] | undefined; readonly \"kibana.alert.rule.author\"?: string | undefined; readonly \"kibana.alert.rule.created_at\"?: string | undefined; readonly \"kibana.alert.rule.created_by\"?: string | undefined; readonly \"kibana.alert.rule.description\"?: string | undefined; readonly \"kibana.alert.rule.enabled\"?: string | undefined; readonly \"kibana.alert.rule.from\"?: string | undefined; readonly \"kibana.alert.rule.interval\"?: string | undefined; readonly \"kibana.alert.rule.license\"?: string | undefined; readonly \"kibana.alert.rule.note\"?: string | undefined; readonly \"kibana.alert.rule.references\"?: string[] | undefined; readonly \"kibana.alert.rule.rule_id\"?: string | undefined; readonly \"kibana.alert.rule.rule_name_override\"?: string | undefined; readonly \"kibana.alert.rule.tags\"?: string[] | undefined; readonly \"kibana.alert.rule.to\"?: string | undefined; readonly \"kibana.alert.rule.type\"?: string | undefined; readonly \"kibana.alert.rule.updated_at\"?: string | undefined; readonly \"kibana.alert.rule.updated_by\"?: string | undefined; readonly \"kibana.alert.rule.version\"?: string | undefined; readonly \"kibana.alert.suppression.terms.field\"?: string[] | undefined; readonly \"kibana.alert.suppression.terms.value\"?: string[] | undefined; readonly \"kibana.alert.suppression.start\"?: string | undefined; readonly \"kibana.alert.suppression.end\"?: string | undefined; readonly \"kibana.alert.suppression.docs_count\"?: number | undefined; readonly \"kibana.alert.last_detected\"?: string | undefined; readonly 'event.kind'?: string | undefined; }" + "{ readonly \"@timestamp\": string; readonly \"kibana.alert.rule.rule_type_id\": string; readonly \"kibana.alert.rule.consumer\": string; readonly \"kibana.alert.instance.id\": string; readonly \"kibana.alert.rule.category\": string; readonly \"kibana.alert.rule.name\": string; readonly \"kibana.alert.rule.producer\": string; readonly \"kibana.alert.rule.uuid\": string; readonly \"kibana.alert.status\": string; readonly \"kibana.alert.uuid\": string; readonly \"kibana.space_ids\": string[]; readonly \"event.action\"?: string | undefined; readonly tags?: string[] | undefined; readonly \"kibana.alert.rule.execution.uuid\"?: string | undefined; readonly \"kibana.alert.action_group\"?: string | undefined; readonly \"kibana.alert.case_ids\"?: string[] | undefined; readonly \"kibana.alert.duration.us\"?: number | undefined; readonly \"kibana.alert.end\"?: string | undefined; readonly \"kibana.alert.flapping\"?: boolean | undefined; readonly \"kibana.alert.flapping_history\"?: boolean[] | undefined; readonly \"kibana.alert.last_detected\"?: string | undefined; readonly \"kibana.alert.reason\"?: string | undefined; readonly \"kibana.alert.rule.parameters\"?: { [key: string]: unknown; } | undefined; readonly \"kibana.alert.rule.tags\"?: string[] | undefined; readonly \"kibana.alert.start\"?: string | undefined; readonly \"kibana.alert.time_range\"?: unknown; readonly \"kibana.alert.workflow_status\"?: string | undefined; readonly \"kibana.version\"?: string | undefined; readonly \"kibana.alert.risk_score\"?: number | undefined; readonly \"kibana.alert.rule.author\"?: string | undefined; readonly \"kibana.alert.rule.created_at\"?: string | undefined; readonly \"kibana.alert.rule.created_by\"?: string | undefined; readonly \"kibana.alert.rule.description\"?: string | undefined; readonly \"kibana.alert.rule.enabled\"?: string | undefined; readonly \"kibana.alert.rule.from\"?: string | undefined; readonly \"kibana.alert.rule.interval\"?: string | undefined; readonly \"kibana.alert.rule.license\"?: string | undefined; readonly \"kibana.alert.rule.note\"?: string | undefined; readonly \"kibana.alert.rule.references\"?: string[] | undefined; readonly \"kibana.alert.rule.rule_id\"?: string | undefined; readonly \"kibana.alert.rule.rule_name_override\"?: string | undefined; readonly \"kibana.alert.rule.to\"?: string | undefined; readonly \"kibana.alert.rule.type\"?: string | undefined; readonly \"kibana.alert.rule.updated_at\"?: string | undefined; readonly \"kibana.alert.rule.updated_by\"?: string | undefined; readonly \"kibana.alert.rule.version\"?: string | undefined; readonly \"kibana.alert.severity\"?: string | undefined; readonly \"kibana.alert.suppression.docs_count\"?: number | undefined; readonly \"kibana.alert.suppression.end\"?: string | undefined; readonly \"kibana.alert.suppression.terms.field\"?: string[] | undefined; readonly \"kibana.alert.suppression.start\"?: string | undefined; readonly \"kibana.alert.suppression.terms.value\"?: string[] | undefined; readonly \"kibana.alert.system_status\"?: string | undefined; readonly \"kibana.alert.workflow_reason\"?: string | undefined; readonly \"kibana.alert.workflow_user\"?: string | undefined; readonly \"ecs.version\"?: string | undefined; readonly \"event.kind\"?: string | undefined; }" ], "path": "x-pack/plugins/rule_registry/common/parse_technical_fields.ts", "deprecated": false, diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 01e03df7443c0..bafd718f19619 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-27 +date: 2023-02-28 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 d97cab5c93af0..ff7aa047cba3c 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-27 +date: 2023-02-28 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 174da172a54e0..16d7f54784ed1 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-27 +date: 2023-02-28 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 0ab98d7d02ba1..ace1059c4bed5 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-27 +date: 2023-02-28 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 526ab50e91670..6fd979ecdbb86 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-27 +date: 2023-02-28 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 505f2a42dc503..18541c12418b1 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-27 +date: 2023-02-28 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 1ef30026b02e6..442d516371a8d 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-27 +date: 2023-02-28 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 d3e548f519309..2ddbf2b3f440a 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-27 +date: 2023-02-28 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 82924478cc916..fbab93eac15de 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-27 +date: 2023-02-28 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 b7b7e30361372..5a9f3c7f4a93e 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-27 +date: 2023-02-28 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 005133426198a..913ea2418a097 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.devdocs.json b/api_docs/security_solution.devdocs.json index 037917ccefd0a..f8cb3ecf363dd 100644 --- a/api_docs/security_solution.devdocs.json +++ b/api_docs/security_solution.devdocs.json @@ -95,7 +95,7 @@ "label": "experimentalFeatures", "description": [], "signature": [ - "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly pendingActionResponsesWithAck: boolean; readonly policyListEnabled: boolean; readonly policyResponseInFleetEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly responseActionsConsoleEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointRbacEnabled: boolean; readonly endpointRbacV1Enabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionGetFileEnabled: boolean; readonly responseActionExecuteEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly riskyHostsEnabled: boolean; readonly riskyUsersEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; }" + "{ readonly tGridEnabled: boolean; readonly tGridEventRenderedViewEnabled: boolean; readonly excludePoliciesInFilterEnabled: boolean; readonly kubernetesEnabled: boolean; readonly disableIsolationUIPendingStatuses: boolean; readonly pendingActionResponsesWithAck: boolean; readonly policyListEnabled: boolean; readonly policyResponseInFleetEnabled: boolean; readonly chartEmbeddablesEnabled: boolean; readonly previewTelemetryUrlEnabled: boolean; readonly responseActionsConsoleEnabled: boolean; readonly insightsRelatedAlertsByProcessAncestry: boolean; readonly extendedRuleExecutionLoggingEnabled: boolean; readonly socTrendsEnabled: boolean; readonly responseActionsEnabled: boolean; readonly endpointRbacEnabled: boolean; readonly endpointRbacV1Enabled: boolean; readonly alertDetailsPageEnabled: boolean; readonly responseActionGetFileEnabled: boolean; readonly responseActionExecuteEnabled: boolean; readonly alertsPageChartsEnabled: boolean; readonly securityFlyoutEnabled: boolean; readonly riskyHostsEnabled: boolean; readonly riskyUsersEnabled: boolean; readonly alertsPageFiltersEnabled: boolean; }" ], "path": "x-pack/plugins/security_solution/public/plugin.tsx", "deprecated": false, diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 2b59497a340fd..eeced72ec06fe 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-27 +date: 2023-02-28 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 02183745d657e..597c0533242ca 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-27 +date: 2023-02-28 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 9d2931bad5e60..ce9b271f3639c 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-27 +date: 2023-02-28 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 39f5d7c1ae7b2..5ffe5a5072c6f 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-27 +date: 2023-02-28 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 a9bc92d8a42e0..f05bf8794e108 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-27 +date: 2023-02-28 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 be729d6bc2ecf..53063d23c2cc2 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-27 +date: 2023-02-28 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 5060499f75c43..7f1f52fa198db 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-27 +date: 2023-02-28 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 860ecb737b655..aa72caf8ee862 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.devdocs.json b/api_docs/telemetry.devdocs.json index ce31c34065ea5..cca1ac23391c3 100644 --- a/api_docs/telemetry.devdocs.json +++ b/api_docs/telemetry.devdocs.json @@ -119,7 +119,7 @@ "Should the telemetry payloads be sent from the server or the browser?" ], "signature": [ - "\"server\" | \"browser\"" + "\"browser\" | \"server\"" ], "path": "src/plugins/telemetry/public/plugin.ts", "deprecated": false, diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 8949000fbd29f..ead6ab9d2fc06 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-27 +date: 2023-02-28 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 5e94c6b49e610..bea30d56e7f3a 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-27 +date: 2023-02-28 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 a19d535900d1f..2eaa03df603b3 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-27 +date: 2023-02-28 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 1d97c165c128a..e445e28aa62ef 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-27 +date: 2023-02-28 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 7623f52a7f706..14fe41c6b8535 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-27 +date: 2023-02-28 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 47c6749027461..34740ef1b0b8a 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-27 +date: 2023-02-28 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 f169e72c7236e..860c46a6aaca7 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-27 +date: 2023-02-28 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 acac8c2932fb4..a5736cefd3749 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -2703,7 +2703,7 @@ "description": [], "signature": [ "BasicFields", - " & { \"@timestamp\"?: string[] | undefined; \"event.action\"?: string[] | undefined; tags?: string[] | undefined; kibana?: string[] | undefined; \"kibana.alert.rule.rule_type_id\"?: string[] | undefined; \"kibana.alert.rule.consumer\"?: string[] | undefined; \"kibana.alert.rule.execution.uuid\"?: string[] | undefined; \"kibana.alert\"?: string[] | undefined; \"kibana.alert.rule\"?: string[] | undefined; \"kibana.alert.rule.parameters\"?: string[] | undefined; \"kibana.alert.rule.producer\"?: string[] | undefined; \"kibana.space_ids\"?: string[] | undefined; \"kibana.alert.uuid\"?: string[] | undefined; \"kibana.alert.instance.id\"?: string[] | undefined; \"kibana.alert.start\"?: string[] | undefined; \"kibana.alert.time_range\"?: string[] | undefined; \"kibana.alert.end\"?: string[] | undefined; \"kibana.alert.duration.us\"?: string[] | undefined; \"kibana.alert.severity\"?: string[] | undefined; \"kibana.alert.status\"?: string[] | undefined; \"kibana.alert.flapping\"?: string[] | undefined; \"kibana.version\"?: string[] | undefined; \"ecs.version\"?: string[] | undefined; \"kibana.alert.risk_score\"?: string[] | undefined; \"kibana.alert.workflow_status\"?: string[] | undefined; \"kibana.alert.workflow_user\"?: string[] | undefined; \"kibana.alert.workflow_reason\"?: string[] | undefined; \"kibana.alert.system_status\"?: string[] | undefined; \"kibana.alert.action_group\"?: string[] | undefined; \"kibana.alert.reason\"?: string[] | undefined; \"kibana.alert.case_ids\"?: string[] | undefined; \"kibana.alert.rule.author\"?: string[] | undefined; \"kibana.alert.rule.category\"?: string[] | undefined; \"kibana.alert.rule.uuid\"?: string[] | undefined; \"kibana.alert.rule.created_at\"?: string[] | undefined; \"kibana.alert.rule.created_by\"?: string[] | undefined; \"kibana.alert.rule.description\"?: string[] | undefined; \"kibana.alert.rule.enabled\"?: string[] | undefined; \"kibana.alert.rule.from\"?: string[] | undefined; \"kibana.alert.rule.interval\"?: string[] | undefined; \"kibana.alert.rule.license\"?: string[] | undefined; \"kibana.alert.rule.name\"?: string[] | undefined; \"kibana.alert.rule.note\"?: string[] | undefined; \"kibana.alert.rule.references\"?: string[] | undefined; \"kibana.alert.rule.rule_id\"?: string[] | undefined; \"kibana.alert.rule.rule_name_override\"?: string[] | undefined; \"kibana.alert.rule.tags\"?: string[] | undefined; \"kibana.alert.rule.to\"?: string[] | undefined; \"kibana.alert.rule.type\"?: string[] | undefined; \"kibana.alert.rule.updated_at\"?: string[] | undefined; \"kibana.alert.rule.updated_by\"?: string[] | undefined; \"kibana.alert.rule.version\"?: string[] | undefined; \"kibana.alert.suppression.terms\"?: string[] | undefined; \"kibana.alert.suppression.terms.field\"?: string[] | undefined; \"kibana.alert.suppression.terms.value\"?: string[] | undefined; \"kibana.alert.suppression.start\"?: string[] | undefined; \"kibana.alert.suppression.end\"?: string[] | undefined; \"kibana.alert.suppression.docs_count\"?: string[] | undefined; \"event.kind\"?: string[] | undefined; \"event.module\"?: string[] | undefined; \"kibana.alert.evaluation.threshold\"?: string[] | undefined; \"kibana.alert.evaluation.value\"?: string[] | undefined; \"kibana.alert.building_block_type\"?: string[] | undefined; \"kibana.alert.rule.exceptions_list\"?: string[] | undefined; \"kibana.alert.rule.namespace\"?: string[] | undefined; \"kibana.alert.rule.threat.framework\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.id\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.name\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.reference\"?: string[] | undefined; } & { [x: string]: unknown[]; }" + " & { \"@timestamp\"?: string[] | undefined; \"event.action\"?: string[] | undefined; tags?: string[] | undefined; kibana?: string[] | undefined; \"kibana.alert.rule.rule_type_id\"?: string[] | undefined; \"kibana.alert.rule.consumer\"?: string[] | undefined; \"kibana.alert.rule.execution.uuid\"?: string[] | undefined; \"kibana.alert\"?: string[] | undefined; \"kibana.alert.action_group\"?: string[] | undefined; \"kibana.alert.case_ids\"?: string[] | undefined; \"kibana.alert.duration.us\"?: string[] | undefined; \"kibana.alert.end\"?: string[] | undefined; \"kibana.alert.flapping\"?: string[] | undefined; \"kibana.alert.instance.id\"?: string[] | undefined; \"kibana.alert.reason\"?: string[] | undefined; \"kibana.alert.rule\"?: string[] | undefined; \"kibana.alert.rule.category\"?: string[] | undefined; \"kibana.alert.rule.name\"?: string[] | undefined; \"kibana.alert.rule.parameters\"?: string[] | undefined; \"kibana.alert.rule.producer\"?: string[] | undefined; \"kibana.alert.rule.tags\"?: string[] | undefined; \"kibana.alert.rule.uuid\"?: string[] | undefined; \"kibana.alert.start\"?: string[] | undefined; \"kibana.alert.status\"?: string[] | undefined; \"kibana.alert.time_range\"?: string[] | undefined; \"kibana.alert.uuid\"?: string[] | undefined; \"kibana.alert.workflow_status\"?: string[] | undefined; \"kibana.space_ids\"?: string[] | undefined; \"kibana.version\"?: string[] | undefined; \"kibana.alert.risk_score\"?: string[] | undefined; \"kibana.alert.rule.author\"?: string[] | undefined; \"kibana.alert.rule.created_at\"?: string[] | undefined; \"kibana.alert.rule.created_by\"?: string[] | undefined; \"kibana.alert.rule.description\"?: string[] | undefined; \"kibana.alert.rule.enabled\"?: string[] | undefined; \"kibana.alert.rule.from\"?: string[] | undefined; \"kibana.alert.rule.interval\"?: string[] | undefined; \"kibana.alert.rule.license\"?: string[] | undefined; \"kibana.alert.rule.note\"?: string[] | undefined; \"kibana.alert.rule.references\"?: string[] | undefined; \"kibana.alert.rule.rule_id\"?: string[] | undefined; \"kibana.alert.rule.rule_name_override\"?: string[] | undefined; \"kibana.alert.rule.to\"?: string[] | undefined; \"kibana.alert.rule.type\"?: string[] | undefined; \"kibana.alert.rule.updated_at\"?: string[] | undefined; \"kibana.alert.rule.updated_by\"?: string[] | undefined; \"kibana.alert.rule.version\"?: string[] | undefined; \"kibana.alert.severity\"?: string[] | undefined; \"kibana.alert.suppression.docs_count\"?: string[] | undefined; \"kibana.alert.suppression.end\"?: string[] | undefined; \"kibana.alert.suppression.terms\"?: string[] | undefined; \"kibana.alert.suppression.terms.field\"?: string[] | undefined; \"kibana.alert.suppression.start\"?: string[] | undefined; \"kibana.alert.suppression.terms.value\"?: string[] | undefined; \"kibana.alert.system_status\"?: string[] | undefined; \"kibana.alert.workflow_reason\"?: string[] | undefined; \"kibana.alert.workflow_user\"?: string[] | undefined; \"ecs.version\"?: string[] | undefined; \"event.kind\"?: string[] | undefined; \"kibana.alert.evaluation.threshold\"?: string[] | undefined; \"kibana.alert.evaluation.value\"?: string[] | undefined; \"event.module\"?: string[] | undefined; \"kibana.alert.building_block_type\"?: string[] | undefined; \"kibana.alert.rule.exceptions_list\"?: string[] | undefined; \"kibana.alert.rule.namespace\"?: string[] | undefined; \"kibana.alert.rule.threat.framework\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.id\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.name\"?: string[] | undefined; \"kibana.alert.rule.threat.tactic.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.reference\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.id\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.name\"?: string[] | undefined; \"kibana.alert.rule.threat.technique.subtechnique.reference\"?: string[] | undefined; } & { [x: string]: unknown[]; }" ], "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, @@ -4172,7 +4172,7 @@ "section": "def-common.RuleType", "text": "RuleType" }, - ", \"id\" | \"name\" | \"actionGroups\" | \"defaultActionGroupId\" | \"recoveryActionGroup\" | \"producer\" | \"minimumLicenseRequired\" | \"defaultScheduleInterval\" | \"ruleTaskTimeout\" | \"doesSetRecoveryContext\">" + ", \"id\" | \"name\" | \"producer\" | \"actionGroups\" | \"defaultActionGroupId\" | \"recoveryActionGroup\" | \"minimumLicenseRequired\" | \"defaultScheduleInterval\" | \"ruleTaskTimeout\" | \"doesSetRecoveryContext\">" ], "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index cc5da08f265c9..2aab69671f429 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-27 +date: 2023-02-28 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 5f66671a8e6ee..c8bbb58cd83b2 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-27 +date: 2023-02-28 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 7cc0b4f939a2c..7aa3001fe08eb 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-27 +date: 2023-02-28 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 0f60b4e9df3a7..6fe0b991d6fa1 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-27 +date: 2023-02-28 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 a521051843765..11a20aaa28491 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-27 +date: 2023-02-28 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 a9a3f8bb2ca79..64d361f9de3a8 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-27 +date: 2023-02-28 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 22f36ce73aeea..938acbf44f8f1 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-27 +date: 2023-02-28 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 79040e0c7cdd2..be3bbff9a466a 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-27 +date: 2023-02-28 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 284a2037ab90b..36998816dcddc 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-27 +date: 2023-02-28 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 6fd75ea172182..185f5306ae783 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-27 +date: 2023-02-28 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 0be33385141aa..2bb4750747ba0 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-27 +date: 2023-02-28 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 2c3d8f2e3aeb1..8d9aea5b9f72e 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-27 +date: 2023-02-28 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 c9cbbb1faa746..efe160318e302 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-27 +date: 2023-02-28 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 aa93bc6b4f587..42329bc9873f6 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-27 +date: 2023-02-28 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 70d76d4c300bb..a4d39e8071188 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-27 +date: 2023-02-28 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 0b2176aad94b4..c7663b05e89cc 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-27 +date: 2023-02-28 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 4312898bd792a..62b8b9db10bc0 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-27 +date: 2023-02-28 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 5f30340988ad6..2cccc99f502f2 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-27 +date: 2023-02-28 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 9f1265bde99de..813c2d581da8f 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-27 +date: 2023-02-28 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 fae5f15be6a53..7530cbec77b3f 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-27 +date: 2023-02-28 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 ed906cba8ff0f..638333102c3b5 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-27 +date: 2023-02-28 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 0af9176d3de807ddb64c46c84c851116d9df8685 Mon Sep 17 00:00:00 2001 From: Wafaa Nasr Date: Tue, 28 Feb 2023 08:41:22 +0000 Subject: [PATCH 036/131] [Security Solution] Fix rules with connectors cannot be imported to a space different from the Default one (#151671) ## Summary - Addresses https://github.com/elastic/kibana/issues/151365 - The SavedObject service generates a new Id for the imported connector(s) in case it was generated in different namespaces. - Solving the issue by swapping the destinationId with the id in actions array to be able to validate the actions further in the create rule method or for any interactions. ## Background about adding the `destinationId` In the Importing/Creation phase of the SavedObject, there is a conflict check `packages/core/saved-objects/core-saved-objects-import-export-server-internal/src/import/resolve_import_errors.ts` where one of the cases is when SO finds out that the new object(s) were exported from a different namespace, it generates new `destinationId` which will be treated as an id for manipulating the actions (ex. actionsClient.bulkGet()..) and any further interactions. example of the `successResult` that returned from the import operation incase of importing from different space ``` const successResults = [ { destinationId: '72cab9bb-535f-45dd-b9c2-5bc1bc0db96b', id: 'cabc78e0-9031-11ed-b076-53cc4d57aaf1', meta: { title: 'Connector: [anotherSpaceSlack]', icon: undefined }, type: 'action', }, ]; ``` ### 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: Maxim Palenov Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../api/rules/import_rules/route.ts | 7 +- .../import_rule_action_connectors.test.ts | 223 ++++++++++-- .../import_rule_action_connectors.ts | 13 +- .../logic/import/action_connectors/types.ts | 7 +- .../import/action_connectors/utils/index.ts | 45 ++- .../group10/import_rules.ts | 336 +++++++++++++----- 6 files changed, 514 insertions(+), 117 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts index ddcbf2cbdd6e4..c4490e418b859 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/api/rules/import_rules/route.ts @@ -135,6 +135,7 @@ export const importRulesRoute = ( success: actionConnectorSuccess, warnings: actionConnectorWarnings, errors: actionConnectorErrors, + rulesWithMigratedActions, } = await importRuleActionConnectors({ actionConnectors, actionsClient, @@ -142,9 +143,12 @@ export const importRulesRoute = ( rules: migratedParsedObjectsWithoutDuplicateErrors, overwrite: request.query.overwrite_action_connectors, }); + + // rulesWithMigratedActions: Is returened only in case connectors were exorted from different namesapce and the + // original rules actions' ids were replaced with new destinationIds const parsedRules = actionConnectorErrors.length ? [] - : migratedParsedObjectsWithoutDuplicateErrors; + : rulesWithMigratedActions || migratedParsedObjectsWithoutDuplicateErrors; // gather all exception lists that the imported rules reference const foundReferencedExceptionLists = await getReferencedExceptionLists({ @@ -166,7 +170,6 @@ export const importRulesRoute = ( existingLists: foundReferencedExceptionLists, allowMissingConnectorSecrets: !!actionConnectors.length, }); - const errorsResp = importRuleResponse.filter((resp) => isBulkError(resp)) as BulkError[]; const successes = importRuleResponse.filter((resp) => { if (isImportRegular(resp)) { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.test.ts index 455274006297e..2f81d1284eb53 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.test.ts @@ -36,7 +36,7 @@ const actionsClient = actionsClientMock.create(); actionsClient.getAll.mockResolvedValue([]); const core = coreMock.createRequestHandlerContext(); -describe('checkRuleExceptionReferences', () => { +describe('importRuleActionConnectors', () => { beforeEach(() => { jest.clearAllMocks(); }); @@ -55,7 +55,7 @@ describe('checkRuleExceptionReferences', () => { const res = await importRuleActionConnectors({ actionConnectors, actionsClient, - actionsImporter: actionsImporter2() as never, + actionsImporter: actionsImporter2(), rules, overwrite: false, }); @@ -82,7 +82,6 @@ describe('checkRuleExceptionReferences', () => { import: jest.fn().mockResolvedValue({ success: true, successCount: 1, - successResults: [], errors: [], warnings: [], }), @@ -92,7 +91,7 @@ describe('checkRuleExceptionReferences', () => { const res = await importRuleActionConnectors({ actionConnectors, actionsClient, - actionsImporter: actionsImporter() as never, + actionsImporter: actionsImporter(), rules, overwrite: false, }); @@ -100,7 +99,6 @@ describe('checkRuleExceptionReferences', () => { expect(res).toEqual({ success: true, successCount: 1, - successResults: [], errors: [], warnings: [], }); @@ -110,7 +108,6 @@ describe('checkRuleExceptionReferences', () => { import: jest.fn().mockResolvedValue({ success: true, successCount: 1, - successResults: [], errors: [], warnings: [], }), @@ -143,7 +140,7 @@ describe('checkRuleExceptionReferences', () => { const res = await importRuleActionConnectors({ actionConnectors, actionsClient, - actionsImporter: actionsImporter() as never, + actionsImporter: actionsImporter(), rules: ruleWith2Connectors, overwrite: false, }); @@ -151,7 +148,6 @@ describe('checkRuleExceptionReferences', () => { expect(res).toEqual({ success: true, successCount: 1, - successResults: [], errors: [], warnings: [], }); @@ -163,7 +159,7 @@ describe('checkRuleExceptionReferences', () => { const res = await importRuleActionConnectors({ actionConnectors: [], actionsClient, - actionsImporter: actionsImporter() as never, + actionsImporter: actionsImporter(), rules, overwrite: false, }); @@ -190,7 +186,7 @@ describe('checkRuleExceptionReferences', () => { const res = await importRuleActionConnectors({ actionConnectors: [], actionsClient, - actionsImporter: actionsImporter() as never, + actionsImporter: actionsImporter(), rules: [ { ...getImportRulesSchemaMock(), @@ -235,7 +231,7 @@ describe('checkRuleExceptionReferences', () => { const res = await importRuleActionConnectors({ actionConnectors: [], actionsClient, - actionsImporter: actionsImporter() as never, + actionsImporter: actionsImporter(), rules: [ { ...getImportRulesSchemaMock(), @@ -285,18 +281,17 @@ describe('checkRuleExceptionReferences', () => { import: jest.fn().mockResolvedValue({ success: true, successCount: 2, - successResults: [], errors: [], warnings: [], }), }); const actionsImporter2 = core.savedObjects.getImporter; - const actionsImporter2Import = actionsImporter2().import; + const actionsImporter2Importer = actionsImporter2(); const res = await importRuleActionConnectors({ actionConnectors, actionsClient, - actionsImporter: actionsImporter2Import as never, + actionsImporter: actionsImporter2Importer, rules: rulesWithoutActions, overwrite: false, }); @@ -307,7 +302,7 @@ describe('checkRuleExceptionReferences', () => { errors: [], warnings: [], }); - expect(actionsImporter2Import).not.toBeCalled(); + expect(actionsImporter2Importer.import).not.toBeCalled(); }); it('should skip importing the action-connectors if all connectors have been imported/created before', async () => { @@ -322,12 +317,12 @@ describe('checkRuleExceptionReferences', () => { }, ]); const actionsImporter2 = core.savedObjects.getImporter; - const actionsImporter2Import = actionsImporter2().import; + const actionsImporter2Importer = actionsImporter2(); const res = await importRuleActionConnectors({ actionConnectors, actionsClient, - actionsImporter: actionsImporter2Import as never, + actionsImporter: actionsImporter2Importer, rules, overwrite: false, }); @@ -338,7 +333,7 @@ describe('checkRuleExceptionReferences', () => { errors: [], warnings: [], }); - expect(actionsImporter2Import).not.toBeCalled(); + expect(actionsImporter2Importer.import).not.toBeCalled(); }); it('should not skip importing the action-connectors if all connectors have been imported/created before when overwrite is true', async () => { @@ -346,7 +341,6 @@ describe('checkRuleExceptionReferences', () => { import: jest.fn().mockResolvedValue({ success: true, successCount: 1, - successResults: [], errors: [], warnings: [], }), @@ -367,7 +361,7 @@ describe('checkRuleExceptionReferences', () => { const res = await importRuleActionConnectors({ actionConnectors, actionsClient, - actionsImporter: actionsImporter() as never, + actionsImporter: actionsImporter(), rules, overwrite: true, }); @@ -377,7 +371,194 @@ describe('checkRuleExceptionReferences', () => { successCount: 1, errors: [], warnings: [], - successResults: [], + }); + }); + + it('should import one rule with connector successfully even if it was exported from different namespaces by generating destinationId and replace the old actionId with it', async () => { + const successResults = [ + { + destinationId: '72cab9bb-535f-45dd-b9c2-5bc1bc0db96b', + id: 'cabc78e0-9031-11ed-b076-53cc4d57aaf1', + meta: { title: 'Connector: [anotherSpaceSlack]', icon: undefined }, + type: 'action', + }, + ]; + core.savedObjects.getImporter = jest.fn().mockReturnValueOnce({ + import: jest.fn().mockResolvedValue({ + success: true, + successCount: 1, + successResults, + errors: [], + warnings: [], + }), + }); + const actionsImporter = core.savedObjects.getImporter; + + actionsClient.getAll.mockResolvedValue([]); + + const res = await importRuleActionConnectors({ + actionConnectors, + actionsClient, + actionsImporter: actionsImporter(), + rules, + overwrite: false, + }); + const rulesWithMigratedActions = [ + { + actions: [ + { + action_type_id: '.webhook', + group: 'default', + id: '72cab9bb-535f-45dd-b9c2-5bc1bc0db96b', + params: {}, + }, + ], + description: 'some description', + language: 'kuery', + name: 'Query with a rule id', + query: 'user.name: root or user.name: admin', + risk_score: 55, + rule_id: 'rule-1', + severity: 'high', + type: 'query', + }, + ]; + + expect(res).toEqual({ + success: true, + successCount: 1, + errors: [], + warnings: [], + rulesWithMigratedActions, + }); + }); + + it('should import multiple rules with connectors successfully even if they were exported from different namespaces by generating destinationIds and replace the old actionIds with them', async () => { + const multipleRules = [ + { + ...getImportRulesSchemaMock(), + actions: [ + { + group: 'default', + id: 'cabc78e0-9031-11ed-b076-53cc4d57aaf1', + action_type_id: '.webhook', + params: {}, + }, + ], + }, + { + ...getImportRulesSchemaMock(), + rule_id: 'rule_2', + id: '0abc78e0-7031-11ed-b076-53cc4d57aaf1', + actions: [ + { + group: 'default', + id: '11abc78e0-9031-11ed-b076-53cc4d57aaw', + action_type_id: '.index', + params: {}, + }, + ], + }, + ]; + const successResults = [ + { + destinationId: '72cab9bb-535f-45dd-b9c2-5bc1bc0db96b', + id: 'cabc78e0-9031-11ed-b076-53cc4d57aaf1', + meta: { title: 'Connector: [anotherSpaceSlack]', icon: undefined }, + type: 'action', + }, + { + destinationId: '892cab9bb-535f-45dd-b9c2-5bc1bc0db96', + id: '11abc78e0-9031-11ed-b076-53cc4d57aaw', + meta: { title: 'Connector: [anotherSpaceSlack]', icon: undefined }, + type: 'action', + }, + ]; + core.savedObjects.getImporter = jest.fn().mockReturnValueOnce({ + import: jest.fn().mockResolvedValue({ + success: true, + successCount: 1, + successResults, + errors: [], + warnings: [], + }), + }); + const actionsImporter = core.savedObjects.getImporter; + const actionConnectorsWithIndex = [ + ...actionConnectors, + { + id: '0abc78e0-7031-11ed-b076-53cc4d57aaf1', + type: 'action', + updated_at: '2023-01-25T14:35:52.852Z', + created_at: '2023-01-25T14:35:52.852Z', + version: 'WzUxNTksMV0=', + attributes: { + actionTypeId: '.webhook', + name: 'webhook', + isMissingSecrets: false, + config: {}, + secrets: {}, + }, + references: [], + migrationVersion: { action: '8.3.0' }, + coreMigrationVersion: '8.7.0', + }, + ]; + actionsClient.getAll.mockResolvedValue([]); + + const res = await importRuleActionConnectors({ + actionConnectors: actionConnectorsWithIndex, + actionsClient, + actionsImporter: actionsImporter(), + rules: multipleRules, + overwrite: false, + }); + const rulesWithMigratedActions = [ + { + actions: [ + { + action_type_id: '.webhook', + group: 'default', + id: '72cab9bb-535f-45dd-b9c2-5bc1bc0db96b', + params: {}, + }, + ], + description: 'some description', + language: 'kuery', + name: 'Query with a rule id', + query: 'user.name: root or user.name: admin', + risk_score: 55, + rule_id: 'rule-1', + severity: 'high', + type: 'query', + }, + { + actions: [ + { + action_type_id: '.index', + group: 'default', + id: '892cab9bb-535f-45dd-b9c2-5bc1bc0db96', + params: {}, + }, + ], + description: 'some description', + language: 'kuery', + name: 'Query with a rule id', + id: '0abc78e0-7031-11ed-b076-53cc4d57aaf1', + rule_id: 'rule_2', + query: 'user.name: root or user.name: admin', + risk_score: 55, + severity: 'high', + type: 'query', + }, + ]; + + expect(res).toEqual({ + success: true, + successCount: 1, + errors: [], + warnings: [], + rulesWithMigratedActions, }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.ts index 3d2fc9fb7c6b6..dda1a28192eef 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/import_rule_action_connectors.ts @@ -9,6 +9,7 @@ import { Readable } from 'stream'; import type { SavedObjectsImportResponse } from '@kbn/core-saved-objects-common'; import type { SavedObject } from '@kbn/core-saved-objects-server'; +import type { RuleToImport } from '../../../../../../../common/detection_engine/rule_management'; import type { WarningSchema } from '../../../../../../../common/detection_engine/schemas/response'; import { checkIfActionsHaveMissingConnectors, @@ -17,6 +18,7 @@ import { handleActionsHaveNoConnectors, mapSOErrorToRuleError, returnErroredImportResult, + updateRuleActionsWithMigratedResults, } from './utils'; import type { ImportRuleActionConnectorsParams, ImportRuleActionConnectorsResult } from './types'; @@ -71,12 +73,21 @@ export const importRuleActionConnectors = async ({ overwrite, createNewCopies: false, }); + /* + // When a connector is exported from one namespace and imported to another, it does not result in an error, but instead a new object is created with + // new destination id and id will have the old origin id, so in order to be able to use the newly generated Connectors id, this util is used to swap the old id with the + // new destination Id + */ + let rulesWithMigratedActions: Array | undefined; + if (successResults?.some((res) => res.destinationId)) + rulesWithMigratedActions = updateRuleActionsWithMigratedResults(rules, successResults); + return { success, successCount, - successResults, errors: errors ? mapSOErrorToRuleError(errors) : [], warnings: (warnings as WarningSchema[]) || [], + rulesWithMigratedActions, }; } catch (error) { return returnErroredImportResult(error); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/types.ts index 8ba6c41c42dde..3d9471016a859 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/types.ts @@ -6,10 +6,7 @@ */ import type { ISavedObjectsImporter, SavedObject } from '@kbn/core-saved-objects-server'; import type { ActionsClient } from '@kbn/actions-plugin/server'; -import type { - SavedObjectsImportFailure, - SavedObjectsImportSuccess, -} from '@kbn/core-saved-objects-common'; +import type { SavedObjectsImportFailure } from '@kbn/core-saved-objects-common'; import type { RuleToImport } from '../../../../../../../common/detection_engine/rule_management'; import type { WarningSchema } from '../../../../../../../common/detection_engine/schemas/response'; import type { BulkError } from '../../../../routes/utils'; @@ -17,9 +14,9 @@ import type { BulkError } from '../../../../routes/utils'; export interface ImportRuleActionConnectorsResult { success: boolean; successCount: number; - successResults?: SavedObjectsImportSuccess[]; errors: BulkError[] | []; warnings: WarningSchema[] | []; + rulesWithMigratedActions?: Array; } export interface ImportRuleActionConnectorsParams { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/utils/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/utils/index.ts index 6d9b3b9da9e6d..caea8ad664f01 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/utils/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/import/action_connectors/utils/index.ts @@ -5,7 +5,10 @@ * 2.0. */ import { pick } from 'lodash'; -import type { SavedObjectsImportFailure } from '@kbn/core-saved-objects-common'; +import type { + SavedObjectsImportFailure, + SavedObjectsImportSuccess, +} from '@kbn/core-saved-objects-common'; import type { SavedObject } from '@kbn/core-saved-objects-server'; import type { ActionsClient } from '@kbn/actions-plugin/server'; import type { BulkError } from '../../../../../routes/utils'; @@ -127,3 +130,43 @@ export const checkIfActionsHaveMissingConnectors = ( } return null; }; + +export const mapActionIdToNewDestinationId = ( + connectorsImportResult: SavedObjectsImportSuccess[] +) => { + return connectorsImportResult.reduce( + (acc: { [actionId: string]: string }, { destinationId, id }) => { + acc[id] = destinationId || id; + return acc; + }, + {} + ); +}; + +export const swapNonDefaultSpaceIdWithDestinationId = ( + rule: RuleToImport, + actionIdDestinationIdLookup: { [actionId: string]: string } +) => { + return rule.actions?.map((action) => { + const destinationId = actionIdDestinationIdLookup[action.id]; + return { ...action, id: destinationId }; + }); +}; +/* +// When a connector is exported from one namespace and imported to another, it does not result in an error, but instead a new object is created with +// new destination id and id will have the old origin id, so in order to be able to use the newly generated Connectors id, this util is used to swap the old id with the +// new destination Id +*/ +export const updateRuleActionsWithMigratedResults = ( + rules: Array, + connectorsImportResult: SavedObjectsImportSuccess[] +): Array => { + const actionIdDestinationIdLookup = mapActionIdToNewDestinationId(connectorsImportResult); + return rules.map((rule) => { + if (rule instanceof Error) return rule; + return { + ...rule, + actions: swapNonDefaultSpaceIdWithDestinationId(rule, actionIdDestinationIdLookup), + }; + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_rules.ts index 41b49ac35bfc6..123e7bdbed2e5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/import_rules.ts @@ -93,6 +93,84 @@ const getImportRuleBuffer = (connectorId: string) => { const buffer = Buffer.from(`${rule1String}\n`); return buffer; }; +const getImportRuleWithConnectorsBuffer = (connectorId: string) => { + const rule1 = { + id: '53aad690-544e-11ec-a349-11361cc441c4', + updated_at: '2021-12-03T15:33:13.271Z', + updated_by: 'elastic', + created_at: '2021-12-03T15:33:13.271Z', + created_by: 'elastic', + name: '7.16 test with action', + tags: [], + interval: '5m', + enabled: true, + description: 'test', + risk_score: 21, + severity: 'low', + license: '', + output_index: '', + meta: { from: '1m', kibana_siem_app_url: 'http://0.0.0.0:5601/s/7/app/security' }, + author: [], + false_positives: [], + from: 'now-360s', + rule_id: 'aa525d7c-8948-439f-b32d-27e00c750246', + max_signals: 100, + risk_score_mapping: [], + severity_mapping: [], + threat: [], + to: 'now', + references: [], + version: 1, + exceptions_list: [], + immutable: false, + type: 'query', + language: 'kuery', + index: [ + 'apm-*-transaction*', + 'traces-apm*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', + ], + query: '*:*', + filters: [], + throttle: '1h', + actions: [ + { + group: 'default', + id: connectorId, + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + }, + action_type_id: '.slack', + }, + ], + }; + const connector = { + id: connectorId, + type: 'action', + updated_at: '2023-01-25T14:35:52.852Z', + created_at: '2023-01-25T14:35:52.852Z', + version: 'WzUxNTksMV0=', + attributes: { + actionTypeId: '.slack', + name: 'slack', + isMissingSecrets: false, + config: {}, + secrets: {}, + }, + references: [], + migrationVersion: { action: '8.3.0' }, + coreMigrationVersion: '8.7.0', + }; + const rule1String = JSON.stringify(rule1); + const connectorString = JSON.stringify(connector); + const buffer = Buffer.from(`${rule1String}\n${connectorString}`); + return buffer; +}; // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext): void => { @@ -1115,95 +1193,179 @@ export default ({ getService }: FtrProviderContext): void => { ); }); - it('importing a non-default-space 7.16 rule with a connector made in the non-default space should result in a 200', async () => { - const spaceId = '714-space'; - // connectorId is from the 7.x connector here - // x-pack/test/functional/es_archives/security_solution/import_rule_connector - const buffer = getImportRuleBuffer(space714ActionConnectorId); - - const { body } = await supertest - .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) - .set('kbn-xsrf', 'true') - .attach('file', buffer, 'rules.ndjson') - .expect(200); - expect(body.success).to.eql(true); - expect(body.success_count).to.eql(1); - expect(body.errors.length).to.eql(0); - }); - - // When objects become share-capable we will either add / update this test - it('importing a non-default-space 7.16 rule with a connector made in the non-default space into the default space should result in a 404', async () => { - // connectorId is from the 7.x connector here - // x-pack/test/functional/es_archives/security_solution/import_rule_connector - const buffer = getImportRuleBuffer(space714ActionConnectorId); - - const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_import`) - .set('kbn-xsrf', 'true') - .attach('file', buffer, 'rules.ndjson') - .expect(200); - expect(body.success).to.equal(false); - expect(body.errors[0].error.status_code).to.equal(404); - expect(body.errors[0].error.message).to.equal( - `1 connector is missing. Connector id missing is: ${space714ActionConnectorId}` - ); - }); - - // When objects become share-capable we will either add / update this test - it('importing a non-default-space 7.16 rule with a connector made in the non-default space into a different non-default space should result in a 404', async () => { - const spaceId = '4567-space'; - // connectorId is from the 7.x connector here - // x-pack/test/functional/es_archives/security_solution/import_rule_connector - // it - const buffer = getImportRuleBuffer(space714ActionConnectorId); - - const { body } = await supertest - .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) - .set('kbn-xsrf', 'true') - .attach('file', buffer, 'rules.ndjson') - .expect(200); - expect(body.success).to.equal(false); - expect(body.errors[0].error.status_code).to.equal(404); - expect(body.errors[0].error.message).to.equal( - `1 connector is missing. Connector id missing is: ${space714ActionConnectorId}` - ); - }); - - it('importing a default-space 7.16 rule with a connector made in the default space into the default space should result in a 200', async () => { - // connectorId is from the 7.x connector here - // x-pack/test/functional/es_archives/security_solution/import_rule_connector - // it - const buffer = getImportRuleBuffer(defaultSpaceActionConnectorId); + describe('should be imported into the non-default space', () => { + it('importing a non-default-space 7.16 rule with a connector made in the non-default space should result in a 200', async () => { + const spaceId = '714-space'; + // connectorId is from the 7.x connector here + // x-pack/test/functional/es_archives/security_solution/import_rule_connector + const buffer = getImportRuleBuffer(space714ActionConnectorId); + + const { body } = await supertest + .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + expect(body.success).to.eql(true); + expect(body.success_count).to.eql(1); + expect(body.errors.length).to.eql(0); + }); - const { body } = await supertest - .post(`${DETECTION_ENGINE_RULES_URL}/_import`) - .set('kbn-xsrf', 'true') - .attach('file', buffer, 'rules.ndjson') - .expect(200); - expect(body.success).to.equal(true); - expect(body.success_count).to.eql(1); - expect(body.errors.length).to.eql(0); + it('should import a non-default-space 7.16 rule with a connector made in the non-default space', async () => { + const spaceId = '714-space'; + const differentSpaceConnectorId = '5272d090-b111-11ed-b56a-a7991a8d8b32'; + + const buffer = getImportRuleWithConnectorsBuffer(differentSpaceConnectorId); + const { body } = await supertest + .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + + expect(body).to.eql({ + success: true, + success_count: 1, + rules_count: 1, + errors: [], + exceptions_errors: [], + exceptions_success: true, + exceptions_success_count: 0, + action_connectors_success: true, + action_connectors_success_count: 1, + action_connectors_warnings: [], + action_connectors_errors: [], + }); + }); + it('should import a non-default-space 7.16 rule with a connector made in the non-default space into the default space successfully', async () => { + // connectorId is from the 7.x connector here + // x-pack/test/functional/es_archives/security_solution/import_rule_connector + const differentSpaceConnectorId = '963ec960-a21a-11ed-84a4-a33e4c2558c9'; + const buffer = getImportRuleWithConnectorsBuffer(differentSpaceConnectorId); + + const { body } = await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + expect(body).to.eql({ + success: true, + success_count: 1, + rules_count: 1, + errors: [], + exceptions_errors: [], + exceptions_success: true, + exceptions_success_count: 0, + action_connectors_success: true, + action_connectors_success_count: 1, + action_connectors_warnings: [], + action_connectors_errors: [], + }); + }); + it('importing a non-default-space 7.16 rule with a connector made in the non-default space into the default space should result in a 404 if the file does not contain connectors', async () => { + // connectorId is from the 7.x connector here + // x-pack/test/functional/es_archives/security_solution/import_rule_connector + const buffer = getImportRuleBuffer(space714ActionConnectorId); + + const { body } = await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + expect(body.success).to.equal(false); + expect(body.errors[0].error.status_code).to.equal(404); + expect(body.errors[0].error.message).to.equal( + `1 connector is missing. Connector id missing is: ${space714ActionConnectorId}` + ); + }); + // When objects become share-capable we will either add / update this test + it('importing a non-default-space 7.16 rule with a connector made in the non-default space into a different non-default space should result in a 404', async () => { + const spaceId = '4567-space'; + // connectorId is from the 7.x connector here + // x-pack/test/functional/es_archives/security_solution/import_rule_connector + // it + const buffer = getImportRuleBuffer(space714ActionConnectorId); + + const { body } = await supertest + .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + expect(body.success).to.equal(false); + expect(body.errors[0].error.status_code).to.equal(404); + expect(body.errors[0].error.message).to.equal( + `1 connector is missing. Connector id missing is: ${space714ActionConnectorId}` + ); + }); }); - it('importing a default-space 7.16 rule with a connector made in the default space into a non-default space should result in a 404', async () => { - await esArchiver.load( - 'x-pack/test/functional/es_archives/security_solution/import_rule_connector' - ); - const spaceId = '4567-space'; - // connectorId is from the 7.x connector here - // x-pack/test/functional/es_archives/security_solution/import_rule_connector - // it - const buffer = getImportRuleBuffer(defaultSpaceActionConnectorId); - - const { body } = await supertest - .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) - .set('kbn-xsrf', 'true') - .attach('file', buffer, 'rules.ndjson') - .expect(200); - expect(body.success).to.equal(false); - expect(body.errors[0].error.status_code).to.equal(404); - expect(body.errors[0].error.message).to.equal( - `1 connector is missing. Connector id missing is: ${defaultSpaceActionConnectorId}` - ); + describe('should be imported into the default space', () => { + it('should import a default-space 7.16 rule with a connector made in the default space into a non-default space successfully', async () => { + await esArchiver.load( + 'x-pack/test/functional/es_archives/security_solution/import_rule_connector' + ); + const defaultSpaceConnectorId = '8fbf6d10-a21a-11ed-84a4-a33e4c2558c9'; + + const spaceId = '4567-space'; + // connectorId is from the 7.x connector here + // x-pack/test/functional/es_archives/security_solution/import_rule_connector + // it + const buffer = getImportRuleWithConnectorsBuffer(defaultSpaceConnectorId); + + const { body } = await supertest + .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + expect(body).to.eql({ + success: true, + success_count: 1, + rules_count: 1, + errors: [], + exceptions_errors: [], + exceptions_success: true, + exceptions_success_count: 0, + action_connectors_success: true, + action_connectors_success_count: 1, + action_connectors_warnings: [], + action_connectors_errors: [], + }); + }); + // When objects become share-capable we will either add / update this test + + it('importing a default-space 7.16 rule with a connector made in the default space into the default space should result in a 200', async () => { + // connectorId is from the 7.x connector here + // x-pack/test/functional/es_archives/security_solution/import_rule_connector + // it + const buffer = getImportRuleBuffer(defaultSpaceActionConnectorId); + + const { body } = await supertest + .post(`${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + expect(body.success).to.equal(true); + expect(body.success_count).to.eql(1); + expect(body.errors.length).to.eql(0); + }); + it('importing a default-space 7.16 rule with a connector made in the default space into a non-default space should result in a 404', async () => { + await esArchiver.load( + 'x-pack/test/functional/es_archives/security_solution/import_rule_connector' + ); + const spaceId = '4567-space'; + // connectorId is from the 7.x connector here + // x-pack/test/functional/es_archives/security_solution/import_rule_connector + // it + const buffer = getImportRuleBuffer(defaultSpaceActionConnectorId); + + const { body } = await supertest + .post(`/s/${spaceId}${DETECTION_ENGINE_RULES_URL}/_import`) + .set('kbn-xsrf', 'true') + .attach('file', buffer, 'rules.ndjson') + .expect(200); + expect(body.success).to.equal(false); + expect(body.errors[0].error.status_code).to.equal(404); + expect(body.errors[0].error.message).to.equal( + `1 connector is missing. Connector id missing is: ${defaultSpaceActionConnectorId}` + ); + }); }); }); From ee56d954dae7d5babd339b40b0103d6a1402e503 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 28 Feb 2023 10:00:24 +0000 Subject: [PATCH 037/131] [Fleet] Make spaces plugin optional (#152115) ## Summary Closes #151897 The spaces service will be disabled in serverless. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/fleet/kibana.jsonc | 4 ++-- x-pack/plugins/fleet/server/plugin.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/fleet/kibana.jsonc b/x-pack/plugins/fleet/kibana.jsonc index bf9db5435be82..4a8076fd09836 100644 --- a/x-pack/plugins/fleet/kibana.jsonc +++ b/x-pack/plugins/fleet/kibana.jsonc @@ -17,7 +17,6 @@ "navigation", "customIntegrations", "share", - "spaces", "security", "unifiedSearch", "savedObjectsTagging", @@ -33,7 +32,8 @@ "globalSearch", "telemetry", "discover", - "ingestPipelines" + "ingestPipelines", + "spaces", ], "requiredBundles": [ "kibanaReact", diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 265431a87e265..4e9a7f19b1818 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -8,7 +8,7 @@ import type { Observable } from 'rxjs'; import { BehaviorSubject } from 'rxjs'; import { take, filter } from 'rxjs/operators'; - +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import { i18n } from '@kbn/i18n'; import type { CoreSetup, @@ -118,7 +118,7 @@ export interface FleetSetupDeps { encryptedSavedObjects: EncryptedSavedObjectsPluginSetup; cloud?: CloudSetup; usageCollection?: UsageCollectionSetup; - spaces: SpacesPluginStart; + spaces?: SpacesPluginStart; telemetry?: TelemetryPluginSetup; taskManager: TaskManagerSetupContract; } @@ -386,7 +386,7 @@ export class FleetPlugin return getInternalSoClient(); }, get spaceId() { - return deps.spaces.spacesService.getSpaceId(request); + return deps.spaces?.spacesService?.getSpaceId(request) ?? DEFAULT_SPACE_ID; }, get limitedToPackages() { From f688b37c89ad9359e989156859f5bac76425ff52 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 28 Feb 2023 05:02:12 -0500 Subject: [PATCH 038/131] [Synthetics] Improve test duration formatting (#152151) Co-authored-by: Shahzad --- .../test_time_formats.test.ts | 36 +++++++++++++++++++ .../monitor_test_result/test_time_formats.ts | 4 +-- 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts new file mode 100644 index 0000000000000..5337468f6e730 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { formatTestDuration } from './test_time_formats'; + +describe('formatTestDuration', () => { + it.each` + duration | expected | isMilli + ${undefined} | ${'0 ms'} | ${undefined} + ${120_000_000} | ${'2 min'} | ${undefined} + ${6_200_000} | ${'6.2 s'} | ${false} + ${500_000} | ${'500 ms'} | ${undefined} + ${100} | ${'0 ms'} | ${undefined} + ${undefined} | ${'0 ms'} | ${true} + ${600_000} | ${'10 min'} | ${true} + ${6_200} | ${'6.2 s'} | ${true} + ${500} | ${'500 ms'} | ${true} + `( + 'returns $expected when `duration` is $duration and `isMilli` $isMilli', + ({ + duration, + expected, + isMilli, + }: { + duration?: number; + expected: string; + isMilli?: boolean; + }) => { + expect(formatTestDuration(duration, isMilli)).toBe(expected); + } + ); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts index fcf07f1cf8714..5d605ad4c2192 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts @@ -17,11 +17,11 @@ export const formatTestDuration = (duration = 0, isMilli = false) => { const secs = isMilli ? duration / 1e3 : duration / 1e6; if (secs >= 60) { - return `${(secs / 60).toFixed(1)} min`; + return `${parseFloat((secs / 60).toFixed(1))} min`; } if (secs >= 1) { - return `${secs.toFixed(1)} s`; + return `${parseFloat(secs.toFixed(1))} s`; } if (isMilli) { From 09902b1055130f52ae833022633beda130d97e08 Mon Sep 17 00:00:00 2001 From: Katerina Patticha Date: Tue, 28 Feb 2023 11:10:20 +0100 Subject: [PATCH 039/131] [APM] Limit cypress recording only when `apm:cypress-record` label is applied to the PR (#152099) Part of https://github.com/elastic/kibana/issues/150682 run cypress recording PRs that have the label `apm:cypress-record` any ideas about the label/naming are welcome :D --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .buildkite/scripts/steps/functional/apm_cypress.sh | 4 ++-- x-pack/plugins/apm/dev_docs/testing.md | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.buildkite/scripts/steps/functional/apm_cypress.sh b/.buildkite/scripts/steps/functional/apm_cypress.sh index ff14df87377cd..987d9de577c8b 100755 --- a/.buildkite/scripts/steps/functional/apm_cypress.sh +++ b/.buildkite/scripts/steps/functional/apm_cypress.sh @@ -12,8 +12,8 @@ APM_CYPRESS_RECORD_KEY="$(retry 5 5 vault read -field=CYPRESS_RECORD_KEY secret/ export JOB=kibana-apm-cypress IS_FLAKY_TEST_RUNNER=${CLI_COUNT:-0} -# Disable parallel tests and dashboard recording when running them in the flaky test runner -if [[ "$IS_FLAKY_TEST_RUNNER" -ne 1 ]]; then +#Enabling cypress dashboard recording when PR is labeled with `apm:cypress-record` and we are not using the flaky test runner +if [[ "$IS_FLAKY_TEST_RUNNER" -ne 1 ]] && is_pr_with_label "apm:cypress-record"; then CYPRESS_ARGS="--record --key "$APM_CYPRESS_RECORD_KEY" --parallel --ci-build-id "${BUILDKITE_BUILD_ID}"" else CYPRESS_ARGS="" diff --git a/x-pack/plugins/apm/dev_docs/testing.md b/x-pack/plugins/apm/dev_docs/testing.md index d6fc05f286d5a..1fa7ac8774b08 100644 --- a/x-pack/plugins/apm/dev_docs/testing.md +++ b/x-pack/plugins/apm/dev_docs/testing.md @@ -72,7 +72,9 @@ node x-pack/plugins/apm/scripts/test/api --runner --basic --updateSnapshots The E2E tests are located in [`x-pack/plugins/apm/ftr_e2e`](../ftr_e2e). -Test runs are recorded to the [Cypress Dashboard](https://dashboard.cypress.io). Tests run on buildkite PR pipeline are parallelized (4 parallel jobs) and are orchestrated by the Cypress dashboard service. It can be configured in [.buildkite/pipelines/pull_request/apm_cypress.yml](https://github.com/elastic/kibana/blob/main/.buildkite/pipelines/pull_request/apm_cypress.yml) with the property `parallelism`. +When PR is labeled with `apm:cypress-record`, test runs are recorded to the [Cypress Dashboard](https://dashboard.cypress.io). + +Tests run on buildkite PR pipeline are parallelized (4 parallel jobs) and are orchestrated by the Cypress dashboard service. It can be configured in [.buildkite/pipelines/pull_request/apm_cypress.yml](https://github.com/elastic/kibana/blob/main/.buildkite/pipelines/pull_request/apm_cypress.yml) with the property `parallelism`. ```yml ... From d6a57aae9ff64c90ee0989e525d0599a8e2f03c3 Mon Sep 17 00:00:00 2001 From: Maryam Saeidi Date: Tue, 28 Feb 2023 11:27:57 +0100 Subject: [PATCH 040/131] [AO] Fix refresh every in the alert search bar (#152246) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #150903 ## 📝 Summary This PR fixes the `refresh every` feature in the alert search bar. ### 🧪 How to test - Check Alert search bar on the following pages, refresh every should work correctly now - Alerts page - Rule details page --- .../shared/alert_search_bar/alert_search_bar.tsx | 4 ++-- .../sections/alerts_search_bar/alerts_search_bar.tsx | 12 +++++++++--- .../application/sections/alerts_search_bar/types.ts | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/observability/public/components/shared/alert_search_bar/alert_search_bar.tsx b/x-pack/plugins/observability/public/components/shared/alert_search_bar/alert_search_bar.tsx index 4d154504ce6ea..aec17127b8dd9 100644 --- a/x-pack/plugins/observability/public/components/shared/alert_search_bar/alert_search_bar.tsx +++ b/x-pack/plugins/observability/public/components/shared/alert_search_bar/alert_search_bar.tsx @@ -62,7 +62,7 @@ export function ObservabilityAlertSearchBar({ const onSearchBarParamsChange = useCallback< (query: { dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' }; - query: string; + query?: string; }) => void >( ({ dateRange, query }) => { @@ -76,7 +76,7 @@ export function ObservabilityAlertSearchBar({ query, [...getAlertStatusQuery(status), ...defaultSearchQueries] ); - onKueryChange(query); + if (query) onKueryChange(query); timeFilterService.setTime(dateRange); onRangeFromChange(dateRange.from); onRangeToChange(dateRange.to); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx index 193d6abf1433b..6a170363d34a8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/alerts_search_bar.tsx @@ -7,6 +7,7 @@ import React, { useCallback, useState } from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { Query, TimeRange } from '@kbn/es-query'; import { NO_INDEX_PATTERNS } from './constants'; import { SEARCH_BAR_PLACEHOLDER } from './translations'; import { AlertsSearchBarProps, QueryLanguageType } from './types'; @@ -32,16 +33,20 @@ export function AlertsSearchBar({ const { value: dataView, loading, error } = useAlertDataView(featureIds); const onQuerySubmit = useCallback( - (payload) => { - const { dateRange, query: nextQuery } = payload; + ({ dateRange, query: nextQuery }: { dateRange: TimeRange; query?: Query }) => { onQueryChange({ dateRange, - query: typeof nextQuery?.query === 'string' ? nextQuery.query : '', + query: typeof nextQuery?.query === 'string' ? nextQuery.query : undefined, }); setQueryLanguage((nextQuery?.language ?? 'kuery') as QueryLanguageType); }, [onQueryChange, setQueryLanguage] ); + const onRefresh = ({ dateRange }: { dateRange: TimeRange }) => { + onQueryChange({ + dateRange, + }); + }; return ( ); } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts index e75dd56168687..2c94c250c168a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_search_bar/types.ts @@ -17,6 +17,6 @@ export interface AlertsSearchBarProps { query?: string; onQueryChange: (query: { dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' }; - query: string; + query?: string; }) => void; } From 6f1565f6b44d5a0abb9afd8d39a205e4b6c01814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Kopyci=C5=84ski?= Date: Tue, 28 Feb 2023 13:33:56 +0100 Subject: [PATCH 041/131] [Cases] Unify SavedObjectFinderUi component (#151491) --- .../public/finder/saved_object_finder.tsx | 193 +++--- .../markdown_editor/plugins/lens/plugin.tsx | 7 +- .../plugins/lens/saved_objects_finder.tsx | 555 ------------------ .../translations/translations/fr-FR.json | 6 - .../translations/translations/ja-JP.json | 6 - .../translations/translations/zh-CN.json | 6 - 6 files changed, 108 insertions(+), 665 deletions(-) delete mode 100644 x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx diff --git a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx index 4c39d02dd55f2..14fc712002abd 100644 --- a/src/plugins/saved_objects/public/finder/saved_object_finder.tsx +++ b/src/plugins/saved_objects/public/finder/saved_object_finder.tsx @@ -27,6 +27,9 @@ import { EuiSpacer, EuiTablePagination, IconType, + EuiFormRow, + EuiFieldSearchProps, + EuiFormRowProps, } from '@elastic/eui'; import { Direction } from '@elastic/eui/src/services/sort/sort_direction'; import { i18n } from '@kbn/i18n'; @@ -80,6 +83,8 @@ interface BaseSavedObjectFinder { noItemsMessage?: React.ReactNode; savedObjectMetaData: Array>; showFilter?: boolean; + euiFormRowProps?: Partial; + euiFieldSearchProps?: EuiFieldSearchProps; } interface SavedObjectFinderFixedPage extends BaseSavedObjectFinder { @@ -110,6 +115,13 @@ class SavedObjectFinderUi extends React.Component< initialPageSize: PropTypes.oneOf([5, 10, 15, 25]), fixedPageSize: PropTypes.number, showFilter: PropTypes.bool, + euiFormRowProps: PropTypes.object, + euiFieldSearchProps: PropTypes.object, + }; + + static defaultProps = { + euiFormRowProps: {}, + euiFieldSearchProps: {}, }; private isComponentMounted: boolean = false; @@ -336,109 +348,114 @@ class SavedObjectFinderUi extends React.Component< const availableSavedObjectMetaData = this.getAvailableSavedObjectMetaData(); return ( - - - { - this.setState( - { - query: e.target.value, - }, - this.fetchItems - ); - }} - data-test-subj="savedObjectFinderSearchInput" - isLoading={this.state.isFetchingItems} - /> - - - - this.setState({ sortOpen: false })} - button={ - - this.setState(({ sortOpen }) => ({ - sortOpen: !sortOpen, - })) - } - iconType="arrowDown" - isSelected={this.state.sortOpen} - data-test-subj="savedObjectFinderSortButton" - > - {i18n.translate('savedObjects.finder.sortButtonLabel', { - defaultMessage: 'Sort', - })} - - } - > - - - {this.props.showFilter && ( + + + + { + this.setState( + { + query: e.target.value, + }, + this.fetchItems + ); + }} + data-test-subj="savedObjectFinderSearchInput" + isLoading={this.state.isFetchingItems} + {...this.props.euiFieldSearchProps} + /> + + + this.setState({ filterOpen: false })} + isOpen={this.state.sortOpen} + closePopover={() => this.setState({ sortOpen: false })} button={ - this.setState(({ filterOpen }) => ({ - filterOpen: !filterOpen, + this.setState(({ sortOpen }) => ({ + sortOpen: !sortOpen, })) } iconType="arrowDown" - data-test-subj="savedObjectFinderFilterButton" - isSelected={this.state.filterOpen} - numFilters={this.props.savedObjectMetaData.length} - hasActiveFilters={this.state.filteredTypes.length > 0} - numActiveFilters={this.state.filteredTypes.length} + isSelected={this.state.sortOpen} + data-test-subj="savedObjectFinderSortButton" > - {i18n.translate('savedObjects.finder.filterButtonLabel', { - defaultMessage: 'Types', + {i18n.translate('savedObjects.finder.sortButtonLabel', { + defaultMessage: 'Sort', })} } > - ( - { - this.setState(({ filteredTypes }) => ({ - filteredTypes: filteredTypes.includes(metaData.type) - ? filteredTypes.filter((t) => t !== metaData.type) - : [...filteredTypes, metaData.type], - page: 0, - })); - }} - > - {metaData.name} - - ))} - /> + - )} - - - {this.props.children ? {this.props.children} : null} - + {this.props.showFilter && ( + this.setState({ filterOpen: false })} + button={ + + this.setState(({ filterOpen }) => ({ + filterOpen: !filterOpen, + })) + } + iconType="arrowDown" + data-test-subj="savedObjectFinderFilterButton" + isSelected={this.state.filterOpen} + numFilters={this.props.savedObjectMetaData.length} + hasActiveFilters={this.state.filteredTypes.length > 0} + numActiveFilters={this.state.filteredTypes.length} + > + {i18n.translate('savedObjects.finder.filterButtonLabel', { + defaultMessage: 'Types', + })} + + } + > + ( + { + this.setState(({ filteredTypes }) => ({ + filteredTypes: filteredTypes.includes(metaData.type) + ? filteredTypes.filter((t) => t !== metaData.type) + : [...filteredTypes, metaData.type], + page: 0, + })); + }} + > + {metaData.name} + + ))} + /> + + )} + + + {this.props.children ? ( + {this.props.children} + ) : null} + + ); } diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx index 71750bbc2a515..ae88e17637627 100644 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx +++ b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx @@ -28,11 +28,11 @@ import styled from 'styled-components'; import type { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import type { EmbeddablePackageState } from '@kbn/embeddable-plugin/public'; +import { SavedObjectFinderUi } from '@kbn/saved-objects-plugin/public'; import { useKibana } from '../../../../common/lib/kibana'; import { DRAFT_COMMENT_STORAGE_ID, ID } from './constants'; import { CommentEditorContext } from '../../context'; import { ModalContainer } from './modal_container'; -import { SavedObjectFinderUi } from './saved_objects_finder'; import { useLensDraftComment } from './use_lens_draft_comment'; import { VISUALIZATION } from './translations'; import { useIsMainApplication } from '../../../../common/hooks'; @@ -72,7 +72,7 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({ embeddable, lens, storage, - savedObjects, + http, uiSettings, data: { query: { @@ -362,9 +362,8 @@ const LensEditorComponent: LensEuiMarkdownEditorUiPlugin['editor'] = ({ savedObjectMetaData={savedObjectMetaData} fixedPageSize={10} uiSettings={uiSettings} - savedObjects={savedObjects} + http={http} euiFieldSearchProps={euiFieldSearchProps} - // @ts-expect-error update types euiFormRowProps={euiFormRowProps} /> diff --git a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx b/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx deleted file mode 100644 index 5b96ea377fc74..0000000000000 --- a/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx +++ /dev/null @@ -1,555 +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. - */ - -// TODO: merge with src/plugins/saved_objects/public/finder/saved_object_finder.tsx - -import { debounce } from 'lodash'; -import PropTypes from 'prop-types'; -import React from 'react'; - -import type { EuiFieldSearchProps, IconType, EuiFormRowProps } from '@elastic/eui'; -import { - EuiContextMenuItem, - EuiContextMenuPanel, - EuiEmptyPrompt, - EuiFieldSearch, - EuiFilterButton, - EuiFilterGroup, - EuiFlexGroup, - EuiFlexItem, - EuiListGroup, - EuiListGroupItem, - EuiLoadingSpinner, - EuiPagination, - EuiPopover, - EuiSpacer, - EuiTablePagination, - EuiFormRow, -} from '@elastic/eui'; -import type { Direction } from '@elastic/eui/src/services/sort/sort_direction'; -import { i18n } from '@kbn/i18n'; - -import type { SimpleSavedObject, CoreStart } from '@kbn/core/public'; - -import { LISTING_LIMIT_SETTING } from '@kbn/saved-objects-plugin/public'; - -export interface SavedObjectMetaData { - type: string; - name: string; - getIconForSavedObject(savedObject: SimpleSavedObject): IconType; - getTooltipForSavedObject?(savedObject: SimpleSavedObject): string; - showSavedObject?(savedObject: SimpleSavedObject): boolean; - getSavedObjectSubType?(savedObject: SimpleSavedObject): string; - includeFields?: string[]; -} - -interface FinderAttributes { - title?: string; - name?: string; - type: string; -} - -interface SavedObjectFinderState { - items: Array<{ - title: string | null; - name: string | null; - id: SimpleSavedObject['id']; - type: SimpleSavedObject['type']; - savedObject: SimpleSavedObject; - }>; - query: string; - isFetchingItems: boolean; - page: number; - perPage: number; - sortDirection?: Direction; - sortOpen: boolean; - filterOpen: boolean; - filteredTypes: string[]; -} - -interface BaseSavedObjectFinder { - onChoose?: ( - id: SimpleSavedObject['id'], - type: SimpleSavedObject['type'], - name: string, - savedObject: SimpleSavedObject - ) => void; - noItemsMessage?: React.ReactNode; - savedObjectMetaData: Array>; - showFilter?: boolean; - euiFormRowProps?: EuiFormRowProps; - euiFieldSearchProps?: EuiFieldSearchProps; -} - -interface SavedObjectFinderFixedPage extends BaseSavedObjectFinder { - initialPageSize?: undefined; - fixedPageSize: number; -} - -interface SavedObjectFinderInitialPageSize extends BaseSavedObjectFinder { - initialPageSize?: 5 | 10 | 15 | 25; - fixedPageSize?: undefined; -} - -export type SavedObjectFinderProps = SavedObjectFinderFixedPage | SavedObjectFinderInitialPageSize; - -export type SavedObjectFinderUiProps = { - savedObjects: CoreStart['savedObjects']; - uiSettings: CoreStart['uiSettings']; -} & SavedObjectFinderProps; - -// TODO: Fix this manually. Issue #123375 -// eslint-disable-next-line react/display-name -export class SavedObjectFinderUi extends React.Component< - SavedObjectFinderUiProps, - SavedObjectFinderState -> { - public static propTypes = { - onChoose: PropTypes.func, - noItemsMessage: PropTypes.node, - savedObjectMetaData: PropTypes.array.isRequired, - initialPageSize: PropTypes.oneOf([5, 10, 15, 25]), - fixedPageSize: PropTypes.number, - showFilter: PropTypes.bool, - euiFormRowProps: PropTypes.object, - euiFieldSearchProps: PropTypes.object, - }; - - private isComponentMounted: boolean = false; - - private debouncedFetch = debounce(async (query: string) => { - const metaDataMap = this.getSavedObjectMetaDataMap(); - - const fields = Object.values(metaDataMap) - .map((metaData) => metaData.includeFields || []) - .reduce((allFields, currentFields) => allFields.concat(currentFields), ['title', 'name']); - - const perPage = this.props.uiSettings.get(LISTING_LIMIT_SETTING); - const resp = await this.props.savedObjects.client.find({ - type: Object.keys(metaDataMap), - fields: [...new Set(fields)], - search: query ? `${query}*` : undefined, - page: 1, - perPage, - searchFields: ['title^3', 'description'], - defaultSearchOperator: 'AND', - }); - - resp.savedObjects = resp.savedObjects.filter((savedObject) => { - const metaData = metaDataMap[savedObject.type]; - if (metaData.showSavedObject) { - return metaData.showSavedObject(savedObject); - } else { - return true; - } - }); - - if (!this.isComponentMounted) { - return; - } - - // We need this check to handle the case where search results come back in a different - // order than they were sent out. Only load results for the most recent search. - if (query === this.state.query) { - this.setState({ - isFetchingItems: false, - page: 0, - items: resp.savedObjects.map((savedObject) => { - const { - attributes: { name, title }, - id, - type, - } = savedObject; - const titleToUse = typeof title === 'string' ? title : ''; - const nameToUse = name && typeof name === 'string' ? name : titleToUse; - return { - title: titleToUse, - name: nameToUse, - id, - type, - savedObject, - }; - }), - }); - } - }, 300); - - constructor(props: SavedObjectFinderUiProps) { - super(props); - - this.state = { - items: [], - isFetchingItems: false, - page: 0, - perPage: props.initialPageSize || props.fixedPageSize || 10, - query: '', - filterOpen: false, - filteredTypes: [], - sortOpen: false, - }; - } - - public componentWillUnmount() { - this.isComponentMounted = false; - this.debouncedFetch.cancel(); - } - - public componentDidMount() { - this.isComponentMounted = true; - this.fetchItems(); - } - - public render() { - return ( - <> - {this.renderSearchBar()} - {this.renderListing()} - - ); - } - - private getSavedObjectMetaDataMap(): Record { - return this.props.savedObjectMetaData.reduce( - (map, metaData) => ({ ...map, [metaData.type]: metaData }), - {} - ); - } - - private getPageCount() { - return Math.ceil( - (this.state.filteredTypes.length === 0 - ? this.state.items.length - : this.state.items.filter( - (item) => - this.state.filteredTypes.length === 0 || this.state.filteredTypes.includes(item.type) - ).length) / this.state.perPage - ); - } - - // server-side paging not supported - // 1) saved object client does not support sorting by title because title is only mapped as analyzed - // 2) can not search on anything other than title because all other fields are stored in opaque JSON strings, - // for example, visualizations need to be search by isLab but this is not possible in Elasticsearch side - // with the current mappings - private getPageOfItems = () => { - // do not sort original list to preserve elasticsearch ranking order - const items = this.state.items.slice(); - const { sortDirection } = this.state; - - if (sortDirection || !this.state.query) { - items.sort(({ title: titleA }, { title: titleB }) => { - let order = 1; - if (sortDirection === 'desc') { - order = -1; - } - return order * (titleA || '').toLowerCase().localeCompare((titleB || '').toLowerCase()); - }); - } - - // If begin is greater than the length of the sequence, an empty array is returned. - const startIndex = this.state.page * this.state.perPage; - // If end is greater than the length of the sequence, slice extracts through to the end of the sequence (arr.length). - const lastIndex = startIndex + this.state.perPage; - return items - .filter( - (item) => - this.state.filteredTypes.length === 0 || this.state.filteredTypes.includes(item.type) - ) - .slice(startIndex, lastIndex); - }; - - private fetchItems = () => { - this.setState( - { - isFetchingItems: true, - }, - this.debouncedFetch.bind(null, this.state.query) - ); - }; - - private getAvailableSavedObjectMetaData() { - const typesInItems = new Set(); - this.state.items.forEach((item) => { - typesInItems.add(item.type); - }); - return this.props.savedObjectMetaData.filter((metaData) => typesInItems.has(metaData.type)); - } - - private getSortOptions() { - const sortOptions = [ - { - this.setState({ - sortDirection: 'asc', - }); - }} - > - {i18n.translate('xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAsc', { - defaultMessage: 'Ascending', - })} - , - { - this.setState({ - sortDirection: 'desc', - }); - }} - > - {i18n.translate('xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortDesc', { - defaultMessage: 'Descending', - })} - , - ]; - if (this.state.query) { - sortOptions.push( - { - this.setState({ - sortDirection: undefined, - }); - }} - > - {i18n.translate('xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAuto', { - defaultMessage: 'Best match', - })} - - ); - } - return sortOptions; - } - - private renderSearchBar() { - const availableSavedObjectMetaData = this.getAvailableSavedObjectMetaData(); - - return ( - - - - { - this.setState( - { - query: e.target.value, - }, - this.fetchItems - ); - }} - data-test-subj="savedObjectFinderSearchInput" - isLoading={this.state.isFetchingItems} - {...(this.props.euiFieldSearchProps || {})} - /> - - - - this.setState({ sortOpen: false })} - button={ - - this.setState(({ sortOpen }) => ({ - sortOpen: !sortOpen, - })) - } - iconType="arrowDown" - isSelected={this.state.sortOpen} - data-test-subj="savedObjectFinderSortButton" - > - {i18n.translate( - 'xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortButtonLabel', - { - defaultMessage: 'Sort', - } - )} - - } - > - - - {this.props.showFilter && ( - this.setState({ filterOpen: false })} - button={ - - this.setState(({ filterOpen }) => ({ - filterOpen: !filterOpen, - })) - } - iconType="arrowDown" - data-test-subj="savedObjectFinderFilterButton" - isSelected={this.state.filterOpen} - numFilters={this.props.savedObjectMetaData.length} - hasActiveFilters={this.state.filteredTypes.length > 0} - numActiveFilters={this.state.filteredTypes.length} - > - {i18n.translate( - 'xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.filterButtonLabel', - { - defaultMessage: 'Types', - } - )} - - } - > - ( - { - this.setState(({ filteredTypes }) => ({ - filteredTypes: filteredTypes.includes(metaData.type) - ? filteredTypes.filter((t) => t !== metaData.type) - : [...filteredTypes, metaData.type], - page: 0, - })); - }} - > - {metaData.name} - - ))} - /> - - )} - - - {this.props.children ? ( - {this.props.children} - ) : null} - - - ); - } - - private renderListing() { - const items = this.state.items.length === 0 ? [] : this.getPageOfItems(); - const { onChoose, savedObjectMetaData } = this.props; - - return ( - <> - {this.state.isFetchingItems && this.state.items.length === 0 && ( - - - - - - - )} - {items.length > 0 ? ( - <> - - - {items.map((item) => { - const currentSavedObjectMetaData = savedObjectMetaData.find( - (metaData) => metaData.type === item.type - ); - - if (currentSavedObjectMetaData == null) { - return null; - } - - const fullName = currentSavedObjectMetaData.getTooltipForSavedObject - ? currentSavedObjectMetaData.getTooltipForSavedObject(item.savedObject) - : `${item.name} (${currentSavedObjectMetaData.name})`; - - const iconType = ( - currentSavedObjectMetaData || - ({ - getIconForSavedObject: () => 'document', - } as Pick, 'getIconForSavedObject'>) - ).getIconForSavedObject(item.savedObject); - - return ( - { - onChoose(item.id, item.type, fullName, item.savedObject); - } - : undefined - } - title={fullName} - data-test-subj={`savedObjectTitle${(item.title || '').split(' ').join('-')}`} - /> - ); - })} - - - ) : ( - !this.state.isFetchingItems && - )} - {this.getPageCount() > 1 && - (this.props.fixedPageSize ? ( - { - this.setState({ - page, - }); - }} - /> - ) : ( - { - this.setState({ - page, - }); - }} - onChangeItemsPerPage={(perPage) => { - this.setState({ - perPage, - }); - }} - itemsPerPage={this.state.perPage} - itemsPerPageOptions={[5, 10, 15, 25]} - /> - ))} - - ); - } -} diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 7464ed2fbb4fe..516eef2d0157e 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -9642,15 +9642,9 @@ "xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.notFoundLabel": "Impossible de trouver un Lens correspondant.", "xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.savedObjectType.lens": "Lens", "xpack.cases.markdownEditor.plugins.lens.openVisualizationButtonLabel": "Visualisation ouverte", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.filterButtonLabel": "Types", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputHelpText": "Insérez un Lens à partir de modèles existants ou en créant un nouveau modèle. Vous créerez un Lens uniquement pour ce commentaire et ne changerez pas la Bibliothèque Visualize.", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputLabel": "Sélectionner un Lens", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputPrependLabel": "Modèle", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchPlaceholder": "Rechercher…", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAsc": "Croissant", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAuto": "Meilleure correspondance", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortButtonLabel": "Trier", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortDesc": "Décroissant", "xpack.cases.markdownEditor.plugins.lens.visualizationButtonLabel": "Visualisation", "xpack.cases.markdownEditor.plugins.timeline.noParenthesesErrorMsg": "Parenthèses gauches attendues", "xpack.cases.markdownEditor.preview": "Aperçu", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f3c0b84e452b1..c81197b7eba19 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9631,15 +9631,9 @@ "xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.notFoundLabel": "一致するLensが見つかりません。", "xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.savedObjectType.lens": "レンズ", "xpack.cases.markdownEditor.plugins.lens.openVisualizationButtonLabel": "ビジュアライゼーションを開く", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.filterButtonLabel": "タイプ", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputHelpText": "既存のテンプレートからLensを挿入するか、新しく作成します。このコメントでのみLensが作成されます。Visualize Libraryは変更されません。", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputLabel": "Lensを選択", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputPrependLabel": "テンプレート", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchPlaceholder": "検索…", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAsc": "昇順", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAuto": "ベストマッチ", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortButtonLabel": "並べ替え", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortDesc": "降順", "xpack.cases.markdownEditor.plugins.lens.visualizationButtonLabel": "ビジュアライゼーション", "xpack.cases.markdownEditor.plugins.timeline.noParenthesesErrorMsg": "想定される左括弧", "xpack.cases.markdownEditor.preview": "プレビュー", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e8809adf47caf..53f914a9e72e3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9646,15 +9646,9 @@ "xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.notFoundLabel": "未找到匹配的 lens。", "xpack.cases.markdownEditor.plugins.lens.insertLensSavedObjectModal.searchSelection.savedObjectType.lens": "Lens", "xpack.cases.markdownEditor.plugins.lens.openVisualizationButtonLabel": "打开可视化", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.filterButtonLabel": "类型", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputHelpText": "通过现有模板或创建新模板来插入 Lens。您将仅为此注释创建 Lens,并且不会更改可视化库。", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputLabel": "选择 Lens", "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchInputPrependLabel": "模板", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.searchPlaceholder": "搜索……", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAsc": "升序", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortAuto": "最佳匹配", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortButtonLabel": "排序", - "xpack.cases.markdownEditor.plugins.lens.savedObjects.finder.sortDesc": "降序", "xpack.cases.markdownEditor.plugins.lens.visualizationButtonLabel": "可视化", "xpack.cases.markdownEditor.plugins.timeline.noParenthesesErrorMsg": "应为左括号", "xpack.cases.markdownEditor.preview": "预览", From 28ab5c73798cbd3c72e520b80738d6fe22d15a21 Mon Sep 17 00:00:00 2001 From: Bena Kansara <69037875+benakansara@users.noreply.github.com> Date: Tue, 28 Feb 2023 13:39:01 +0100 Subject: [PATCH 042/131] Combine rule tags with source tags in alert context and AAD for infra rules (#150502) Part of https://github.com/elastic/kibana/issues/150110 Combines rule tags with source tags in alert's context for Inventory threshold and Metric threshold rules. The same combination of tags is also indexed to AAD. ### Manual Testing 1. Create Inventory rule with some tags 2. Add connector for active and recovered alerts with `{{context}}` in action template 3. Ensure that both rule tags and tags from source are available in `context.tags` in alert notifications 4. Ensure that the combination of tags is also indexed to AAD Repeat the same steps for Metric threshold rule. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/alerting/common/utils.test.ts | 58 +++ .../infra/server/lib/alerting/common/utils.ts | 60 +-- ...nventory_metric_threshold_executor.test.ts | 301 ++++++++++++++ .../inventory_metric_threshold_executor.ts | 386 +++++++++--------- .../metric_threshold_executor.test.ts | 137 +++++++ .../metric_threshold_executor.ts | 10 +- .../log_views/log_views_client.mock.ts | 3 +- .../server/utils/create_lifecycle_executor.ts | 4 +- 8 files changed, 724 insertions(+), 235 deletions(-) create mode 100644 x-pack/plugins/infra/server/lib/alerting/common/utils.test.ts create mode 100644 x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts diff --git a/x-pack/plugins/infra/server/lib/alerting/common/utils.test.ts b/x-pack/plugins/infra/server/lib/alerting/common/utils.test.ts new file mode 100644 index 0000000000000..808b75cdb36c9 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/common/utils.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { flattenObject } from './utils'; + +describe('FlattenObject', () => { + it('flattens multi level item', () => { + const data = { + key1: { + item1: 'value 1', + item2: { itemA: 'value 2' }, + }, + key2: { + item3: { itemA: { itemAB: 'value AB' } }, + item4: 'value 4', + }, + }; + + const flatten = flattenObject(data); + expect(flatten).toEqual({ + 'key2.item3.itemA.itemAB': 'value AB', + 'key2.item4': 'value 4', + 'key1.item1': 'value 1', + 'key1.item2.itemA': 'value 2', + }); + }); + + it('does not flatten an array item', () => { + const data = { + key1: { + item1: 'value 1', + item2: { itemA: 'value 2' }, + }, + key2: { + item3: { itemA: { itemAB: 'value AB' } }, + item4: 'value 4', + item5: [1], + item6: { itemA: [1, 2, 3] }, + }, + key3: ['item7', 'item8'], + }; + + const flatten = flattenObject(data); + expect(flatten).toEqual({ + key3: ['item7', 'item8'], + 'key2.item3.itemA.itemAB': 'value AB', + 'key2.item4': 'value 4', + 'key2.item5': [1], + 'key2.item6.itemA': [1, 2, 3], + 'key1.item1': 'value 1', + 'key1.item2.itemA': 'value 2', + }); + }); +}); diff --git a/x-pack/plugins/infra/server/lib/alerting/common/utils.ts b/x-pack/plugins/infra/server/lib/alerting/common/utils.ts index d59192306874a..01c69d4f5d126 100644 --- a/x-pack/plugins/infra/server/lib/alerting/common/utils.ts +++ b/x-pack/plugins/infra/server/lib/alerting/common/utils.ts @@ -226,18 +226,7 @@ export const shouldTermsAggOnContainer = (groupBy: string | string[] | undefined export const flattenAdditionalContext = ( additionalContext: AdditionalContext | undefined | null ): AdditionalContext => { - let flattenedContext: AdditionalContext = {}; - if (additionalContext) { - Object.keys(additionalContext).forEach((context: string) => { - if (additionalContext[context]) { - flattenedContext = { - ...flattenedContext, - ...flattenObject(additionalContext[context], [context + '.']), - }; - } - }); - } - return flattenedContext; + return additionalContext ? flattenObject(additionalContext) : {}; }; export const getContextForRecoveredAlerts = ( @@ -261,39 +250,24 @@ export const unflattenObject = (object: ob return acc; }, {} as T); -/** - * Wrap the key with [] if it is a key from an Array - * @param key The object key - * @param isArrayItem Flag to indicate if it is the key of an Array - */ -const renderKey = (key: string, isArrayItem: boolean): string => (isArrayItem ? `[${key}]` : key); - -export const flattenObject = ( - obj: AdditionalContext, - prefix: string[] = [], - isArrayItem = false -): AdditionalContext => - Object.keys(obj).reduce((acc, k) => { - const nextValue = obj[k]; - - if (typeof nextValue === 'object' && nextValue !== null) { - const isNextValueArray = Array.isArray(nextValue); - const dotSuffix = isNextValueArray ? '' : '.'; - - if (Object.keys(nextValue).length > 0) { - return { - ...acc, - ...flattenObject( - nextValue, - [...prefix, `${renderKey(k, isArrayItem)}${dotSuffix}`], - isNextValueArray - ), - }; +export const flattenObject = (obj: AdditionalContext, prefix: string = ''): AdditionalContext => + Object.keys(obj).reduce((acc, key) => { + const nextValue = obj[key]; + + if (nextValue) { + if (typeof nextValue === 'object' && !Array.isArray(nextValue)) { + const dotSuffix = '.'; + if (Object.keys(nextValue).length > 0) { + return { + ...acc, + ...flattenObject(nextValue, `${prefix}${key}${dotSuffix}`), + }; + } } - } - const fullPath = `${prefix.join('')}${renderKey(k, isArrayItem)}`; - acc[fullPath] = nextValue; + const fullPath = `${prefix}${key}`; + acc[fullPath] = nextValue; + } return acc; }, {}); diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts new file mode 100644 index 0000000000000..63b0c81108a47 --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.test.ts @@ -0,0 +1,301 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + AlertInstanceContext as AlertContext, + AlertInstanceState as AlertState, +} from '@kbn/alerting-plugin/server'; +import { + AlertInstanceMock, + RuleExecutorServicesMock, + alertsMock, +} from '@kbn/alerting-plugin/server/mocks'; +import { LifecycleAlertServices } from '@kbn/rule-registry-plugin/server'; +import { ruleRegistryMocks } from '@kbn/rule-registry-plugin/server/mocks'; +import { createLifecycleRuleExecutorMock } from '@kbn/rule-registry-plugin/server/utils/create_lifecycle_rule_executor_mock'; +import { + Aggregators, + Comparator, + InventoryMetricConditions, +} from '../../../../common/alerting/metrics'; + +import type { LogMeta, Logger } from '@kbn/logging'; +import { DEFAULT_FLAPPING_SETTINGS } from '@kbn/alerting-plugin/common'; +import { createInventoryMetricThresholdExecutor } from './inventory_metric_threshold_executor'; +import { ConditionResult } from './evaluate_condition'; +import { InfraBackendLibs } from '../../infra_types'; +import { infraPluginMock } from '../../../mocks'; + +jest.mock('./evaluate_condition', () => ({ evaluateCondition: jest.fn() })); + +interface AlertTestInstance { + instance: AlertInstanceMock; + actionQueue: any[]; + state: any; +} + +const persistAlertInstances = false; + +const fakeLogger = (msg: string, meta?: Meta) => {}; + +const logger = { + trace: fakeLogger, + debug: fakeLogger, + info: fakeLogger, + warn: fakeLogger, + error: fakeLogger, + fatal: fakeLogger, + log: () => void 0, + get: () => logger, +} as unknown as Logger; + +const mockOptions = { + executionId: '', + startedAt: new Date(), + previousStartedAt: null, + spaceId: '', + rule: { + id: '', + name: '', + tags: [], + consumer: '', + enabled: true, + schedule: { + interval: '1h', + }, + actions: [], + createdBy: null, + updatedBy: null, + createdAt: new Date(), + updatedAt: new Date(), + throttle: null, + notifyWhen: null, + producer: '', + ruleTypeId: '', + ruleTypeName: '', + muteAll: false, + }, + logger, + flappingSettings: DEFAULT_FLAPPING_SETTINGS, +}; + +const setEvaluationResults = (response: Record) => { + jest.requireMock('./evaluate_condition').evaluateCondition.mockImplementation(() => response); +}; +const createMockStaticConfiguration = (sources: any) => ({ + alerting: { + inventory_threshold: { + group_by_page_size: 100, + }, + metric_threshold: { + group_by_page_size: 100, + }, + }, + inventory: { + compositeSize: 2000, + }, + sources, +}); + +const mockLibs = { + sources: { + getSourceConfiguration: (savedObjectsClient: any, sourceId: string) => { + return Promise.resolve({ + id: sourceId, + configuration: { + logIndices: { + type: 'index_pattern', + indexPatternId: 'some-id', + }, + }, + }); + }, + }, + getStartServices: () => [ + null, + infraPluginMock.createSetupContract(), + infraPluginMock.createStartContract(), + ], + configuration: createMockStaticConfiguration({}), + metricsRules: { + createLifecycleRuleExecutor: createLifecycleRuleExecutorMock, + }, + basePath: { + publicBaseUrl: 'http://localhost:5601', + prepend: (path: string) => path, + }, + logger, +} as unknown as InfraBackendLibs; + +const alertsServices = alertsMock.createRuleExecutorServices(); +const services: RuleExecutorServicesMock & + LifecycleAlertServices = { + ...alertsServices, + ...ruleRegistryMocks.createLifecycleAlertServices(alertsServices), +}; + +const alertInstances = new Map(); + +services.alertFactory.create.mockImplementation((instanceID: string) => { + const newAlertInstance: AlertTestInstance = { + instance: alertsMock.createAlertFactory.create(), + actionQueue: [], + state: {}, + }; + + const alertInstance: AlertTestInstance = persistAlertInstances + ? alertInstances.get(instanceID) || newAlertInstance + : newAlertInstance; + alertInstances.set(instanceID, alertInstance); + + alertInstance.instance.scheduleActions.mockImplementation((id: string, action: any) => { + alertInstance.actionQueue.push({ id, action }); + return alertInstance.instance; + }); + + return alertInstance.instance; +}); + +function mostRecentAction(id: string) { + const instance = alertInstances.get(id); + if (!instance) return undefined; + return instance.actionQueue.pop(); +} + +function clearInstances() { + alertInstances.clear(); +} + +const executor = createInventoryMetricThresholdExecutor(mockLibs); + +const baseCriterion = { + aggType: Aggregators.AVERAGE, + metric: 'count', + timeSize: 1, + timeUnit: 'm', + threshold: [0], + comparator: Comparator.GT, +} as InventoryMetricConditions; + +describe('The inventory threshold alert type', () => { + describe('querying with Hosts and rule tags', () => { + afterAll(() => clearInstances()); + const execute = (comparator: Comparator, threshold: number[], state?: any) => + executor({ + ...mockOptions, + services, + params: { + nodeType: 'host', + criteria: [ + { + ...baseCriterion, + comparator, + threshold, + }, + ], + }, + state: state ?? {}, + rule: { + ...mockOptions.rule, + tags: ['ruleTag1', 'ruleTag2'], + }, + }); + + const instanceIdA = 'host-01'; + const instanceIdB = 'host-02'; + + test('when tags are present in the source, rule tags and source tags are combined in alert context', async () => { + setEvaluationResults({ + 'host-01': { + ...baseCriterion, + metric: 'count', + timeSize: 1, + timeUnit: 'm', + threshold: [0.75], + comparator: Comparator.GT, + shouldFire: true, + shouldWarn: false, + currentValue: 1.0, + isNoData: false, + isError: false, + context: { + tags: ['host-01_tag1', 'host-01_tag2'], + }, + }, + 'host-02': { + ...baseCriterion, + metric: 'count', + timeSize: 1, + timeUnit: 'm', + threshold: [0.75], + comparator: Comparator.GT, + shouldFire: true, + shouldWarn: false, + currentValue: 1.0, + isNoData: false, + isError: false, + context: { + tags: ['host-02_tag1', 'host-02_tag2'], + }, + }, + }); + await execute(Comparator.GT, [0.75]); + expect(mostRecentAction(instanceIdA).action.tags).toStrictEqual([ + 'host-01_tag1', + 'host-01_tag2', + 'ruleTag1', + 'ruleTag2', + ]); + expect(mostRecentAction(instanceIdB).action.tags).toStrictEqual([ + 'host-02_tag1', + 'host-02_tag2', + 'ruleTag1', + 'ruleTag2', + ]); + }); + + test('when tags are NOT present in the source, rule tags are added in alert context', async () => { + setEvaluationResults({ + 'host-01': { + ...baseCriterion, + metric: 'count', + timeSize: 1, + timeUnit: 'm', + threshold: [0.75], + comparator: Comparator.GT, + shouldFire: true, + shouldWarn: false, + currentValue: 1.0, + isNoData: false, + isError: false, + context: { + cloud: undefined, + }, + }, + 'host-02': { + ...baseCriterion, + metric: 'count', + timeSize: 1, + timeUnit: 'm', + threshold: [0.75], + comparator: Comparator.GT, + shouldFire: true, + shouldWarn: false, + currentValue: 1.0, + isNoData: false, + isError: false, + context: { + tags: undefined, + }, + }, + }); + await execute(Comparator.GT, [0.75]); + expect(mostRecentAction(instanceIdA).action.tags).toStrictEqual(['ruleTag1', 'ruleTag2']); + expect(mostRecentAction(instanceIdB).action.tags).toStrictEqual(['ruleTag1', 'ruleTag2']); + }); + }); +}); diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index ffd0a7e563339..e62fd9291fc33 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -76,176 +76,218 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = InventoryMetricThresholdAlertState, InventoryMetricThresholdAlertContext, InventoryMetricThresholdAllowedActionGroups - >(async ({ services, params, executionId, spaceId, startedAt, rule: { id: ruleId } }) => { - const startTime = Date.now(); + >( + async ({ + services, + params, + executionId, + spaceId, + startedAt, + rule: { id: ruleId, tags: ruleTags }, + }) => { + const startTime = Date.now(); - const { criteria, filterQuery, sourceId = 'default', nodeType, alertOnNoData } = params; + const { criteria, filterQuery, sourceId = 'default', nodeType, alertOnNoData } = params; - if (criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions'); + if (criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions'); - const logger = createScopedLogger(libs.logger, 'inventoryRule', { - alertId: ruleId, - executionId, - }); - - const esClient = services.scopedClusterClient.asCurrentUser; - - const { - alertWithLifecycle, - savedObjectsClient, - getAlertStartedDate, - getAlertUuid, - getAlertByAlertUuid, - } = services; - const alertFactory: InventoryMetricThresholdAlertFactory = ( - id, - reason, - actionGroup, - additionalContext - ) => - alertWithLifecycle({ - id, - fields: { - [ALERT_REASON]: reason, - [ALERT_ACTION_GROUP]: actionGroup, - ...flattenAdditionalContext(additionalContext), - }, + const logger = createScopedLogger(libs.logger, 'inventoryRule', { + alertId: ruleId, + executionId, }); - if (!params.filterQuery && params.filterQueryText) { - try { - const { fromKueryExpression } = await import('@kbn/es-query'); - fromKueryExpression(params.filterQueryText); - } catch (e) { - logger.error(e.message); - const actionGroupId = FIRED_ACTIONS.id; // Change this to an Error action group when able - const reason = buildInvalidQueryAlertReason(params.filterQueryText); - const alert = alertFactory(UNGROUPED_FACTORY_KEY, reason, actionGroupId); - const indexedStartedDate = - getAlertStartedDate(UNGROUPED_FACTORY_KEY) ?? startedAt.toISOString(); - const alertUuid = getAlertUuid(UNGROUPED_FACTORY_KEY); - - alert.scheduleActions(actionGroupId, { - alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, alertUuid), - alertState: stateToAlertMessage[AlertStates.ERROR], - group: UNGROUPED_FACTORY_KEY, - metric: mapToConditionsLookup(criteria, (c) => c.metric), - reason, - timestamp: startedAt.toISOString(), - value: null, - viewInAppUrl: getViewInInventoryAppUrl({ - basePath: libs.basePath, - criteria, - nodeType, - timestamp: indexedStartedDate, - spaceId, - }), + const esClient = services.scopedClusterClient.asCurrentUser; + + const { + alertWithLifecycle, + savedObjectsClient, + getAlertStartedDate, + getAlertUuid, + getAlertByAlertUuid, + } = services; + const alertFactory: InventoryMetricThresholdAlertFactory = ( + id, + reason, + actionGroup, + additionalContext + ) => + alertWithLifecycle({ + id, + fields: { + [ALERT_REASON]: reason, + [ALERT_ACTION_GROUP]: actionGroup, + ...flattenAdditionalContext(additionalContext), + }, }); - return { state: {} }; + if (!params.filterQuery && params.filterQueryText) { + try { + const { fromKueryExpression } = await import('@kbn/es-query'); + fromKueryExpression(params.filterQueryText); + } catch (e) { + logger.error(e.message); + const actionGroupId = FIRED_ACTIONS.id; // Change this to an Error action group when able + const reason = buildInvalidQueryAlertReason(params.filterQueryText); + const alert = alertFactory(UNGROUPED_FACTORY_KEY, reason, actionGroupId); + const indexedStartedDate = + getAlertStartedDate(UNGROUPED_FACTORY_KEY) ?? startedAt.toISOString(); + const alertUuid = getAlertUuid(UNGROUPED_FACTORY_KEY); + + alert.scheduleActions(actionGroupId, { + alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, alertUuid), + alertState: stateToAlertMessage[AlertStates.ERROR], + group: UNGROUPED_FACTORY_KEY, + metric: mapToConditionsLookup(criteria, (c) => c.metric), + reason, + timestamp: startedAt.toISOString(), + value: null, + viewInAppUrl: getViewInInventoryAppUrl({ + basePath: libs.basePath, + criteria, + nodeType, + timestamp: indexedStartedDate, + spaceId, + }), + }); + + return { state: {} }; + } } - } - const source = await libs.sources.getSourceConfiguration(savedObjectsClient, sourceId); - - const [, , { logViews }] = await libs.getStartServices(); - const logQueryFields: LogQueryFields | undefined = await logViews - .getClient(savedObjectsClient, esClient) - .getResolvedLogView(sourceId) - .then( - ({ indices }) => ({ indexPattern: indices }), - () => undefined + const source = await libs.sources.getSourceConfiguration(savedObjectsClient, sourceId); + + const [, , { logViews }] = await libs.getStartServices(); + const logQueryFields: LogQueryFields | undefined = await logViews + .getClient(savedObjectsClient, esClient) + .getResolvedLogView(sourceId) + .then( + ({ indices }) => ({ indexPattern: indices }), + () => undefined + ); + + const compositeSize = libs.configuration.alerting.inventory_threshold.group_by_page_size; + const results = await Promise.all( + criteria.map((condition) => + evaluateCondition({ + compositeSize, + condition, + esClient, + executionTimestamp: startedAt, + filterQuery, + logger, + logQueryFields, + nodeType, + source, + }) + ) ); - const compositeSize = libs.configuration.alerting.inventory_threshold.group_by_page_size; - const results = await Promise.all( - criteria.map((condition) => - evaluateCondition({ - compositeSize, - condition, - esClient, - executionTimestamp: startedAt, - filterQuery, - logger, - logQueryFields, - nodeType, - source, - }) - ) - ); - - let scheduledActionsCount = 0; - const inventoryItems = Object.keys(first(results)!); - for (const group of inventoryItems) { - // AND logic; all criteria must be across the threshold - const shouldAlertFire = results.every((result) => result[group]?.shouldFire); - const shouldAlertWarn = results.every((result) => result[group]?.shouldWarn); - // AND logic; because we need to evaluate all criteria, if one of them reports no data then the - // whole alert is in a No Data/Error state - const isNoData = results.some((result) => result[group]?.isNoData); - const isError = results.some((result) => result[group]?.isError); - - const nextState = isError - ? AlertStates.ERROR - : isNoData - ? AlertStates.NO_DATA - : shouldAlertFire - ? AlertStates.ALERT - : shouldAlertWarn - ? AlertStates.WARNING - : AlertStates.OK; - let reason; - if (nextState === AlertStates.ALERT || nextState === AlertStates.WARNING) { - reason = results - .map((result) => - buildReasonWithVerboseMetricName( - group, - result[group], - buildFiredAlertReason, - nextState === AlertStates.WARNING - ) - ) - .join('\n'); - } - if (alertOnNoData) { - if (nextState === AlertStates.NO_DATA) { - reason = results - .filter((result) => result[group].isNoData) - .map((result) => - buildReasonWithVerboseMetricName(group, result[group], buildNoDataAlertReason) - ) - .join('\n'); - } else if (nextState === AlertStates.ERROR) { + let scheduledActionsCount = 0; + const inventoryItems = Object.keys(first(results)!); + for (const group of inventoryItems) { + // AND logic; all criteria must be across the threshold + const shouldAlertFire = results.every((result) => result[group]?.shouldFire); + const shouldAlertWarn = results.every((result) => result[group]?.shouldWarn); + // AND logic; because we need to evaluate all criteria, if one of them reports no data then the + // whole alert is in a No Data/Error state + const isNoData = results.some((result) => result[group]?.isNoData); + const isError = results.some((result) => result[group]?.isError); + + const nextState = isError + ? AlertStates.ERROR + : isNoData + ? AlertStates.NO_DATA + : shouldAlertFire + ? AlertStates.ALERT + : shouldAlertWarn + ? AlertStates.WARNING + : AlertStates.OK; + let reason; + if (nextState === AlertStates.ALERT || nextState === AlertStates.WARNING) { reason = results - .filter((result) => result[group].isError) .map((result) => - buildReasonWithVerboseMetricName(group, result[group], buildErrorAlertReason) + buildReasonWithVerboseMetricName( + group, + result[group], + buildFiredAlertReason, + nextState === AlertStates.WARNING + ) ) .join('\n'); } + if (alertOnNoData) { + if (nextState === AlertStates.NO_DATA) { + reason = results + .filter((result) => result[group].isNoData) + .map((result) => + buildReasonWithVerboseMetricName(group, result[group], buildNoDataAlertReason) + ) + .join('\n'); + } else if (nextState === AlertStates.ERROR) { + reason = results + .filter((result) => result[group].isError) + .map((result) => + buildReasonWithVerboseMetricName(group, result[group], buildErrorAlertReason) + ) + .join('\n'); + } + } + if (reason) { + const actionGroupId = + nextState === AlertStates.WARNING ? WARNING_ACTIONS_ID : FIRED_ACTIONS_ID; + + const additionalContext = results && results.length > 0 ? results[0][group].context : {}; + additionalContext.tags = Array.from( + new Set([...(additionalContext.tags ?? []), ...ruleTags]) + ); + + const alert = alertFactory(group, reason, actionGroupId, additionalContext); + const indexedStartedDate = getAlertStartedDate(group) ?? startedAt.toISOString(); + const alertUuid = getAlertUuid(group); + + scheduledActionsCount++; + + const context = { + alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, alertUuid), + alertState: stateToAlertMessage[nextState], + group, + reason, + metric: mapToConditionsLookup(criteria, (c) => c.metric), + timestamp: startedAt.toISOString(), + threshold: mapToConditionsLookup(criteria, (c) => c.threshold), + value: mapToConditionsLookup(results, (result) => + formatMetric(result[group].metric, result[group].currentValue) + ), + viewInAppUrl: getViewInInventoryAppUrl({ + basePath: libs.basePath, + criteria, + nodeType, + timestamp: indexedStartedDate, + spaceId, + }), + ...additionalContext, + }; + alert.scheduleActions(actionGroupId, context); + } } - if (reason) { - const actionGroupId = - nextState === AlertStates.WARNING ? WARNING_ACTIONS_ID : FIRED_ACTIONS_ID; - const additionalContext = results && results.length > 0 ? results[0][group].context : null; + const { getRecoveredAlerts } = services.alertFactory.done(); + const recoveredAlerts = getRecoveredAlerts(); - const alert = alertFactory(group, reason, actionGroupId, additionalContext); - const indexedStartedDate = getAlertStartedDate(group) ?? startedAt.toISOString(); - const alertUuid = getAlertUuid(group); + for (const alert of recoveredAlerts) { + const recoveredAlertId = alert.getId(); + const indexedStartedDate = getAlertStartedDate(recoveredAlertId) ?? startedAt.toISOString(); + const alertUuid = getAlertUuid(recoveredAlertId); + const alertHits = alertUuid ? await getAlertByAlertUuid(alertUuid) : undefined; + const additionalContext = getContextForRecoveredAlerts(alertHits); + const originalActionGroup = getOriginalActionGroup(alertHits); - scheduledActionsCount++; - - const context = { + alert.setContext({ alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, alertUuid), - alertState: stateToAlertMessage[nextState], - group, - reason, + alertState: stateToAlertMessage[AlertStates.OK], + group: recoveredAlertId, metric: mapToConditionsLookup(criteria, (c) => c.metric), - timestamp: startedAt.toISOString(), threshold: mapToConditionsLookup(criteria, (c) => c.threshold), - value: mapToConditionsLookup(results, (result) => - formatMetric(result[group].metric, result[group].currentValue) - ), + timestamp: startedAt.toISOString(), viewInAppUrl: getViewInInventoryAppUrl({ basePath: libs.basePath, criteria, @@ -253,49 +295,19 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = timestamp: indexedStartedDate, spaceId, }), + originalAlertState: translateActionGroupToAlertState(originalActionGroup), + originalAlertStateWasALERT: originalActionGroup === FIRED_ACTIONS_ID, + originalAlertStateWasWARNING: originalActionGroup === WARNING_ACTIONS_ID, ...additionalContext, - }; - alert.scheduleActions(actionGroupId, context); + }); } - } - const { getRecoveredAlerts } = services.alertFactory.done(); - const recoveredAlerts = getRecoveredAlerts(); - - for (const alert of recoveredAlerts) { - const recoveredAlertId = alert.getId(); - const indexedStartedDate = getAlertStartedDate(recoveredAlertId) ?? startedAt.toISOString(); - const alertUuid = getAlertUuid(recoveredAlertId); - const alertHits = alertUuid ? await getAlertByAlertUuid(alertUuid) : undefined; - const additionalContext = getContextForRecoveredAlerts(alertHits); - const originalActionGroup = getOriginalActionGroup(alertHits); - - alert.setContext({ - alertDetailsUrl: getAlertDetailsUrl(libs.basePath, spaceId, alertUuid), - alertState: stateToAlertMessage[AlertStates.OK], - group: recoveredAlertId, - metric: mapToConditionsLookup(criteria, (c) => c.metric), - threshold: mapToConditionsLookup(criteria, (c) => c.threshold), - timestamp: startedAt.toISOString(), - viewInAppUrl: getViewInInventoryAppUrl({ - basePath: libs.basePath, - criteria, - nodeType, - timestamp: indexedStartedDate, - spaceId, - }), - originalAlertState: translateActionGroupToAlertState(originalActionGroup), - originalAlertStateWasALERT: originalActionGroup === FIRED_ACTIONS_ID, - originalAlertStateWasWARNING: originalActionGroup === WARNING_ACTIONS_ID, - ...additionalContext, - }); - } + const stopTime = Date.now(); + logger.debug(`Scheduled ${scheduledActionsCount} actions in ${stopTime - startTime}ms`); - const stopTime = Date.now(); - logger.debug(`Scheduled ${scheduledActionsCount} actions in ${stopTime - startTime}ms`); - - return { state: {} }; - }); + return { state: {} }; + } + ); const formatThreshold = (metric: SnapshotMetricType, value: number | number[]) => { const metricFormatter = get(METRIC_FORMATTERS, metric, METRIC_FORMATTERS.count); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index a94521c22bde4..f363b5baeabf1 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -690,6 +690,143 @@ describe('The metric threshold alert type', () => { }); }); + describe('querying with a groupBy parameter host.name and rule tags', () => { + afterAll(() => clearInstances()); + const execute = ( + comparator: Comparator, + threshold: number[], + groupBy: string[] = ['host.name'], + metric?: string, + state?: any + ) => + executor({ + ...mockOptions, + services, + params: { + groupBy, + criteria: [ + { + ...baseNonCountCriterion, + comparator, + threshold, + metric: metric ?? baseNonCountCriterion.metric, + }, + ], + }, + state: state ?? mockOptions.state.wrapped, + rule: { + ...mockOptions.rule, + tags: ['ruleTag1', 'ruleTag2'], + }, + }); + const instanceIdA = 'host-01'; + const instanceIdB = 'host-02'; + + test('rule tags and source tags are combined in alert context', async () => { + setEvaluationResults([ + { + 'host-01': { + ...baseNonCountCriterion, + comparator: Comparator.GT, + threshold: [0.75], + metric: 'test.metric.1', + currentValue: 1.0, + timestamp: new Date().toISOString(), + shouldFire: true, + shouldWarn: false, + isNoData: false, + bucketKey: { groupBy0: 'host-01' }, + context: { + tags: ['host-01_tag1', 'host-01_tag2'], + }, + }, + 'host-02': { + ...baseNonCountCriterion, + comparator: Comparator.GT, + threshold: [0.75], + metric: 'test.metric.1', + currentValue: 3, + timestamp: new Date().toISOString(), + shouldFire: true, + shouldWarn: false, + isNoData: false, + bucketKey: { groupBy0: 'host-02' }, + context: { + tags: ['host-02_tag1', 'host-02_tag2'], + }, + }, + }, + ]); + await execute(Comparator.GT, [0.75]); + expect(mostRecentAction(instanceIdA).action.tags).toStrictEqual([ + 'host-01_tag1', + 'host-01_tag2', + 'ruleTag1', + 'ruleTag2', + ]); + expect(mostRecentAction(instanceIdB).action.tags).toStrictEqual([ + 'host-02_tag1', + 'host-02_tag2', + 'ruleTag1', + 'ruleTag2', + ]); + }); + }); + + describe('querying without a groupBy parameter and rule tags', () => { + afterAll(() => clearInstances()); + const execute = ( + comparator: Comparator, + threshold: number[], + groupBy: string = '', + metric?: string, + state?: any + ) => + executor({ + ...mockOptions, + services, + params: { + groupBy, + criteria: [ + { + ...baseNonCountCriterion, + comparator, + threshold, + metric: metric ?? baseNonCountCriterion.metric, + }, + ], + }, + state: state ?? mockOptions.state.wrapped, + rule: { + ...mockOptions.rule, + tags: ['ruleTag1', 'ruleTag2'], + }, + }); + + test('rule tags are added in alert context', async () => { + setEvaluationResults([ + { + '*': { + ...baseNonCountCriterion, + comparator: Comparator.GT, + threshold: [0.75], + metric: 'test.metric.1', + currentValue: 1.0, + timestamp: new Date().toISOString(), + shouldFire: true, + shouldWarn: false, + isNoData: false, + bucketKey: { groupBy0: '*' }, + }, + }, + ]); + + const instanceID = '*'; + await execute(Comparator.GT, [0.75]); + expect(mostRecentAction(instanceID).action.tags).toStrictEqual(['ruleTag1', 'ruleTag2']); + }); + }); + describe('querying with multiple criteria', () => { afterAll(() => clearInstances()); const execute = ( diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts index cd0b0f48f36d4..28a32a8c46174 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts @@ -287,9 +287,13 @@ export const createMetricThresholdExecutor = (libs: InfraBackendLibs) => const additionalContext = hasAdditionalContext(params.groupBy, validGroupByForContext) ? alertResults && alertResults.length > 0 - ? alertResults[0][group].context - : null - : null; + ? alertResults[0][group].context ?? {} + : {} + : {}; + + additionalContext.tags = Array.from( + new Set([...(additionalContext.tags ?? []), ...options.rule.tags]) + ); const alert = alertFactory(`${group}`, reason, actionGroupId, additionalContext); const alertUuid = getAlertUuid(group); diff --git a/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts b/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts index ac69ae4f85ba5..5c20297b82c65 100644 --- a/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts +++ b/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts @@ -5,11 +5,12 @@ * 2.0. */ +import { createResolvedLogViewMock } from '../../../common/log_views/resolved_log_view.mock'; import { ILogViewsClient } from './types'; export const createLogViewsClientMock = (): jest.Mocked => ({ getLogView: jest.fn(), - getResolvedLogView: jest.fn(), + getResolvedLogView: jest.fn((logViewId: string) => Promise.resolve(createResolvedLogViewMock())), putLogView: jest.fn(), resolveLogView: jest.fn(), }); diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts index f0eef646a1f28..fdb73c85cecb1 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts @@ -314,7 +314,9 @@ export const createLifecycleExecutor = [ALERT_WORKFLOW_STATUS]: alertData?.fields[ALERT_WORKFLOW_STATUS] ?? 'open', [EVENT_KIND]: 'signal', [EVENT_ACTION]: isNew ? 'open' : isActive ? 'active' : 'close', - [TAGS]: options.rule.tags, + [TAGS]: Array.from( + new Set([...(currentAlertData?.tags ?? []), ...(options.rule.tags ?? [])]) + ), [VERSION]: ruleDataClient.kibanaVersion, [ALERT_FLAPPING]: flapping, ...(isRecovered ? { [ALERT_END]: commonRuleFields[TIMESTAMP] } : {}), From 19ea0909a3111627df2147b34be13672247c14d6 Mon Sep 17 00:00:00 2001 From: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com> Date: Tue, 28 Feb 2023 07:41:56 -0500 Subject: [PATCH 043/131] [Cases] Removing unnecessary mapping fields (#151511) This PR removes fields that do not need to be indexed from the various cases saved objects. Fixes: https://github.com/elastic/kibana/issues/151501, https://github.com/elastic/kibana/issues/138727 --- .../group2/check_registered_types.test.ts | 10 +-- .../cases/server/saved_object_types/cases.ts | 1 + .../server/saved_object_types/comments.ts | 82 +------------------ .../server/saved_object_types/configure.ts | 56 +------------ .../saved_object_types/connector_mappings.ts | 14 +--- .../server/saved_object_types/user_actions.ts | 10 +-- 6 files changed, 10 insertions(+), 163 deletions(-) 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 626b405b165ed..8aa1eb22fccbe 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 @@ -69,12 +69,12 @@ describe('checking migration metadata changes on all registered SO types', () => "canvas-element": "ec334dd45d14291db4d74197e0e42dfe06526868", "canvas-workpad": "ab0525bd5aa4dbad2d6fdb30e6a51bb475254751", "canvas-workpad-template": "c54f2a188a1d0bf18a6cebd9d6f28a7337d41bbf", - "cases": "74c00dfb25f4b109894971bd1090fce4a7c99490", - "cases-comments": "371662a8464e623f1f4f55a981cec78bec4a12f5", - "cases-configure": "25099c9e4bbb91e01e334848c605b4a5de5c9fce", - "cases-connector-mappings": "8de3b77dc6ae8ee62cce2b58a222471dfc3dbdad", + "cases": "1e86563e8364c69f86b77cb6f2933408dd5b827a", + "cases-comments": "69257ec55e8380fdb2ecbddc83e7c26d2ce2a351", + "cases-configure": "66d4c64d83b464f5166005b8ffa03b721fcaaf8b", + "cases-connector-mappings": "877bb4d52e9821e330622bd75fba799490ec6952", "cases-telemetry": "fdeddcef28c75d8c66422475a829e75d37f0b668", - "cases-user-actions": "cfd388d2ca27b3abfd3955dc41428fb229989921", + "cases-user-actions": "8ad74294b71edffa58fad7a40eea2388209477c9", "config": "97e16b8f5dc10c404fd3b201ef36bc6c3c63dc80", "config-global": "d9791e8f73edee884630e1cb6e4954ae513ce75e", "connector_token": "fb05ff5afdcb6e2f20c9c6513ff7a1ab12b66f36", diff --git a/x-pack/plugins/cases/server/saved_object_types/cases.ts b/x-pack/plugins/cases/server/saved_object_types/cases.ts index e32aa462d7121..1d70808f14db2 100644 --- a/x-pack/plugins/cases/server/saved_object_types/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/cases.ts @@ -26,6 +26,7 @@ export const createCaseSavedObjectType = ( namespaceType: 'multiple-isolated', convertToMultiNamespaceTypeVersion: '8.0.0', mappings: { + dynamic: false, properties: { assignees: { 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 c795b7d960e61..1d02a26f732c8 100644 --- a/x-pack/plugins/cases/server/saved_object_types/comments.ts +++ b/x-pack/plugins/cases/server/saved_object_types/comments.ts @@ -20,6 +20,7 @@ export const createCaseCommentSavedObjectType = ({ namespaceType: 'multiple-isolated', convertToMultiNamespaceTypeVersion: '8.0.0', mappings: { + dynamic: false, properties: { comment: { type: 'text', @@ -32,115 +33,34 @@ export const createCaseCommentSavedObjectType = ({ }, actions: { properties: { - targets: { - type: 'nested', - properties: { - hostname: { type: 'keyword' }, - endpointId: { type: 'keyword' }, - }, - }, type: { type: 'keyword' }, }, }, alertId: { type: 'keyword', }, - index: { - type: 'keyword', - }, created_at: { type: 'date', }, created_by: { properties: { - full_name: { - type: 'keyword', - }, username: { type: 'keyword', }, - email: { - type: 'keyword', - }, - profile_uid: { - type: 'keyword', - }, - }, - }, - externalReferenceId: { - type: 'keyword', - }, - externalReferenceStorage: { - dynamic: false, - properties: { - // externalReferenceStorage.type - type: { - type: 'keyword', - }, }, }, externalReferenceAttachmentTypeId: { type: 'keyword', }, - externalReferenceMetadata: { - dynamic: false, - properties: {}, - }, persistableStateAttachmentTypeId: { type: 'keyword', }, - persistableStateAttachmentState: { - dynamic: false, - properties: {}, - }, pushed_at: { type: 'date', }, - pushed_by: { - properties: { - username: { - type: 'keyword', - }, - full_name: { - type: 'keyword', - }, - email: { - type: 'keyword', - }, - profile_uid: { - type: 'keyword', - }, - }, - }, - rule: { - properties: { - id: { - type: 'keyword', - }, - name: { - type: 'keyword', - }, - }, - }, updated_at: { type: 'date', }, - updated_by: { - properties: { - username: { - type: 'keyword', - }, - full_name: { - type: 'keyword', - }, - email: { - type: 'keyword', - }, - profile_uid: { - type: 'keyword', - }, - }, - }, }, }, migrations: () => createCommentsMigrations(migrationDeps), diff --git a/x-pack/plugins/cases/server/saved_object_types/configure.ts b/x-pack/plugins/cases/server/saved_object_types/configure.ts index 2ee1e3458c647..879640c4b6e40 100644 --- a/x-pack/plugins/cases/server/saved_object_types/configure.ts +++ b/x-pack/plugins/cases/server/saved_object_types/configure.ts @@ -15,71 +15,17 @@ export const caseConfigureSavedObjectType: SavedObjectsType = { namespaceType: 'multiple-isolated', convertToMultiNamespaceTypeVersion: '8.0.0', mappings: { + dynamic: false, properties: { created_at: { type: 'date', }, - created_by: { - properties: { - email: { - type: 'keyword', - }, - username: { - type: 'keyword', - }, - full_name: { - type: 'keyword', - }, - profile_uid: { - type: 'keyword', - }, - }, - }, - connector: { - properties: { - name: { - type: 'text', - }, - type: { - type: 'keyword', - }, - fields: { - properties: { - key: { - type: 'text', - }, - value: { - type: 'text', - }, - }, - }, - }, - }, closure_type: { type: 'keyword', }, owner: { type: 'keyword', }, - updated_at: { - type: 'date', - }, - updated_by: { - properties: { - email: { - type: 'keyword', - }, - username: { - type: 'keyword', - }, - full_name: { - type: 'keyword', - }, - profile_uid: { - type: 'keyword', - }, - }, - }, }, }, migrations: configureMigrations, diff --git a/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts b/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts index 7d89b090847d3..1335570e8a132 100644 --- a/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts +++ b/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts @@ -15,20 +15,8 @@ export const caseConnectorMappingsSavedObjectType: SavedObjectsType = { namespaceType: 'multiple-isolated', convertToMultiNamespaceTypeVersion: '8.0.0', mappings: { + dynamic: false, properties: { - mappings: { - properties: { - source: { - type: 'keyword', - }, - target: { - type: 'keyword', - }, - action_type: { - type: 'keyword', - }, - }, - }, owner: { type: 'keyword', }, diff --git a/x-pack/plugins/cases/server/saved_object_types/user_actions.ts b/x-pack/plugins/cases/server/saved_object_types/user_actions.ts index 067ecaaf8fe1e..d8c442b39dab1 100644 --- a/x-pack/plugins/cases/server/saved_object_types/user_actions.ts +++ b/x-pack/plugins/cases/server/saved_object_types/user_actions.ts @@ -18,6 +18,7 @@ export const createCaseUserActionSavedObjectType = ( namespaceType: 'multiple-isolated', convertToMultiNamespaceTypeVersion: '8.0.0', mappings: { + dynamic: false, properties: { action: { type: 'keyword', @@ -27,18 +28,9 @@ export const createCaseUserActionSavedObjectType = ( }, created_by: { properties: { - email: { - type: 'keyword', - }, username: { type: 'keyword', }, - full_name: { - type: 'keyword', - }, - profile_uid: { - type: 'keyword', - }, }, }, payload: { From 0af458986252297b2c36fb78c6e20fac0cfaa702 Mon Sep 17 00:00:00 2001 From: Carlos Crespo Date: Tue, 28 Feb 2023 13:42:58 +0100 Subject: [PATCH 044/131] [Infrastucture UI] Use ECS fields in the rx and tx chart formulas (#152214) ## Summary closes [#152010](https://github.com/elastic/kibana/issues/152010) The RX and TX formulas were using `system.network.*` fields and their value didn't match with those of the Hosts table and KPI chart, which use the ECS `host.network.*` and `host.network.*` fields. This PR fixes the formulas to use the correct fields image image The values and the trend lines are similar or close to what's on the KPI and Table. RX ~5mb and TX with spikes of 800Pbit image ### How to test - Make sure you have metrics data (either through enabling system module in metricbeat or connecting your local kibana to an oblt-cli cluster) - Navigate to `Infrastructure` > `Hosts` - Compare metric charts against the table and KPI tiles. Adjust the time range filter to check if the values in the charts continue to make sense --- .../public/common/visualizations/lens/hosts/rx.ts | 8 ++++---- .../public/common/visualizations/lens/hosts/tx.ts | 7 +++---- .../pages/metrics/hosts/hooks/use_hosts_table.tsx | 12 ++++++------ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/hosts/rx.ts b/x-pack/plugins/infra/public/common/visualizations/lens/hosts/rx.ts index 228d479f39ee2..4b2ee6d8a2eda 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/hosts/rx.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/hosts/rx.ts @@ -53,8 +53,8 @@ export class RX implements ILensVisualization { const dataLayer = this.formula.insertOrReplaceFormulaColumn( 'y_network_in_bytes', { - formula: "counter_rate(max(system.network.in.bytes), kql='system.network.in.bytes: *') * 8", - timeScale: 's', + formula: + "average(host.network.ingress.bytes) * 8 / (max(metricset.period, kql='host.network.ingress.bytes: *') / 1000)", format: { id: 'bits', params: { @@ -95,13 +95,13 @@ export class RX implements ILensVisualization { negate: false, alias: null, index: '3be1e71b-4bc5-4462-a314-04539f877a19', - key: 'system.network.in.bytes', + key: 'host.network.ingress.bytes', value: 'exists', type: 'exists', }, query: { exists: { - field: 'system.network.in.bytes', + field: 'host.network.ingress.bytes', }, }, $state: { diff --git a/x-pack/plugins/infra/public/common/visualizations/lens/hosts/tx.ts b/x-pack/plugins/infra/public/common/visualizations/lens/hosts/tx.ts index da5e4635d55ca..236efed938046 100644 --- a/x-pack/plugins/infra/public/common/visualizations/lens/hosts/tx.ts +++ b/x-pack/plugins/infra/public/common/visualizations/lens/hosts/tx.ts @@ -54,8 +54,7 @@ export class TX implements ILensVisualization { 'y_network_out_bytes', { formula: - "counter_rate(max(system.network.out.bytes), kql='system.network.out.bytes: *') * 8", - timeScale: 's', + "average(host.network.egress.bytes) * 8 / (max(metricset.period, kql='host.network.egress.bytes: *') / 1000)", format: { id: 'bits', params: { @@ -96,13 +95,13 @@ export class TX implements ILensVisualization { negate: false, alias: null, index: '3be1e71b-4bc5-4462-a314-04539f877a19', - key: 'system.network.out.bytes', + key: 'host.network.egress.bytes', value: 'exists', type: 'exists', }, query: { exists: { - field: 'system.network.out.bytes', + field: 'host.network.egress.bytes', }, }, $state: { diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx index 558a7bac920b7..2db824f9c01d7 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx @@ -163,17 +163,17 @@ export const useHostsTable = (nodes: SnapshotNode[], { time }: HostTableParams) align: 'right', }, { - name: averageTXLabel, - field: 'tx.avg', + name: averageRXLabel, + field: 'rx.avg', sortable: true, - render: (avg: number) => formatMetric('tx', avg), + render: (avg: number) => formatMetric('rx', avg), align: 'right', }, { - name: averageRXLabel, - field: 'rx.avg', + name: averageTXLabel, + field: 'tx.avg', sortable: true, - render: (avg: number) => formatMetric('rx', avg), + render: (avg: number) => formatMetric('tx', avg), align: 'right', }, { From b1ba7e1bb6b370dec5c30729dc674038bb30f6f2 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 28 Feb 2023 07:58:06 -0500 Subject: [PATCH 045/131] [Synthetics] fix alert actions for synthetics monitor status rule (#151900) ## Summary Resolves https://github.com/elastic/kibana/issues/151796 Resolves https://github.com/elastic/kibana/issues/151795 The index alert connector is shared by both legacy uptime and synthetics, but the context shape is different between the two alert types. To account for this a `isLegacy` boolean was added that determines which index connector configuration is used. Additionally, the recovery message was missing when the monitor resolves due to status up. This PR ensures that a recovery message is still populated when the monitor recovers after coming up. Example server log for down monitor ``` [2023-02-22T13:46:04.521-05:00][WARN ][plugins.actions.server-log] Server log: The monitor Badssl checking https://expired.badssl.com/ from US Central QA last ran at February 22, 2023 1:45 PM and is down. The last error received is: error executing step: page.goto: net::ERR_CERT_DATE_INVALID at https://expired.badssl.com/. ``` Example slack message for down monitor Screen Shot 2023-02-22 at 1 47 57 PM Example Example server log for recovery ``` [2023-02-22T13:16:45.058-05:00][INFO ][plugins.actions.server-log] Server log: The alert for the monitor Badssl checking https://expired.badssl.com/ from North America - US Central is no longer active: Monitor has recovered with status Up. ``` Example slack message for recovery Screen Shot 2023-02-22 at 1 18 40 PM Example index document for recovery ``` { "_index": "test3", "_id": "WnZieoYBn2Xs-NzyH0X7", "_score": 1, "_source": { "monitorName": "https://elastic.co", "monitorUrl": "https://elastic.co/", "statusMessage": "up", "latestErrorMessage": "", "observerLocation": "North America - US Central", "recoveryReason": "Monitor has recovered with status Up" } } ``` ``` { "_index": "test3", "_id": "z1RseoYBfB3Am9NRsxsx", "_score": 1, "_source": { "monitorName": "Beep", "monitorUrl": "about:blank", "statusMessage": "down", "latestErrorMessage": "", "observerLocation": "North America - US Central", "recoveryReason": "Location has been removed from the monitor" } } ``` ``` { "_index": "test3", "_id": "rVRreoYBfB3Am9NRvRsu", "_score": 1, "_source": { "monitorName": "TCP monitor", "monitorUrl": "tcp://localhost:5601", "statusMessage": "down", "latestErrorMessage": "", "observerLocation": "North America - US Central", "recoveryReason": "Monitor has been deleted" } }, ``` Testing -- 1. Create a default alert connector on the Synthetics settings page. This issue in particular impacted the `index` connector, so it's recommended to create an index connector. For smoke testing, it's also good to create an server log connector, or a slack connector. 2. Create an always down monitor, and ideally run it against two locations (if using the dev service environment, you can use US Central dev and US Central QA). 3. Wait for the alert to fire 4. Confirm that all your alert connectors are working with all content populated. In particular, query against the index that you are using for the index connector. Confirm that all the fields are populated appropriately in the document. 5. Remove one of the locations from your monitor 6. Wait for the alert for that location to resolve. Confirm that the recovery message for that location was sent to all your connectors. In particular, query against the index that you are using for the index connector. Find the recovery document. Ensure that all the fields are populated appropriately 7. Update the monitor so it now fires as up 8. Wait for the alert to resolve. Confirm that the recovery message for the remaining location was sent to all your alert connectors. In particular, query against the index that you are using for the index connector. Find the recovery document. Ensure that the reason message mentions that the monitor is now up and the status is marked as up. 9. Update the monitor so that it becomes down again 10. Wait for the alert to fire 11. After the alert fires for the down monitor, delete the monitor 12. Wait for the alert to resolve. Confirm that the recovery message was sent to all your alert connectors stating that the alert was resolved because the monitor was deleted. In particular, query against the index that you are using for the index connector. Find the recovery document. Ensure that the reason message mentions that the monitor was deleted. --------- Co-authored-by: Shahzad --- .../common/rules/alert_actions.test.ts | 219 +++++++++++++++++- .../synthetics/common/rules/alert_actions.ts | 51 +++- .../public/legacy_uptime/state/api/alerts.ts | 1 + .../server/alert_rules/common.test.ts | 156 ++++++++++++- .../synthetics/server/alert_rules/common.ts | 11 + .../status_rule/monitor_status_rule.ts | 3 +- 6 files changed, 430 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/synthetics/common/rules/alert_actions.test.ts b/x-pack/plugins/synthetics/common/rules/alert_actions.test.ts index 19fc96ef86cf1..219790bfe991c 100644 --- a/x-pack/plugins/synthetics/common/rules/alert_actions.test.ts +++ b/x-pack/plugins/synthetics/common/rules/alert_actions.test.ts @@ -8,9 +8,11 @@ import { populateAlertActions } from './alert_actions'; import { ActionConnector } from './types'; import { MONITOR_STATUS } from '../constants/uptime_alerts'; +import { MONITOR_STATUS as SYNTHETICS_MONITOR_STATUS } from '../constants/synthetics_alerts'; import { MonitorStatusTranslations } from '../translations'; +import { SyntheticsMonitorStatusTranslations } from './synthetics/translations'; -describe('Alert Actions factory', () => { +describe('Legacy Alert Actions factory', () => { it('generate expected action for pager duty', async () => { const resp = populateAlertActions({ groupId: MONITOR_STATUS.id, @@ -32,6 +34,7 @@ describe('Alert Actions factory', () => { defaultRecoveryMessage: MonitorStatusTranslations.defaultRecoveryMessage, defaultSubjectMessage: MonitorStatusTranslations.defaultSubjectMessage, }, + isLegacy: true, }); expect(resp).toEqual([ { @@ -57,6 +60,66 @@ describe('Alert Actions factory', () => { ]); }); + it('generate expected action for index', async () => { + const resp = populateAlertActions({ + groupId: MONITOR_STATUS.id, + defaultActions: [ + { + actionTypeId: '.index', + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: MonitorStatusTranslations.defaultActionMessage, + }, + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + }, + ] as unknown as ActionConnector[], + translations: { + defaultActionMessage: MonitorStatusTranslations.defaultActionMessage, + defaultRecoveryMessage: MonitorStatusTranslations.defaultRecoveryMessage, + defaultSubjectMessage: MonitorStatusTranslations.defaultSubjectMessage, + }, + isLegacy: true, + }); + expect(resp).toEqual([ + { + group: 'recovered', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + documents: [ + { + latestErrorMessage: '', + monitorName: '{{context.monitorName}}', + monitorUrl: '{{{context.monitorUrl}}}', + observerLocation: '{{context.observerLocation}}', + statusMessage: + 'Alert for monitor {{context.monitorName}} with url {{{context.monitorUrl}}} from {{context.observerLocation}} has recovered', + }, + ], + indexOverride: null, + }, + }, + { + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + documents: [ + { + latestErrorMessage: '{{{context.latestErrorMessage}}}', + monitorName: '{{context.monitorName}}', + monitorUrl: '{{{context.monitorUrl}}}', + observerLocation: '{{context.observerLocation}}', + statusMessage: '{{{context.statusMessage}}}', + }, + ], + indexOverride: null, + }, + }, + ]); + }); + it('generate expected action for slack action connector', async () => { const resp = populateAlertActions({ groupId: MONITOR_STATUS.id, @@ -104,3 +167,157 @@ describe('Alert Actions factory', () => { ]); }); }); + +describe('Alert Actions factory', () => { + it('generate expected action for pager duty', async () => { + const resp = populateAlertActions({ + groupId: SYNTHETICS_MONITOR_STATUS.id, + defaultActions: [ + { + actionTypeId: '.pagerduty', + group: 'xpack.uptime.alerts.actionGroups.monitorStatus', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: SyntheticsMonitorStatusTranslations.defaultActionMessage, + }, + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + }, + ] as unknown as ActionConnector[], + translations: { + defaultActionMessage: SyntheticsMonitorStatusTranslations.defaultActionMessage, + defaultRecoveryMessage: SyntheticsMonitorStatusTranslations.defaultRecoveryMessage, + defaultSubjectMessage: SyntheticsMonitorStatusTranslations.defaultSubjectMessage, + }, + }); + expect(resp).toEqual([ + { + group: 'recovered', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: expect.any(String), + eventAction: 'resolve', + summary: + 'The alert for the monitor {{context.monitorName}} checking {{{context.monitorUrl}}} from {{context.locationName}} is no longer active: {{context.recoveryReason}}.', + }, + }, + { + group: 'xpack.synthetics.alerts.actionGroups.monitorStatus', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: expect.any(String), + eventAction: 'trigger', + severity: 'error', + summary: SyntheticsMonitorStatusTranslations.defaultActionMessage, + }, + }, + ]); + }); + + it('generate expected action for index', async () => { + const resp = populateAlertActions({ + groupId: SYNTHETICS_MONITOR_STATUS.id, + defaultActions: [ + { + actionTypeId: '.index', + group: 'xpack.synthetics.alerts.actionGroups.monitorStatus', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: SyntheticsMonitorStatusTranslations.defaultActionMessage, + }, + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + }, + ] as unknown as ActionConnector[], + translations: { + defaultActionMessage: SyntheticsMonitorStatusTranslations.defaultActionMessage, + defaultRecoveryMessage: SyntheticsMonitorStatusTranslations.defaultRecoveryMessage, + defaultSubjectMessage: SyntheticsMonitorStatusTranslations.defaultSubjectMessage, + }, + }); + expect(resp).toEqual([ + { + group: 'recovered', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + documents: [ + { + latestErrorMessage: '{{{context.latestErrorMessage}}}', + monitorName: '{{context.monitorName}}', + monitorUrl: '{{{context.monitorUrl}}}', + observerLocation: '{{context.locationName}}', + statusMessage: '{{{context.status}}}', + recoveryReason: '{{context.recoveryReason}}', + }, + ], + indexOverride: null, + }, + }, + { + group: 'xpack.synthetics.alerts.actionGroups.monitorStatus', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + documents: [ + { + latestErrorMessage: '{{{context.lastErrorMessage}}}', + monitorName: '{{context.monitorName}}', + monitorUrl: '{{{context.monitorUrl}}}', + observerLocation: '{{context.locationName}}', + statusMessage: '{{{context.status}}}', + }, + ], + indexOverride: null, + }, + }, + ]); + }); + + it('generate expected action for slack action connector', async () => { + const resp = populateAlertActions({ + groupId: SYNTHETICS_MONITOR_STATUS.id, + defaultActions: [ + { + actionTypeId: '.pagerduty', + group: 'xpack.synthetics.alerts.actionGroups.monitorStatus', + params: { + dedupKey: 'always-downxpack.uptime.alerts.actionGroups.monitorStatus', + eventAction: 'trigger', + severity: 'error', + summary: + 'Monitor {{context.monitorName}} with url {{{context.monitorUrl}}} from {{context.observerLocation}} {{{context.statusMessage}}} The latest error message is {{{context.latestErrorMessage}}}', + }, + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + }, + ] as unknown as ActionConnector[], + translations: { + defaultActionMessage: SyntheticsMonitorStatusTranslations.defaultActionMessage, + defaultRecoveryMessage: SyntheticsMonitorStatusTranslations.defaultRecoveryMessage, + defaultSubjectMessage: SyntheticsMonitorStatusTranslations.defaultSubjectMessage, + }, + }); + expect(resp).toEqual([ + { + group: 'recovered', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: expect.any(String), + eventAction: 'resolve', + summary: + 'The alert for the monitor {{context.monitorName}} checking {{{context.monitorUrl}}} from {{context.locationName}} is no longer active: {{context.recoveryReason}}.', + }, + }, + { + group: 'xpack.synthetics.alerts.actionGroups.monitorStatus', + id: 'f2a3b195-ed76-499a-805d-82d24d4eeba9', + params: { + dedupKey: expect.any(String), + eventAction: 'trigger', + severity: 'error', + summary: SyntheticsMonitorStatusTranslations.defaultActionMessage, + }, + }, + ]); + }); +}); diff --git a/x-pack/plugins/synthetics/common/rules/alert_actions.ts b/x-pack/plugins/synthetics/common/rules/alert_actions.ts index 9c32fbdf8d3cf..3f8cedf715536 100644 --- a/x-pack/plugins/synthetics/common/rules/alert_actions.ts +++ b/x-pack/plugins/synthetics/common/rules/alert_actions.ts @@ -43,11 +43,13 @@ export function populateAlertActions({ defaultEmail, groupId, translations, + isLegacy = false, }: { groupId: string; defaultActions: ActionConnector[]; defaultEmail?: DefaultEmail; translations: Translations; + isLegacy?: boolean; }) { const actions: RuleAction[] = []; defaultActions.forEach((aId) => { @@ -78,8 +80,8 @@ export function populateAlertActions({ actions.push(recoveredAction); break; case INDEX_ACTION_ID: - action.params = getIndexActionParams(translations); - recoveredAction.params = getIndexActionParams(translations, true); + action.params = getIndexActionParams(translations, false, isLegacy); + recoveredAction.params = getIndexActionParams(translations, true, isLegacy); actions.push(recoveredAction); break; case SERVICE_NOW_ACTION_ID: @@ -119,8 +121,12 @@ export function populateAlertActions({ return actions; } -function getIndexActionParams(translations: Translations, recovery = false): IndexActionParams { - if (recovery) { +function getIndexActionParams( + translations: Translations, + recovery = false, + isLegacy = false +): IndexActionParams { + if (isLegacy && recovery) { return { documents: [ { @@ -134,14 +140,45 @@ function getIndexActionParams(translations: Translations, recovery = false): Ind indexOverride: null, }; } + + if (isLegacy) { + return { + documents: [ + { + monitorName: '{{context.monitorName}}', + monitorUrl: '{{{context.monitorUrl}}}', + statusMessage: '{{{context.statusMessage}}}', + latestErrorMessage: '{{{context.latestErrorMessage}}}', + observerLocation: '{{context.observerLocation}}', + }, + ], + indexOverride: null, + }; + } + + if (recovery) { + return { + documents: [ + { + monitorName: '{{context.monitorName}}', + monitorUrl: '{{{context.monitorUrl}}}', + statusMessage: '{{{context.status}}}', + latestErrorMessage: '{{{context.latestErrorMessage}}}', + observerLocation: '{{context.locationName}}', + recoveryReason: '{{context.recoveryReason}}', + }, + ], + indexOverride: null, + }; + } return { documents: [ { monitorName: '{{context.monitorName}}', monitorUrl: '{{{context.monitorUrl}}}', - statusMessage: '{{{context.statusMessage}}}', - latestErrorMessage: '{{{context.latestErrorMessage}}}', - observerLocation: '{{context.observerLocation}}', + statusMessage: '{{{context.status}}}', + latestErrorMessage: '{{{context.lastErrorMessage}}}', + observerLocation: '{{context.locationName}}', }, ], indexOverride: null, diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/state/api/alerts.ts b/x-pack/plugins/synthetics/public/legacy_uptime/state/api/alerts.ts index e0f83c917aa8a..33cbac6468306 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/state/api/alerts.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/state/api/alerts.ts @@ -87,6 +87,7 @@ export const createAlert = async ({ defaultRecoveryMessage: MonitorStatusTranslations.defaultRecoveryMessage, defaultSubjectMessage: MonitorStatusTranslations.defaultSubjectMessage, }, + isLegacy: true, }); const data: NewMonitorStatusAlert = { diff --git a/x-pack/plugins/synthetics/server/alert_rules/common.test.ts b/x-pack/plugins/synthetics/server/alert_rules/common.test.ts index 34caffe5fcdd9..6280ebb3fdd5b 100644 --- a/x-pack/plugins/synthetics/server/alert_rules/common.test.ts +++ b/x-pack/plugins/synthetics/server/alert_rules/common.test.ts @@ -4,9 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import { updateState } from './common'; +import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; +import { IBasePath } from '@kbn/core/server'; +import { updateState, setRecoveredAlertsContext } from './common'; import { SyntheticsCommonState } from '../../common/runtime_types/alert_rules/common'; +import { StaleDownConfig } from './status_rule/status_rule_executor'; describe('updateState', () => { let spy: jest.SpyInstance; @@ -180,3 +182,153 @@ describe('updateState', () => { `); }); }); + +describe('setRecoveredAlertsContext', () => { + const { alertFactory } = alertsMock.createRuleExecutorServices(); + const { getRecoveredAlerts } = alertFactory.done(); + const alertUuid = 'alert-id'; + const location = 'US Central'; + const configId = '12345'; + const idWithLocation = `${configId}-${location}`; + const basePath = { + publicBaseUrl: 'https://localhost:5601', + } as IBasePath; + const getAlertUuid = () => alertUuid; + + const upConfigs = { + [idWithLocation]: { + configId, + monitorQueryId: 'stale-config', + status: 'up', + location: '', + ping: { + '@timestamp': new Date().toISOString(), + } as StaleDownConfig['ping'], + timestamp: new Date().toISOString(), + }, + }; + + it('sets context correctly when monitor is deleted', () => { + const setContext = jest.fn(); + getRecoveredAlerts.mockReturnValue([ + { + getId: () => alertUuid, + getState: () => ({ + idWithLocation, + monitorName: 'test-monitor', + }), + setContext, + }, + ]); + const staleDownConfigs = { + [idWithLocation]: { + configId, + monitorQueryId: 'stale-config', + status: 'down', + location: 'location', + ping: { + '@timestamp': new Date().toISOString(), + } as StaleDownConfig['ping'], + timestamp: new Date().toISOString(), + isDeleted: true, + }, + }; + setRecoveredAlertsContext({ + alertFactory, + basePath, + getAlertUuid, + spaceId: 'default', + staleDownConfigs, + upConfigs: {}, + }); + expect(setContext).toBeCalledWith({ + idWithLocation, + alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id', + monitorName: 'test-monitor', + recoveryReason: 'Monitor has been deleted', + }); + }); + + it('sets context correctly when location is removed', () => { + const setContext = jest.fn(); + getRecoveredAlerts.mockReturnValue([ + { + getId: () => alertUuid, + getState: () => ({ + idWithLocation, + monitorName: 'test-monitor', + }), + setContext, + }, + ]); + const staleDownConfigs = { + [idWithLocation]: { + configId, + monitorQueryId: 'stale-config', + status: 'down', + location: 'location', + ping: { + '@timestamp': new Date().toISOString(), + } as StaleDownConfig['ping'], + timestamp: new Date().toISOString(), + isLocationRemoved: true, + }, + }; + setRecoveredAlertsContext({ + alertFactory, + basePath, + getAlertUuid, + spaceId: 'default', + staleDownConfigs, + upConfigs: {}, + }); + expect(setContext).toBeCalledWith({ + idWithLocation, + alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id', + monitorName: 'test-monitor', + recoveryReason: 'Location has been removed from the monitor', + }); + }); + + it('sets context correctly when monitor is up', () => { + const setContext = jest.fn(); + getRecoveredAlerts.mockReturnValue([ + { + getId: () => alertUuid, + getState: () => ({ + idWithLocation, + monitorName: 'test-monitor', + }), + setContext, + }, + ]); + const staleDownConfigs = { + [idWithLocation]: { + configId, + monitorQueryId: 'stale-config', + status: 'down', + location: 'location', + ping: { + '@timestamp': new Date().toISOString(), + } as StaleDownConfig['ping'], + timestamp: new Date().toISOString(), + isLocationRemoved: true, + }, + }; + setRecoveredAlertsContext({ + alertFactory, + basePath, + getAlertUuid, + spaceId: 'default', + staleDownConfigs, + upConfigs, + }); + expect(setContext).toBeCalledWith({ + idWithLocation, + alertDetailsUrl: 'https://localhost:5601/app/observability/alerts/alert-id', + monitorName: 'test-monitor', + status: 'up', + recoveryReason: 'Monitor has recovered with status Up', + }); + }); +}); diff --git a/x-pack/plugins/synthetics/server/alert_rules/common.ts b/x-pack/plugins/synthetics/server/alert_rules/common.ts index 2b629e865a115..e12e85bf82ee2 100644 --- a/x-pack/plugins/synthetics/server/alert_rules/common.ts +++ b/x-pack/plugins/synthetics/server/alert_rules/common.ts @@ -80,12 +80,14 @@ export const setRecoveredAlertsContext = ({ getAlertUuid, spaceId, staleDownConfigs, + upConfigs, }: { alertFactory: RuleExecutorServices['alertFactory']; basePath?: IBasePath; getAlertUuid?: (alertId: string) => string | null; spaceId?: string; staleDownConfigs: AlertOverviewStatus['staleDownConfigs']; + upConfigs: AlertOverviewStatus['upConfigs']; }) => { const { getRecoveredAlerts } = alertFactory.done(); for (const alert of getRecoveredAlerts()) { @@ -95,6 +97,7 @@ export const setRecoveredAlertsContext = ({ const state = alert.getState() as SyntheticsCommonState; let recoveryReason = ''; + let isUp = false; if (state?.idWithLocation && staleDownConfigs[state.idWithLocation]) { const { idWithLocation } = state; @@ -110,8 +113,16 @@ export const setRecoveredAlertsContext = ({ } } + if (state?.idWithLocation && upConfigs[state.idWithLocation]) { + isUp = Boolean(upConfigs[state.idWithLocation]) || false; + recoveryReason = i18n.translate('xpack.synthetics.alerts.monitorStatus.upCheck', { + defaultMessage: `Monitor has recovered with status Up`, + }); + } + alert.setContext({ ...state, + ...(isUp ? { status: 'up' } : {}), ...(recoveryReason ? { [RECOVERY_REASON]: recoveryReason } : {}), ...(basePath && spaceId && alertUuid ? { [ALERT_DETAILS_URL]: getAlertDetailsUrl(basePath, spaceId, alertUuid) } diff --git a/x-pack/plugins/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts b/x-pack/plugins/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts index 7d309c1f595aa..e1719c1e84b93 100644 --- a/x-pack/plugins/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts +++ b/x-pack/plugins/synthetics/server/alert_rules/status_rule/monitor_status_rule.ts @@ -84,7 +84,7 @@ export const registerSyntheticsStatusCheckRule = ( syntheticsMonitorClient ); - const { downConfigs, staleDownConfigs } = await statusRule.getDownChecks( + const { downConfigs, staleDownConfigs, upConfigs } = await statusRule.getDownChecks( ruleState.meta?.downConfigs as OverviewStatus['downConfigs'] ); @@ -129,6 +129,7 @@ export const registerSyntheticsStatusCheckRule = ( getAlertUuid, spaceId, staleDownConfigs, + upConfigs, }); return { From 97e85ac2c4bbfcdf7e7a340cac42565eb64fc2d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20C=C3=B4t=C3=A9?= Date: Tue, 28 Feb 2023 08:06:46 -0500 Subject: [PATCH 046/131] Cleanup maxConcurrency usage and create an allow list for what task types can use it (#151930) Similar to https://github.com/elastic/kibana/pull/144910 In this PR, I'm removing the `maxConcurrency` from the `apm-source-map-migration-task` task types given it only has a single task created for it. The concurrency setting limits how many tasks of such type a single Kibana process should handle at most, and internally requires a separate task claiming query to run every poll interval to claim those tasks. With this PR, task manager goes from running 3 update_by_query requests to 2 every 3 seconds, removing stress put onto Elasticsearch. For more details, see `maxConcurrency` here https://github.com/elastic/kibana/tree/main/x-pack/plugins/task_manager#task-definitions. I've also created an allow list of which task types can set a `maxConcurrency` given the consequences this has on system performance. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../schedule_source_map_migration.ts | 1 - .../plugins/task_manager/server/constants.ts | 10 ++++++++++ .../server/ephemeral_task_lifecycle.test.ts | 4 ++++ .../server/polling_lifecycle.test.ts | 4 ++++ .../server/queries/task_claiming.test.ts | 11 +++++++++++ .../server/task_scheduling.test.ts | 4 ++++ .../server/task_type_dictionary.test.ts | 19 ++++++++++++++++++- .../server/task_type_dictionary.ts | 16 +++++++++++++++- 8 files changed, 66 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/server/routes/source_maps/schedule_source_map_migration.ts b/x-pack/plugins/apm/server/routes/source_maps/schedule_source_map_migration.ts index 08c8a29ef6712..3ab48db456845 100644 --- a/x-pack/plugins/apm/server/routes/source_maps/schedule_source_map_migration.ts +++ b/x-pack/plugins/apm/server/routes/source_maps/schedule_source_map_migration.ts @@ -44,7 +44,6 @@ export async function scheduleSourceMapMigration({ description: `Migrates fleet source map artifacts to "${APM_SOURCE_MAP_INDEX}" index`, timeout: '1h', maxAttempts: 5, - maxConcurrency: 1, createTaskRunner() { const taskState: TaskState = { isAborted: false }; diff --git a/x-pack/plugins/task_manager/server/constants.ts b/x-pack/plugins/task_manager/server/constants.ts index e843a0b4815d1..e9294b25e2859 100644 --- a/x-pack/plugins/task_manager/server/constants.ts +++ b/x-pack/plugins/task_manager/server/constants.ts @@ -5,3 +5,13 @@ * 2.0. */ export const TASK_MANAGER_INDEX = '.kibana_task_manager'; +export const CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE: string[] = [ + // for testing + 'sampleTaskWithSingleConcurrency', + 'sampleTaskWithLimitedConcurrency', + 'timedTaskWithSingleConcurrency', + 'timedTaskWithLimitedConcurrency', + + // task types requiring a concurrency + 'report:execute', +]; diff --git a/x-pack/plugins/task_manager/server/ephemeral_task_lifecycle.test.ts b/x-pack/plugins/task_manager/server/ephemeral_task_lifecycle.test.ts index d6d0881cf0d50..374a52ea84b2f 100644 --- a/x-pack/plugins/task_manager/server/ephemeral_task_lifecycle.test.ts +++ b/x-pack/plugins/task_manager/server/ephemeral_task_lifecycle.test.ts @@ -22,6 +22,10 @@ import { TaskPoolMock } from './task_pool.mock'; import { executionContextServiceMock } from '@kbn/core/server/mocks'; import { taskManagerMock } from './mocks'; +jest.mock('./constants', () => ({ + CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE: ['report'], +})); + const executionContext = executionContextServiceMock.createSetupContract(); describe('EphemeralTaskLifecycle', () => { diff --git a/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts b/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts index f4616b2f8c205..51cac494d3a67 100644 --- a/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts +++ b/x-pack/plugins/task_manager/server/polling_lifecycle.test.ts @@ -31,6 +31,10 @@ jest.mock('./queries/task_claiming', () => { }; }); +jest.mock('./constants', () => ({ + CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE: ['report', 'quickReport'], +})); + describe('TaskPollingLifecycle', () => { let clock: sinon.SinonFakeTimers; const taskManagerLogger = mockLogger(); diff --git a/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts b/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts index d847165bdba9d..6d24e4c0f5987 100644 --- a/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts +++ b/x-pack/plugins/task_manager/server/queries/task_claiming.test.ts @@ -27,6 +27,17 @@ import { taskStoreMock } from '../task_store.mock'; import apm from 'elastic-apm-node'; import { TASK_MANAGER_TRANSACTION_TYPE } from '../task_running'; +jest.mock('../constants', () => ({ + CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE: [ + 'limitedToZero', + 'limitedToOne', + 'anotherLimitedToZero', + 'anotherLimitedToOne', + 'limitedToTwo', + 'limitedToFive', + ], +})); + const taskManagerLogger = mockLogger(); beforeEach(() => jest.clearAllMocks()); diff --git a/x-pack/plugins/task_manager/server/task_scheduling.test.ts b/x-pack/plugins/task_manager/server/task_scheduling.test.ts index 4433a0ad83e8c..7f59f9f362554 100644 --- a/x-pack/plugins/task_manager/server/task_scheduling.test.ts +++ b/x-pack/plugins/task_manager/server/task_scheduling.test.ts @@ -27,6 +27,10 @@ jest.mock('uuid', () => ({ v4: () => 'v4uuid', })); +jest.mock('./constants', () => ({ + CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE: ['foo'], +})); + jest.mock('elastic-apm-node', () => ({ currentTraceparent: 'parent', currentTransaction: { diff --git a/x-pack/plugins/task_manager/server/task_type_dictionary.test.ts b/x-pack/plugins/task_manager/server/task_type_dictionary.test.ts index cb2f436fa8676..039403816da5e 100644 --- a/x-pack/plugins/task_manager/server/task_type_dictionary.test.ts +++ b/x-pack/plugins/task_manager/server/task_type_dictionary.test.ts @@ -14,6 +14,10 @@ import { TaskTypeDictionary, } from './task_type_dictionary'; +jest.mock('./constants', () => ({ + CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE: ['foo'], +})); + interface Opts { numTasks: number; } @@ -182,7 +186,6 @@ describe('taskTypeDictionary', () => { definitions.registerTaskDefinitions({ foo: { title: 'foo', - maxConcurrency: 2, createTaskRunner: jest.fn(), }, }); @@ -209,5 +212,19 @@ describe('taskTypeDictionary', () => { `"Task sampleTaskRemovedType has been removed from registration!"` ); }); + + it(`throws error when setting maxConcurrency to a task type that isn't allowed to set it`, () => { + expect(() => { + definitions.registerTaskDefinitions({ + foo2: { + title: 'foo2', + maxConcurrency: 2, + createTaskRunner: jest.fn(), + }, + }); + }).toThrowErrorMatchingInlineSnapshot( + `"maxConcurrency setting isn't allowed for task type: foo2"` + ); + }); }); }); diff --git a/x-pack/plugins/task_manager/server/task_type_dictionary.ts b/x-pack/plugins/task_manager/server/task_type_dictionary.ts index 9aeafa0a18c7d..3c0e4a0fe5542 100644 --- a/x-pack/plugins/task_manager/server/task_type_dictionary.ts +++ b/x-pack/plugins/task_manager/server/task_type_dictionary.ts @@ -7,6 +7,7 @@ import { Logger } from '@kbn/core/server'; import { TaskDefinition, taskDefinitionSchema, TaskRunCreatorFunction } from './task'; +import { CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE } from './constants'; /** * Types that are no longer registered and will be marked as unregistered @@ -129,12 +130,25 @@ export class TaskTypeDictionary { throw new Error(`Task ${removed} has been removed from registration!`); } + for (const taskType of Object.keys(taskDefinitions)) { + if ( + taskDefinitions[taskType].maxConcurrency !== undefined && + !CONCURRENCY_ALLOW_LIST_BY_TASK_TYPE.includes(taskType) + ) { + // maxConcurrency is designed to limit how many tasks of the same type a single Kibana + // instance should run at a time. Meaning if you have 8 Kibanas running, you will still + // see up to 8 tasks running at a time but one per Kibana instance. This is helpful for + // reporting purposes but not for many other cases and are better off not setting this value. + throw new Error(`maxConcurrency setting isn't allowed for task type: ${taskType}`); + } + } + try { for (const definition of sanitizeTaskDefinitions(taskDefinitions)) { this.definitions.set(definition.type, definition); } } catch (e) { - this.logger.error('Could not sanitize task definitions'); + this.logger.error(`Could not sanitize task definitions: ${e.message}`); } } } From 3d649ef254ae93a06bea2916686fca3a519b89d0 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 28 Feb 2023 07:16:39 -0600 Subject: [PATCH 047/131] [Security solution] Alert Grouping - fix loading issues (#152235) --- .../grouping/accordion_panel/index.test.tsx | 1 + .../grouping/accordion_panel/index.tsx | 3 + .../grouping/container/index.test.tsx | 1 + .../components/grouping/container/index.tsx | 20 +++- .../alerts_table/grouped_alerts.tsx | 82 +++++++------- .../components/alerts_table/index.test.tsx | 104 +++++++++++------- 6 files changed, 132 insertions(+), 79 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.test.tsx index 3da0aefb35895..db78f6f2e9257 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.test.tsx @@ -16,6 +16,7 @@ const ruleName = 'Rule name'; const ruleDesc = 'Rule description'; const testProps = { + isLoading: false, groupBucket: { key: [ruleName, ruleDesc], key_as_string: `${ruleName}|${ruleDesc}`, diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.tsx b/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.tsx index 446b872f3d5f1..548aa81272cd9 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/grouping/accordion_panel/index.tsx @@ -31,6 +31,7 @@ interface GroupPanelProps { forceState?: 'open' | 'closed'; groupBucket: RawBucket; groupPanelRenderer?: JSX.Element; + isLoading: boolean; level?: number; onToggleGroup?: (isOpen: boolean, groupBucket: RawBucket) => void; renderChildComponent: (groupFilter: Filter[]) => React.ReactNode; @@ -56,6 +57,7 @@ const GroupPanelComponent = ({ forceState, groupBucket, groupPanelRenderer, + isLoading, level = 0, onToggleGroup, renderChildComponent, @@ -89,6 +91,7 @@ const GroupPanelComponent = ({ data-test-subj="grouping-accordion" extraAction={extraAction} forceState={forceState} + isLoading={isLoading} id={`group${level}-${groupFieldValue}`} onToggle={onToggle} paddingSize="m" diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx index c74218cf09e80..d9aa2f589c343 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.test.tsx @@ -97,6 +97,7 @@ const testProps = { value: 2, }, }, + isLoading: false, pagination: { pageIndex: 0, pageSize: 25, diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx index e0ddd959d8b8d..9956ba8e40c06 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/grouping/container/index.tsx @@ -5,7 +5,13 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTablePagination } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiProgress, + EuiSpacer, + EuiTablePagination, +} from '@elastic/eui'; import type { Filter } from '@kbn/es-query'; import React, { useMemo, useState } from 'react'; import { firstNonNullValue } from '../../../../../common/endpoint/models/ecs_safety_helpers'; @@ -36,6 +42,7 @@ export interface GroupingContainerProps { groupPanelRenderer?: (fieldBucket: RawBucket) => JSX.Element | undefined; groupsSelector?: JSX.Element; inspectButton?: JSX.Element; + isLoading: boolean; pagination: { pageIndex: number; pageSize: number; @@ -55,6 +62,7 @@ const GroupingContainerComponent = ({ groupPanelRenderer, groupsSelector, inspectButton, + isLoading, pagination, renderChildComponent, selectedGroup, @@ -96,6 +104,7 @@ const GroupingContainerComponent = ({ forceState={(trigger[groupKey] && trigger[groupKey].state) ?? 'closed'} groupBucket={groupBucket} groupPanelRenderer={groupPanelRenderer && groupPanelRenderer(groupBucket)} + isLoading={isLoading} onToggleGroup={(isOpen) => { setTrigger({ // ...trigger, -> this change will keep only one group at a time expanded and one table displayed @@ -121,6 +130,7 @@ const GroupingContainerComponent = ({ customMetricStats, data.stackByMultipleFields0?.buckets, groupPanelRenderer, + isLoading, renderChildComponent, selectedGroup, takeActionItems, @@ -134,6 +144,7 @@ const GroupingContainerComponent = ({ return ( <> ) : ( - + <> + {isLoading && ( + + )} + + )} diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx index 2e4576576dc60..6c5f68d546f97 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/grouped_alerts.tsx @@ -14,7 +14,6 @@ import { v4 as uuidv4 } from 'uuid'; import type { Filter } from '@kbn/es-query'; import { buildEsQuery } from '@kbn/es-query'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; -import type { ReactNode } from 'react-markdown'; import { useGetGroupingSelector } from '../../../common/containers/grouping/hooks/use_get_group_selector'; import type { Status } from '../../../../common/detection_engine/schemas/common'; import { defaultGroup } from '../../../common/store/grouping/defaults'; @@ -68,10 +67,10 @@ interface OwnProps { runtimeMappings: MappingRuntimeFields; signalIndexName: string | null; currentAlertStatusFilterValue?: Status; - renderChildComponent: (groupingFilters: Filter[]) => ReactNode; + renderChildComponent: (groupingFilters: Filter[]) => React.ReactElement; } -type AlertsTableComponentProps = OwnProps & PropsFromRedux; +export type AlertsTableComponentProps = OwnProps & PropsFromRedux; export const GroupedAlertsTableComponent: React.FC = ({ defaultFilters = [], @@ -91,10 +90,10 @@ export const GroupedAlertsTableComponent: React.FC = const dispatch = useDispatch(); const groupingId = tableId; - const getGroupbyIdSelector = groupSelectors.getGroupByIdSelector(); + const getGroupByIdSelector = groupSelectors.getGroupByIdSelector(); const { activeGroup: selectedGroup } = - useSelector((state: State) => getGroupbyIdSelector(state, groupingId)) ?? defaultGroup; + useSelector((state: State) => getGroupByIdSelector(state, groupingId)) ?? defaultGroup; const { browserFields, @@ -237,41 +236,50 @@ export const GroupedAlertsTableComponent: React.FC = [defaultFilters, getGlobalQuery, takeActionItems] ); - if (loading || isLoadingGroups || isEmpty(selectedPatterns)) { + const groupedAlerts = useMemo( + () => + isNoneGroup(selectedGroup) ? ( + renderChildComponent([]) + ) : ( + + getSelectedGroupBadgeMetrics(selectedGroup, fieldBucket) + } + customMetricStats={(fieldBucket: RawBucket) => + getSelectedGroupCustomMetrics(selectedGroup, fieldBucket) + } + data={alertsGroupsData?.aggregations ?? {}} + groupPanelRenderer={(fieldBucket: RawBucket) => + getSelectedGroupButtonContent(selectedGroup, fieldBucket) + } + groupsSelector={groupsSelector} + inspectButton={inspect} + isLoading={loading || isLoadingGroups} + pagination={pagination} + renderChildComponent={renderChildComponent} + selectedGroup={selectedGroup} + takeActionItems={getTakeActionItems} + unit={defaultUnit} + /> + ), + [ + alertsGroupsData?.aggregations, + getTakeActionItems, + groupsSelector, + inspect, + isLoadingGroups, + loading, + pagination, + renderChildComponent, + selectedGroup, + ] + ); + + if (isEmpty(selectedPatterns)) { return null; } - const dataTable = renderChildComponent([]); - - return ( - <> - {isNoneGroup(selectedGroup) ? ( - dataTable - ) : ( - <> - - getSelectedGroupButtonContent(selectedGroup, fieldBucket) - } - badgeMetricStats={(fieldBucket: RawBucket) => - getSelectedGroupBadgeMetrics(selectedGroup, fieldBucket) - } - customMetricStats={(fieldBucket: RawBucket) => - getSelectedGroupCustomMetrics(selectedGroup, fieldBucket) - } - /> - - )} - - ); + return groupedAlerts; }; const makeMapStateToProps = () => { diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx index f2d1c860bf390..8cb24295f62a4 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.test.tsx @@ -6,9 +6,8 @@ */ import React from 'react'; -import { shallow } from 'enzyme'; import { waitFor, render, fireEvent } from '@testing-library/react'; -import type { Filter, Query } from '@kbn/es-query'; +import type { Filter } from '@kbn/es-query'; import useResizeObserver from 'use-resize-observer/polyfilled'; import '../../../common/mock/match_media'; @@ -19,6 +18,7 @@ import { SUB_PLUGINS_REDUCER, TestProviders, } from '../../../common/mock'; +import type { AlertsTableComponentProps } from './grouped_alerts'; import { GroupedAlertsTableComponent } from './grouped_alerts'; import { TableId } from '../../../../common/types'; import { useSourcererDataView } from '../../../common/containers/sourcerer'; @@ -28,8 +28,8 @@ import { mockTimelines } from '../../../common/mock/mock_timelines_plugin'; import { createFilterManagerMock } from '@kbn/data-plugin/public/query/filter_manager/filter_manager.mock'; import type { State } from '../../../common/store'; import { createStore } from '../../../common/store'; -import { AlertsTableComponent } from '.'; import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { defaultGroup } from '../../../common/store/grouping/defaults'; jest.mock('../../../common/containers/sourcerer'); jest.mock('../../../common/containers/use_global_time', () => ({ @@ -149,6 +149,18 @@ const state: State = { const { storage } = createSecuritySolutionStorageMock(); const store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); +const groupingStore = createStore( + { + ...state, + groups: { + groupById: { [`${TableId.test}`]: { ...defaultGroup, activeGroup: 'host.name' } }, + }, + }, + SUB_PLUGINS_REDUCER, + kibanaObservable, + storage +); + jest.mock('./timeline_actions/use_add_bulk_to_timeline', () => ({ useAddBulkToTimelineAction: jest.fn(() => {}), })); @@ -165,52 +177,64 @@ const sourcererDataView = { }, browserFields: {}, }; +const renderChildComponent = (groupingFilters: Filter[]) =>

; -const from = '2020-07-07T08:20:18.966Z'; -const to = '2020-07-08T08:20:18.966Z'; -const renderChildComponent = (groupingFilters: Filter[]) => ( - -); +const testProps: AlertsTableComponentProps = { + defaultFilters: [], + dispatch: jest.fn(), + from: '2020-07-07T08:20:18.966Z', + globalFilters: [], + globalQuery: { + query: 'query', + language: 'language', + }, + hasIndexMaintenance: true, + hasIndexWrite: true, + loading: false, + renderChildComponent, + runtimeMappings: {}, + signalIndexName: 'test', + tableId: TableId.test, + to: '2020-07-08T08:20:18.966Z', +}; describe('GroupedAlertsTable', () => { - (useSourcererDataView as jest.Mock).mockReturnValue({ - ...sourcererDataView, - selectedPatterns: ['myFakebeat-*'], + beforeEach(() => { + jest.clearAllMocks(); + (useSourcererDataView as jest.Mock).mockReturnValue({ + ...sourcererDataView, + selectedPatterns: ['myFakebeat-*'], + }); }); - it('renders correctly', () => { - const wrapper = shallow( + it('renders alerts table when no group selected', () => { + const { getByTestId, queryByTestId } = render( - + ); + expect(getByTestId('alerts-table')).toBeInTheDocument(); + expect(queryByTestId('grouping-table')).not.toBeInTheDocument(); + }); - expect(wrapper.find('[title="Alerts"]')).toBeTruthy(); + it('renders grouped alerts when group selected', () => { + const { getByTestId, queryByTestId } = render( + + + + ); + expect(getByTestId('grouping-table')).toBeInTheDocument(); + expect(queryByTestId('alerts-table')).not.toBeInTheDocument(); + expect(queryByTestId('is-loading-grouping-table')).not.toBeInTheDocument(); + }); + + it('renders loading when expected', () => { + const { getByTestId } = render( + + + + ); + expect(getByTestId('is-loading-grouping-table')).toBeInTheDocument(); }); // Not a valid test as of now.. because, table is used from trigger actions.. From 89dee6db5ee42e66139ee487a3e2b19699412abb Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 28 Feb 2023 07:17:30 -0600 Subject: [PATCH 048/131] [Security solution] Fix alert grouping beta label (#152307) --- .../grouping/groups_selector/index.tsx | 83 ++++++++++--------- .../components/grouping/translations.ts | 37 +++++++-- .../grouping/hooks/use_get_group_selector.tsx | 3 +- 3 files changed, 80 insertions(+), 43 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/groups_selector/index.tsx b/x-pack/plugins/security_solution/public/common/components/grouping/groups_selector/index.tsx index 389645bf549da..81382406d2af4 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/groups_selector/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/grouping/groups_selector/index.tsx @@ -9,18 +9,13 @@ import type { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor, } from '@elastic/eui'; -import { EuiFlexGroup, EuiFlexItem, EuiBetaBadge, EuiPopover } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiPopover } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; import type { FieldSpec } from '@kbn/data-views-plugin/common'; import { CustomFieldPanel } from './custom_field_panel'; -import { GROUP_BY, TECHNICAL_PREVIEW } from '../translations'; +import * as i18n from '../translations'; import { StyledContextMenu, StyledEuiButtonEmpty } from '../styles'; -const none = i18n.translate('xpack.securitySolution.groupsSelector.noneGroupByOptionName', { - defaultMessage: 'None', -}); - interface GroupSelectorProps { fields: FieldSpec[]; groupSelected: string; @@ -34,17 +29,38 @@ const GroupsSelectorComponent = ({ groupSelected = 'none', onGroupChange, options, - title = '', + title = i18n.GROUP_BY, }: GroupSelectorProps) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const panels: EuiContextMenuPanelDescriptor[] = useMemo( () => [ { id: 'firstPanel', + title: ( + + + {i18n.SELECT_FIELD.toUpperCase()} + + + + + + ), items: [ { 'data-test-subj': 'panel-none', - name: none, + name: i18n.NONE, icon: groupSelected === 'none' ? 'check' : 'empty', onClick: () => onGroupChange('none'), }, @@ -56,9 +72,7 @@ const GroupsSelectorComponent = ({ })), { 'data-test-subj': `panel-custom`, - name: i18n.translate('xpack.securitySolution.groupsSelector.customGroupByOptionName', { - defaultMessage: 'Custom field', - }), + name: i18n.CUSTOM_FIELD, icon: 'empty', panel: 'customPanel', }, @@ -66,9 +80,7 @@ const GroupsSelectorComponent = ({ }, { id: 'customPanel', - title: i18n.translate('xpack.securitySolution.groupsSelector.customGroupByPanelTitle', { - defaultMessage: 'Group By Custom Field', - }), + title: i18n.GROUP_BY_CUSTOM_FIELD, width: 685, content: ( 0 ? selectedOption[0].label : none + groupSelected !== 'none' && selectedOption.length > 0 + ? selectedOption[0].label + : i18n.NONE } size="xs" > - {`${title ?? GROUP_BY}: ${ - groupSelected !== 'none' && selectedOption.length > 0 ? selectedOption[0].label : none + {`${title}: ${ + groupSelected !== 'none' && selectedOption.length > 0 + ? selectedOption[0].label + : i18n.NONE }`} ), @@ -114,25 +130,18 @@ const GroupsSelectorComponent = ({ ); return ( - - - - - - - - - - + + + ); }; diff --git a/x-pack/plugins/security_solution/public/common/components/grouping/translations.ts b/x-pack/plugins/security_solution/public/common/components/grouping/translations.ts index 2e73e95b80de5..a9cd9a7d233dc 100644 --- a/x-pack/plugins/security_solution/public/common/components/grouping/translations.ts +++ b/x-pack/plugins/security_solution/public/common/components/grouping/translations.ts @@ -20,13 +20,40 @@ export const TAKE_ACTION = i18n.translate( } ); -export const TECHNICAL_PREVIEW = i18n.translate( - 'xpack.securitySolution.grouping.technicalPreviewLabel', +export const BETA = i18n.translate('xpack.securitySolution.grouping.betaLabel', { + defaultMessage: 'Beta', +}); + +export const BETA_TOOL_TIP = i18n.translate('xpack.securitySolution.grouping.betaToolTip', { + defaultMessage: + 'Grouping may show only a subset of alerts while in beta. To see all alerts, use the list view by selecting "None"', +}); + +export const GROUP_BY = i18n.translate('xpack.securitySolution.selector.grouping.label', { + defaultMessage: 'Group alerts by', +}); + +export const GROUP_BY_CUSTOM_FIELD = i18n.translate( + 'xpack.securitySolution.groupsSelector.customGroupByPanelTitle', { - defaultMessage: 'Technical Preview', + defaultMessage: 'Group By Custom Field', } ); -export const GROUP_BY = i18n.translate('xpack.securitySolution.selector.grouping.label', { - defaultMessage: 'Group by field', +export const SELECT_FIELD = i18n.translate( + 'xpack.securitySolution.groupsSelector.groupByPanelTitle', + { + defaultMessage: 'Select Field', + } +); + +export const NONE = i18n.translate('xpack.securitySolution.groupsSelector.noneGroupByOptionName', { + defaultMessage: 'None', }); + +export const CUSTOM_FIELD = i18n.translate( + 'xpack.securitySolution.groupsSelector.customGroupByOptionName', + { + defaultMessage: 'Custom field', + } +); diff --git a/x-pack/plugins/security_solution/public/common/containers/grouping/hooks/use_get_group_selector.tsx b/x-pack/plugins/security_solution/public/common/containers/grouping/hooks/use_get_group_selector.tsx index aac4305f8518c..0e29b3edba7ab 100644 --- a/x-pack/plugins/security_solution/public/common/containers/grouping/hooks/use_get_group_selector.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/grouping/hooks/use_get_group_selector.tsx @@ -8,6 +8,7 @@ import type { FieldSpec } from '@kbn/data-views-plugin/common'; import React, { useCallback, useEffect, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { GROUP_BY } from '../../../components/grouping/translations'; import type { TableId } from '../../../../../common/types'; import { getDefaultGroupingOptions } from '../../../../detections/components/alerts_table/grouping_settings'; import type { State } from '../../../store'; @@ -101,7 +102,7 @@ export const useGetGroupingSelector = ({ }} fields={fields} options={options} - title={'Group Alerts Selector'} + title={GROUP_BY} /> ), [ From f075e1264d970dfa82f2bc662717c15370c8e056 Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Tue, 28 Feb 2023 14:23:33 +0100 Subject: [PATCH 049/131] [Lens] Improve multiple error messages from formula (#152198) ## Summary Fixes #150114 This PR reduces a tech debt on the user messages side, making formula return a better user message shape. Now multiple errors are rendered as follow, instead of being concatenated: Screenshot 2023-02-27 at 13 01 32 Also, messages are now deduped resulting in a more compact UI, as in this case of wrong type field for 2 inner `sum` functions: Screenshot 2023-02-27 at 13 01 46 ### 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) --- .../definitions/formula/formula.test.tsx | 17 ++++++- .../definitions/formula/formula.tsx | 48 ++++++++++++------- .../definitions/formula/validation.ts | 2 +- 3 files changed, 47 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.test.tsx index 72cca338117da..bc711e7d094c1 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.test.tsx @@ -1520,7 +1520,10 @@ invalid: " operationDefinitionMap ) ).toEqual([ - 'A layer with only static values will not show results, use at least one dynamic metric', + { + message: + 'A layer with only static values will not show results, use at least one dynamic metric', + }, ]); }); @@ -1856,5 +1859,17 @@ invalid: " ).toEqual(undefined); } }); + + it('returns deduped errors on inner operation validation', () => { + expect( + formulaOperation.getErrorMessage!( + getNewLayerWithFormula('sum(clientip) + sum(clientip)', true), + 'col1', + indexPattern, + undefined, + operationDefinitionMap + ) + ).toHaveLength(1); + }); }); }); diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx index 70ccbc5fd25e8..20432dcdb6e24 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/formula.tsx @@ -7,7 +7,11 @@ import { i18n } from '@kbn/i18n'; import { uniqBy } from 'lodash'; -import type { BaseIndexPatternColumn, OperationDefinition } from '..'; +import type { + BaseIndexPatternColumn, + FieldBasedOperationErrorMessage, + OperationDefinition, +} from '..'; import type { ReferenceBasedIndexPatternColumn } from '../column_types'; import type { IndexPattern } from '../../../../../types'; import { runASTValidation, tryToParse } from './validation'; @@ -94,22 +98,30 @@ export const formulaOperation: OperationDefinition { - const def = visibleOperationsMap[col.operationType]; - if (def?.getErrorMessage) { - const messages = def.getErrorMessage( - layer, - id, - indexPattern, - dateRange, - visibleOperationsMap - ); - return messages ? { message: messages.join(', ') } : []; - } - return []; - }) - .filter(nonNullable); + const innerErrors = [ + ...managedColumns + .flatMap(([id, col]) => { + const def = visibleOperationsMap[col.operationType]; + if (def?.getErrorMessage) { + // TOOD: it would be nice to have nicer column names here rather than `Part of ` + const messages = def.getErrorMessage( + layer, + id, + indexPattern, + dateRange, + visibleOperationsMap + ); + return messages || []; + } + return []; + }) + .filter(nonNullable) + // dedup messages with the same content + .reduce((memo, message) => { + memo.add(message); + return memo; + }, new Set()), + ]; const hasBuckets = layer.columnOrder.some((colId) => layer.columns[colId].isBucketed); const hasOtherMetrics = layer.columnOrder.some((colId) => { const col = layer.columns[colId]; @@ -135,7 +147,7 @@ export const formulaOperation: OperationDefinition message) : undefined; + return innerErrors.length ? innerErrors : undefined; }, getPossibleOperation() { return { diff --git a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/validation.ts b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/validation.ts index a8828a9462ddd..520d0f53b143f 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/validation.ts +++ b/x-pack/plugins/lens/public/datasources/form_based/operations/definitions/formula/validation.ts @@ -512,7 +512,7 @@ function checkMissingVariableOrFunctions( }, locations: missingVariables.map(({ location }) => location), }), - extraInfo: { missingFields: missingVariables.map(({ value }) => value) }, + extraInfo: { missingFields: [...new Set(missingVariables.map(({ value }) => value))] }, }); } const invalidVariableErrors = checkVariableEdgeCases( From a799a8553302eef668b54d86d160f6d1de240136 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 28 Feb 2023 08:35:25 -0500 Subject: [PATCH 050/131] feat(slo): Add filter query into APM indicator types (#152273) --- .../apm_availability_indicator_type_form.tsx | 23 ++++++++++++++++--- .../field_selector.stories.tsx | 2 +- .../{common => apm_common}/field_selector.tsx | 0 .../apm_latency_indicator_type_form.tsx | 23 ++++++++++++++++--- .../query_builder.stories.tsx | 0 .../{custom_kql => common}/query_builder.tsx | 0 .../custom_kql_indicator_type_form.tsx | 2 +- 7 files changed, 42 insertions(+), 8 deletions(-) rename x-pack/plugins/observability/public/pages/slo_edit/components/{common => apm_common}/field_selector.stories.tsx (95%) rename x-pack/plugins/observability/public/pages/slo_edit/components/{common => apm_common}/field_selector.tsx (100%) rename x-pack/plugins/observability/public/pages/slo_edit/components/{custom_kql => common}/query_builder.stories.tsx (100%) rename x-pack/plugins/observability/public/pages/slo_edit/components/{custom_kql => common}/query_builder.tsx (100%) diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx index c24bf74dc6346..e61e1c7056596 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_availability/apm_availability_indicator_type_form.tsx @@ -18,10 +18,11 @@ import { i18n } from '@kbn/i18n'; import type { CreateSLOInput } from '@kbn/slo-schema'; import { useFetchApmIndex } from '../../../../hooks/slo/use_fetch_apm_indices'; -import { FieldSelector } from '../common/field_selector'; +import { FieldSelector } from '../apm_common/field_selector'; +import { QueryBuilder } from '../common/query_builder'; export function ApmAvailabilityIndicatorTypeForm() { - const { control, setValue } = useFormContext(); + const { control, setValue, watch } = useFormContext(); const { data: apmIndex } = useFetchApmIndex(); useEffect(() => { setValue('indicator.params.index', apmIndex); @@ -145,7 +146,23 @@ export function ApmAvailabilityIndicatorTypeForm() { )} /> - + + + ); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_common/field_selector.stories.tsx similarity index 95% rename from x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.stories.tsx rename to x-pack/plugins/observability/public/pages/slo_edit/components/apm_common/field_selector.stories.tsx index 748b53ca82d57..47111ee1c565b 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_common/field_selector.stories.tsx @@ -15,7 +15,7 @@ import { SLO_EDIT_FORM_DEFAULT_VALUES } from '../../constants'; export default { component: Component, - title: 'app/SLO/EditPage/Common/FieldSelector', + title: 'app/SLO/EditPage/ApmCommon/FieldSelector', decorators: [KibanaReactStorybookDecorator], }; diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_common/field_selector.tsx similarity index 100% rename from x-pack/plugins/observability/public/pages/slo_edit/components/common/field_selector.tsx rename to x-pack/plugins/observability/public/pages/slo_edit/components/apm_common/field_selector.tsx diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx index 4dcf095571c4a..a5f39a0f8f958 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/apm_latency/apm_latency_indicator_type_form.tsx @@ -12,10 +12,11 @@ import { i18n } from '@kbn/i18n'; import type { CreateSLOInput } from '@kbn/slo-schema'; import { useFetchApmIndex } from '../../../../hooks/slo/use_fetch_apm_indices'; -import { FieldSelector } from '../common/field_selector'; +import { FieldSelector } from '../apm_common/field_selector'; +import { QueryBuilder } from '../common/query_builder'; export function ApmLatencyIndicatorTypeForm() { - const { control, setValue } = useFormContext(); + const { control, setValue, watch } = useFormContext(); const { data: apmIndex } = useFetchApmIndex(); useEffect(() => { setValue('indicator.params.index', apmIndex); @@ -113,7 +114,23 @@ export function ApmLatencyIndicatorTypeForm() { )} /> - + + + ); diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/query_builder.stories.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/query_builder.stories.tsx similarity index 100% rename from x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/query_builder.stories.tsx rename to x-pack/plugins/observability/public/pages/slo_edit/components/common/query_builder.stories.tsx diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/query_builder.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/common/query_builder.tsx similarity index 100% rename from x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/query_builder.tsx rename to x-pack/plugins/observability/public/pages/slo_edit/components/common/query_builder.tsx diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx index d9c39b0715be4..a9fb7cd58e480 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/custom_kql/custom_kql_indicator_type_form.tsx @@ -12,7 +12,7 @@ import { useFormContext } from 'react-hook-form'; import { CreateSLOInput } from '@kbn/slo-schema'; import { IndexSelection } from './index_selection'; -import { QueryBuilder } from './query_builder'; +import { QueryBuilder } from '../common/query_builder'; export function CustomKqlIndicatorTypeForm() { const { control, watch } = useFormContext(); From 2e171759ca4bdd9d7a2c9919bbe02e913eb57188 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Tue, 28 Feb 2023 14:57:57 +0100 Subject: [PATCH 051/131] [CM] Example plugin with server-side registry usage (#151885) ## Summary Close https://github.com/elastic/kibana/issues/152002 In https://github.com/elastic/kibana/pull/151163 we introduced a simple demo todo app run in a storybook with a custom client-side content management client (no server-side cm registry usage). This is a follow-up PR that re-uses the same demo todo app, but also runs it in an example plugin with proper server-side content management registry usage, so now we have a basic end-to-end demonstration of content management capabilities. The demo app is covered by functional tests, so now we also have basic end-to-end test coverage. As this is the first kind of real-world end-to-end usage of the CM APIs, I'd like to use this and [previous](https://github.com/elastic/kibana/pull/151163) prs as a base for the discussion and polishing current APIs. I'll leave a review with comments where I think some API polishing is needed. **Notable changes apart from the example plugin itself:** 1. Move `demo/` todo app and its stories introduced in https://github.com/elastic/kibana/pull/151163 from `src/plugins/content_management` to `examples/content_management_examples`. This was mostly needed to not export `demo/` code on the public plugin export to avoid increasing bundle size. 2. Add needed exports to the plugin contract 3. Reshuffle `common/` to not import `@kbn/schema` client side https://github.com/elastic/kibana/pull/151885/commits/48aa41403b7d248b671511f357878701d5080ae2 4. Fix client-side RPC client to work with the latest server-side changes (shouldn't break from now on because of the end-to-end test coverage) --- .../steps/storybooks/build_and_upload.ts | 2 +- .github/CODEOWNERS | 1 + .../.storybook/main.js | 0 .../content_management_examples/README.md | 3 + .../common/examples/todos/index.ts | 9 ++ .../common/examples/todos/todos.ts | 63 ++++++++ .../jest.config.js | 13 ++ .../content_management_examples/kibana.jsonc | 15 ++ .../public/examples/index.tsx | 31 ++++ .../public/examples/todos/index.tsx | 9 ++ .../todos/stories}/todo.stories.test.tsx | 0 .../examples/todos/stories}/todo.stories.tsx | 5 +- .../examples/todos/stories}/todos_client.ts | 42 ++--- .../public/examples/todos/todo_app.tsx | 19 +++ .../public/examples/todos}/todos.tsx | 41 +++-- .../public/index.ts | 13 ++ .../public/plugin.ts | 42 +++++ .../public/types.ts | 22 +++ .../server/examples/todos/index.ts | 9 ++ .../server/examples/todos/todos.ts | 147 ++++++++++++++++++ .../server/index.ts | 14 ++ .../server/plugin.ts | 26 ++++ .../server/types.ts | 20 +++ .../content_management_examples/tsconfig.json | 24 +++ package.json | 1 + src/dev/storybook/aliases.ts | 2 +- .../content_management/common/constants.ts | 2 +- .../content_management/common/index.ts | 5 +- .../content_management/common/schemas.ts | 11 ++ .../content_management/public/index.ts | 12 ++ .../content_management/public/plugin.ts | 20 ++- .../public/rpc_client/rpc_client.test.ts | 2 +- .../public/rpc_client/rpc_client.ts | 24 ++- .../content_management/server/core/crud.ts | 9 +- .../content_management/server/index.ts | 1 + .../server/rpc/procedures/bulk_get.ts | 2 +- .../server/rpc/procedures/create.ts | 2 +- .../server/rpc/procedures/delete.ts | 2 +- .../server/rpc/procedures/get.ts | 2 +- .../server/rpc/procedures/search.ts | 2 +- .../server/rpc/procedures/update.ts | 2 +- .../content_management/server/types.ts | 4 +- src/plugins/content_management/tsconfig.json | 2 +- test/examples/config.js | 1 + test/examples/content_management/index.ts | 16 ++ test/examples/content_management/todo_app.ts | 72 +++++++++ tsconfig.base.json | 2 + yarn.lock | 10 +- 48 files changed, 706 insertions(+), 72 deletions(-) rename {src/plugins/content_management => examples/content_management_examples}/.storybook/main.js (100%) create mode 100644 examples/content_management_examples/README.md create mode 100644 examples/content_management_examples/common/examples/todos/index.ts create mode 100644 examples/content_management_examples/common/examples/todos/todos.ts create mode 100644 examples/content_management_examples/jest.config.js create mode 100644 examples/content_management_examples/kibana.jsonc create mode 100644 examples/content_management_examples/public/examples/index.tsx create mode 100644 examples/content_management_examples/public/examples/todos/index.tsx rename {src/plugins/content_management/demo/todo => examples/content_management_examples/public/examples/todos/stories}/todo.stories.test.tsx (100%) rename {src/plugins/content_management/demo/todo => examples/content_management_examples/public/examples/todos/stories}/todo.stories.tsx (88%) rename {src/plugins/content_management/demo/todo => examples/content_management_examples/public/examples/todos/stories}/todos_client.ts (62%) create mode 100644 examples/content_management_examples/public/examples/todos/todo_app.tsx rename {src/plugins/content_management/demo/todo => examples/content_management_examples/public/examples/todos}/todos.tsx (80%) create mode 100644 examples/content_management_examples/public/index.ts create mode 100644 examples/content_management_examples/public/plugin.ts create mode 100644 examples/content_management_examples/public/types.ts create mode 100644 examples/content_management_examples/server/examples/todos/index.ts create mode 100644 examples/content_management_examples/server/examples/todos/todos.ts create mode 100644 examples/content_management_examples/server/index.ts create mode 100644 examples/content_management_examples/server/plugin.ts create mode 100644 examples/content_management_examples/server/types.ts create mode 100644 examples/content_management_examples/tsconfig.json create mode 100644 src/plugins/content_management/common/schemas.ts create mode 100644 test/examples/content_management/index.ts create mode 100644 test/examples/content_management/todo_app.ts diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.ts b/.buildkite/scripts/steps/storybooks/build_and_upload.ts index fbe8daee88370..949cb0a0ff534 100644 --- a/.buildkite/scripts/steps/storybooks/build_and_upload.ts +++ b/.buildkite/scripts/steps/storybooks/build_and_upload.ts @@ -19,7 +19,7 @@ const STORYBOOKS = [ 'cloud_chat', 'coloring', 'chart_icons', - 'content_management_plugin', + 'content_management_examples', 'controls', 'custom_integrations', 'dashboard_enhanced', diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3d67d466db782..27a7f01ec78e9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -83,6 +83,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 +examples/content_management_examples @elastic/appex-sharedux src/plugins/content_management @elastic/appex-sharedux packages/content-management/table_list @elastic/appex-sharedux examples/controls_example @elastic/kibana-presentation diff --git a/src/plugins/content_management/.storybook/main.js b/examples/content_management_examples/.storybook/main.js similarity index 100% rename from src/plugins/content_management/.storybook/main.js rename to examples/content_management_examples/.storybook/main.js diff --git a/examples/content_management_examples/README.md b/examples/content_management_examples/README.md new file mode 100644 index 0000000000000..a4b0486903dba --- /dev/null +++ b/examples/content_management_examples/README.md @@ -0,0 +1,3 @@ +# Content Management Examples + +An example plugin that shows how to integrate with the Kibana "content management" plugin. diff --git a/examples/content_management_examples/common/examples/todos/index.ts b/examples/content_management_examples/common/examples/todos/index.ts new file mode 100644 index 0000000000000..9ef986ec2032f --- /dev/null +++ b/examples/content_management_examples/common/examples/todos/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 * from './todos'; diff --git a/examples/content_management_examples/common/examples/todos/todos.ts b/examples/content_management_examples/common/examples/todos/todos.ts new file mode 100644 index 0000000000000..0371651c128f9 --- /dev/null +++ b/examples/content_management_examples/common/examples/todos/todos.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { schema } from '@kbn/config-schema'; +import { + CreateIn, + DeleteIn, + GetIn, + SearchIn, + UpdateIn, +} from '@kbn/content-management-plugin/common'; + +export const TODO_CONTENT_ID = 'todos'; +export interface Todo { + id: string; + title: string; + completed: boolean; +} +const todoSchema = schema.object({ + id: schema.string(), + title: schema.string(), + completed: schema.boolean(), +}); + +export type TodoCreateIn = CreateIn<'todos', { title: string }>; +export type TodoCreateOut = Todo; // TODO: Is this correct? +export const createInSchema = schema.object({ title: schema.string() }); +export const createOutSchema = todoSchema; + +export type TodoUpdateIn = UpdateIn<'todos', Partial>>; +export type TodoUpdateOut = Todo; +export const updateInSchema = schema.object({ + title: schema.maybe(schema.string()), + completed: schema.maybe(schema.boolean()), +}); +export const updateOutSchema = todoSchema; + +export type TodoDeleteIn = DeleteIn<'todos', { id: string }>; +export type TodoDeleteOut = void; + +export type TodoGetIn = GetIn<'todos'>; +export type TodoGetOut = Todo; +export const getOutSchema = todoSchema; + +export type TodoSearchIn = SearchIn<'todos', { filter?: 'todo' | 'completed' }>; +export interface TodoSearchOut { + hits: Todo[]; +} +export const searchInSchema = schema.object({ + filter: schema.maybe( + schema.oneOf([schema.literal('todo'), schema.literal('completed')], { + defaultValue: undefined, + }) + ), +}); +export const searchOutSchema = schema.object({ + hits: schema.arrayOf(todoSchema), +}); diff --git a/examples/content_management_examples/jest.config.js b/examples/content_management_examples/jest.config.js new file mode 100644 index 0000000000000..9f84c97053475 --- /dev/null +++ b/examples/content_management_examples/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../..', + roots: ['/examples/content_management_examples'], +}; diff --git a/examples/content_management_examples/kibana.jsonc b/examples/content_management_examples/kibana.jsonc new file mode 100644 index 0000000000000..24759d7abdfb6 --- /dev/null +++ b/examples/content_management_examples/kibana.jsonc @@ -0,0 +1,15 @@ +{ + "type": "plugin", + "id": "@kbn/content-management-examples-plugin", + "owner": "@elastic/appex-sharedux", + "description": "Example plugin integrating with content management plugin", + "plugin": { + "id": "contentManagementExamples", + "server": true, + "browser": true, + "requiredPlugins": [ + "contentManagement", + "developerExamples" + ] + } +} diff --git a/examples/content_management_examples/public/examples/index.tsx b/examples/content_management_examples/public/examples/index.tsx new file mode 100644 index 0000000000000..715f3a6809581 --- /dev/null +++ b/examples/content_management_examples/public/examples/index.tsx @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { EuiPageTemplate } from '@elastic/eui'; +import { AppMountParameters, CoreStart } from '@kbn/core/public'; +import { StartDeps } from '../types'; +import { TodoApp } from './todos'; + +export const renderApp = ( + { notifications }: CoreStart, + { contentManagement }: StartDeps, + { element }: AppMountParameters +) => { + ReactDOM.render( + + + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/examples/content_management_examples/public/examples/todos/index.tsx b/examples/content_management_examples/public/examples/todos/index.tsx new file mode 100644 index 0000000000000..dd19feb3e0a80 --- /dev/null +++ b/examples/content_management_examples/public/examples/todos/index.tsx @@ -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 { TodoApp } from './todo_app'; diff --git a/src/plugins/content_management/demo/todo/todo.stories.test.tsx b/examples/content_management_examples/public/examples/todos/stories/todo.stories.test.tsx similarity index 100% rename from src/plugins/content_management/demo/todo/todo.stories.test.tsx rename to examples/content_management_examples/public/examples/todos/stories/todo.stories.test.tsx diff --git a/src/plugins/content_management/demo/todo/todo.stories.tsx b/examples/content_management_examples/public/examples/todos/stories/todo.stories.tsx similarity index 88% rename from src/plugins/content_management/demo/todo/todo.stories.tsx rename to examples/content_management_examples/public/examples/todos/stories/todo.stories.tsx index 23cd2a194cf6d..5b7b8f1e23823 100644 --- a/src/plugins/content_management/demo/todo/todo.stories.tsx +++ b/examples/content_management_examples/public/examples/todos/stories/todo.stories.tsx @@ -7,8 +7,9 @@ */ import * as React from 'react'; -import { Todos } from './todos'; -import { ContentClientProvider, ContentClient } from '../../public/content_client'; +import { ContentClientProvider, ContentClient } from '@kbn/content-management-plugin/public'; + +import { Todos } from '../todos'; import { TodosClient } from './todos_client'; export default { diff --git a/src/plugins/content_management/demo/todo/todos_client.ts b/examples/content_management_examples/public/examples/todos/stories/todos_client.ts similarity index 62% rename from src/plugins/content_management/demo/todo/todos_client.ts rename to examples/content_management_examples/public/examples/todos/stories/todos_client.ts index c6f5fe4bf5f36..04d1f6fb990ed 100644 --- a/src/plugins/content_management/demo/todo/todos_client.ts +++ b/examples/content_management_examples/public/examples/todos/stories/todos_client.ts @@ -7,28 +7,32 @@ */ import { v4 as uuidv4 } from 'uuid'; -import type { CrudClient } from '../../public/crud_client'; -import type { CreateIn, DeleteIn, GetIn, SearchIn, UpdateIn } from '../../common'; - -export interface Todo { - id: string; - title: string; - completed: boolean; -} - -export type TodoCreateIn = CreateIn<'todos', { title: string }>; -export type TodoUpdateIn = UpdateIn<'todos', Partial>>; -export type TodoDeleteIn = DeleteIn<'todos', { id: string }>; -export type TodoGetIn = GetIn<'todos'>; -export type TodoSearchIn = SearchIn<'todos', { filter?: 'todo' | 'completed' }>; +import type { CrudClient } from '@kbn/content-management-plugin/public'; +import type { + TodoCreateIn, + TodoUpdateIn, + TodoDeleteIn, + TodoGetIn, + TodoSearchIn, + TodoUpdateOut, + TodoCreateOut, + TodoSearchOut, + TodoDeleteOut, + Todo, + TodoGetOut, +} from '../../../../common/examples/todos'; +/** + * This client is used in the storybook examples to simulate a server-side registry client + * and to show how a content type can have a custom client-side CRUD client without using the server-side registry + */ export class TodosClient implements CrudClient { private todos: Todo[] = [ { id: uuidv4(), title: 'Learn Elasticsearch', completed: true }, { id: uuidv4(), title: 'Learn Kibana', completed: false }, ]; - async create(input: TodoCreateIn): Promise { + async create(input: TodoCreateIn): Promise { const todo = { id: uuidv4(), title: input.data.title, @@ -38,22 +42,22 @@ export class TodosClient implements CrudClient { return todo; } - async delete(input: TodoDeleteIn): Promise { + async delete(input: TodoDeleteIn): Promise { this.todos = this.todos.filter((todo) => todo.id !== input.id); } - async get(input: TodoGetIn): Promise { + async get(input: TodoGetIn): Promise { return this.todos.find((todo) => todo.id === input.id)!; } - async search(input: TodoSearchIn): Promise<{ hits: Todo[] }> { + async search(input: TodoSearchIn): Promise { const filter = input.query.filter; if (filter === 'todo') return { hits: this.todos.filter((t) => !t.completed) }; if (filter === 'completed') return { hits: this.todos.filter((t) => t.completed) }; return { hits: [...this.todos] }; } - async update(input: TodoUpdateIn): Promise { + async update(input: TodoUpdateIn): Promise { const idToUpdate = input.id; const todoToUpdate = this.todos.find((todo) => todo.id === idToUpdate)!; if (todoToUpdate) { diff --git a/examples/content_management_examples/public/examples/todos/todo_app.tsx b/examples/content_management_examples/public/examples/todos/todo_app.tsx new file mode 100644 index 0000000000000..d2fae22bb41a1 --- /dev/null +++ b/examples/content_management_examples/public/examples/todos/todo_app.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { ContentClientProvider, type ContentClient } from '@kbn/content-management-plugin/public'; +import { Todos } from './todos'; + +export const TodoApp = (props: { contentClient: ContentClient }) => { + return ( + + + + ); +}; diff --git a/src/plugins/content_management/demo/todo/todos.tsx b/examples/content_management_examples/public/examples/todos/todos.tsx similarity index 80% rename from src/plugins/content_management/demo/todo/todos.tsx rename to examples/content_management_examples/public/examples/todos/todos.tsx index 667e455029ab4..84c48aa24c88b 100644 --- a/src/plugins/content_management/demo/todo/todos.tsx +++ b/examples/content_management_examples/public/examples/todos/todos.tsx @@ -7,22 +7,32 @@ */ import React from 'react'; import { EuiButtonGroup, EuiButtonIcon, EuiCheckbox, EuiFieldText, EuiSpacer } from '@elastic/eui'; - import { useCreateContentMutation, useDeleteContentMutation, useSearchContentQuery, useUpdateContentMutation, - // eslint-disable-next-line @kbn/imports/no_boundary_crossing -} from '../../public/content_client'; -import type { Todo, TodoCreateIn, TodoDeleteIn, TodoSearchIn, TodoUpdateIn } from './todos_client'; +} from '@kbn/content-management-plugin/public'; + +import { + TODO_CONTENT_ID, + Todo, + TodoCreateIn, + TodoDeleteIn, + TodoSearchIn, + TodoUpdateIn, + TodoUpdateOut, + TodoCreateOut, + TodoSearchOut, + TodoDeleteOut, +} from '../../../common/examples/todos'; -const useCreateTodoMutation = () => useCreateContentMutation(); -const useDeleteTodoMutation = () => useDeleteContentMutation(); -const useUpdateTodoMutation = () => useUpdateContentMutation(); +const useCreateTodoMutation = () => useCreateContentMutation(); +const useDeleteTodoMutation = () => useDeleteContentMutation(); +const useUpdateTodoMutation = () => useUpdateContentMutation(); const useSearchTodosQuery = ({ filter }: { filter: TodoSearchIn['query']['filter'] }) => - useSearchContentQuery({ - contentTypeId: 'todos', + useSearchContentQuery({ + contentTypeId: TODO_CONTENT_ID, query: { filter }, }); @@ -70,14 +80,17 @@ export const Todos = () => {

    {data.hits.map((todo: Todo) => ( -
  • +
  • { updateTodoMutation.mutate({ - contentTypeId: 'todos', + contentTypeId: TODO_CONTENT_ID, id: todo.id, data: { completed: e.target.checked, @@ -85,7 +98,7 @@ export const Todos = () => { }); }} label={todo.title} - data-test-subj={`todoCheckbox-${todo.id}`} + data-test-subj={`todoCheckbox todoCheckbox-${todo.id}`} /> { aria-label="Delete" color="danger" onClick={() => { - deleteTodoMutation.mutate({ contentTypeId: 'todos', id: todo.id }); + deleteTodoMutation.mutate({ contentTypeId: TODO_CONTENT_ID, id: todo.id }); }} />
  • @@ -112,7 +125,7 @@ export const Todos = () => { if (!inputRef || !inputRef.value) return; createTodoMutation.mutate({ - contentTypeId: 'todos', + contentTypeId: TODO_CONTENT_ID, data: { title: inputRef.value, }, diff --git a/examples/content_management_examples/public/index.ts b/examples/content_management_examples/public/index.ts new file mode 100644 index 0000000000000..ba96df2040435 --- /dev/null +++ b/examples/content_management_examples/public/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { ContentManagementExamplesPlugin } from './plugin'; + +export function plugin() { + return new ContentManagementExamplesPlugin(); +} diff --git a/examples/content_management_examples/public/plugin.ts b/examples/content_management_examples/public/plugin.ts new file mode 100644 index 0000000000000..8731ef667650a --- /dev/null +++ b/examples/content_management_examples/public/plugin.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 { AppNavLinkStatus } from '@kbn/core-application-browser'; +import { AppMountParameters, CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; +import { StartDeps, SetupDeps } from './types'; + +export class ContentManagementExamplesPlugin + implements Plugin +{ + public setup(core: CoreSetup, { contentManagement, developerExamples }: SetupDeps) { + developerExamples.register({ + appId: `contentManagementExamples`, + title: `Content Management Examples`, + description: 'Example plugin for the content management plugin', + }); + + core.application.register({ + id: `contentManagementExamples`, + title: `Content Management Examples`, + navLinkStatus: AppNavLinkStatus.hidden, + async mount(params: AppMountParameters) { + const { renderApp } = await import('./examples'); + const [coreStart, deps] = await core.getStartServices(); + return renderApp(coreStart, deps, params); + }, + }); + + return {}; + } + + public start(core: CoreStart) { + return {}; + } + + public stop() {} +} diff --git a/examples/content_management_examples/public/types.ts b/examples/content_management_examples/public/types.ts new file mode 100644 index 0000000000000..83e65c5455afd --- /dev/null +++ b/examples/content_management_examples/public/types.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + ContentManagementPublicSetup, + ContentManagementPublicStart, +} from '@kbn/content-management-plugin/public'; +import { DeveloperExamplesSetup } from '@kbn/developer-examples-plugin/public'; + +export interface SetupDeps { + contentManagement: ContentManagementPublicSetup; + developerExamples: DeveloperExamplesSetup; +} + +export interface StartDeps { + contentManagement: ContentManagementPublicStart; +} diff --git a/examples/content_management_examples/server/examples/todos/index.ts b/examples/content_management_examples/server/examples/todos/index.ts new file mode 100644 index 0000000000000..bf065ba480736 --- /dev/null +++ b/examples/content_management_examples/server/examples/todos/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 { registerTodoContentType } from './todos'; diff --git a/examples/content_management_examples/server/examples/todos/todos.ts b/examples/content_management_examples/server/examples/todos/todos.ts new file mode 100644 index 0000000000000..fe8a7826be655 --- /dev/null +++ b/examples/content_management_examples/server/examples/todos/todos.ts @@ -0,0 +1,147 @@ +/* + * Copyright 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 { + ContentStorage, + StorageContext, + ContentManagementServerSetup, +} from '@kbn/content-management-plugin/server'; +import { v4 } from 'uuid'; +import { + createInSchema, + searchInSchema, + Todo, + TODO_CONTENT_ID, + updateInSchema, + TodoSearchOut, + TodoCreateOut, + TodoUpdateOut, + TodoDeleteOut, + TodoGetOut, + createOutSchema, + getOutSchema, + updateOutSchema, + searchOutSchema, + TodoUpdateIn, + TodoSearchIn, + TodoCreateIn, +} from '../../../common/examples/todos'; + +export const registerTodoContentType = ({ + contentManagement, +}: { + contentManagement: ContentManagementServerSetup; +}) => { + contentManagement.register({ + id: TODO_CONTENT_ID, + schemas: { + content: { + create: { + in: { + data: createInSchema, + }, + out: { + result: createOutSchema, + }, + }, + update: { + in: { + data: updateInSchema, + }, + out: { + result: updateOutSchema, + }, + }, + search: { + in: { + query: searchInSchema, + }, + out: { + result: searchOutSchema, + }, + }, + get: { + out: { + result: getOutSchema, + }, + }, + }, + }, + storage: new TodosStorage(), + }); +}; + +class TodosStorage implements ContentStorage { + private db: Map = new Map(); + + constructor() { + const id1 = v4(); + this.db.set(id1, { + id: id1, + title: 'Learn Elasticsearch', + completed: true, + }); + const id2 = v4(); + this.db.set(id2, { + id: id2, + title: 'Learn Kibana', + completed: false, + }); + } + + async get(ctx: StorageContext, id: string): Promise { + return this.db.get(id)!; + } + + async bulkGet(ctx: StorageContext, ids: string[]): Promise { + return ids.map((id) => this.db.get(id)!); + } + + async create(ctx: StorageContext, data: TodoCreateIn['data']): Promise { + const todo: Todo = { + ...data, + completed: false, + id: v4(), + }; + + this.db.set(todo.id, todo); + + return todo; + } + + async update( + ctx: StorageContext, + id: string, + data: TodoUpdateIn['data'] + ): Promise { + 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); + + return updatedContent; + } + + async delete(ctx: StorageContext, id: string): Promise { + this.db.delete(id); + } + + async search(ctx: StorageContext, query: TodoSearchIn['query']): Promise { + const hits = Array.from(this.db.values()); + if (query.filter === 'todo') return { hits: hits.filter((t) => !t.completed) }; + if (query.filter === 'completed') return { hits: hits.filter((t) => t.completed) }; + return { hits }; + } +} diff --git a/examples/content_management_examples/server/index.ts b/examples/content_management_examples/server/index.ts new file mode 100644 index 0000000000000..d75af7bacf224 --- /dev/null +++ b/examples/content_management_examples/server/index.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 { PluginInitializerContext } from '@kbn/core/server'; +import { ContentManagementExamplesPlugin } from './plugin'; + +export function plugin(initializerContext: PluginInitializerContext) { + return new ContentManagementExamplesPlugin(initializerContext); +} diff --git a/examples/content_management_examples/server/plugin.ts b/examples/content_management_examples/server/plugin.ts new file mode 100644 index 0000000000000..bf66de46e1251 --- /dev/null +++ b/examples/content_management_examples/server/plugin.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/server'; +import type { SetupDeps, StartDeps } from './types'; +import { registerTodoContentType } from './examples/todos'; + +export class ContentManagementExamplesPlugin implements Plugin { + constructor(initializerContext: PluginInitializerContext) {} + + public setup(core: CoreSetup, { contentManagement }: SetupDeps) { + registerTodoContentType({ contentManagement }); + return {}; + } + + public start(core: CoreStart, { contentManagement }: StartDeps) { + return {}; + } + + public stop() {} +} diff --git a/examples/content_management_examples/server/types.ts b/examples/content_management_examples/server/types.ts new file mode 100644 index 0000000000000..57427001461b0 --- /dev/null +++ b/examples/content_management_examples/server/types.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 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 { + ContentManagementServerSetup, + ContentManagementServerStart, +} from '@kbn/content-management-plugin/server'; + +export interface SetupDeps { + contentManagement: ContentManagementServerSetup; +} + +export interface StartDeps { + contentManagement: ContentManagementServerStart; +} diff --git a/examples/content_management_examples/tsconfig.json b/examples/content_management_examples/tsconfig.json new file mode 100644 index 0000000000000..1e899345b0bf4 --- /dev/null +++ b/examples/content_management_examples/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types" + }, + "include": [ + "index.ts", + "common/**/*", + "public/**/*.ts", + "public/**/*.tsx", + "server/**/*.ts", + "../../typings/**/*" + ], + "exclude": [ + "target/**/*", + ], + "kbn_references": [ + "@kbn/core", + "@kbn/developer-examples-plugin", + "@kbn/config-schema", + "@kbn/content-management-plugin", + "@kbn/core-application-browser", + ] +} diff --git a/package.json b/package.json index fcb6cffab0bf0..f091b8dd3073d 100644 --- a/package.json +++ b/package.json @@ -182,6 +182,7 @@ "@kbn/config-schema": "link:packages/kbn-config-schema", "@kbn/console-plugin": "link:src/plugins/console", "@kbn/content-management-content-editor": "link:packages/content-management/content_editor", + "@kbn/content-management-examples-plugin": "link:examples/content_management_examples", "@kbn/content-management-plugin": "link:src/plugins/content_management", "@kbn/content-management-table-list": "link:packages/content-management/table_list", "@kbn/controls-example-plugin": "link:examples/controls_example", diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index fc80a35a2def8..47ebefcc9c8c7 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -18,7 +18,7 @@ export const storybookAliases = { language_documentation_popover: 'packages/kbn-language-documentation-popover/.storybook', chart_icons: 'packages/kbn-chart-icons/.storybook', content_management: 'packages/content-management/.storybook', - content_management_plugin: 'src/plugins/content_management/.storybook', + content_management_examples: 'examples/content_management_examples/.storybook', controls: 'src/plugins/controls/storybook', custom_integrations: 'src/plugins/custom_integrations/storybook', dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/.storybook', diff --git a/src/plugins/content_management/common/constants.ts b/src/plugins/content_management/common/constants.ts index 5c35a41577b82..90298e1729d89 100644 --- a/src/plugins/content_management/common/constants.ts +++ b/src/plugins/content_management/common/constants.ts @@ -8,4 +8,4 @@ export const PLUGIN_ID = 'contentManagement'; -export const API_ENDPOINT = '/api/content_management'; +export const API_ENDPOINT = '/api/content_management/rpc'; diff --git a/src/plugins/content_management/common/index.ts b/src/plugins/content_management/common/index.ts index 0bc6549a1681b..ac944daf3571b 100644 --- a/src/plugins/content_management/common/index.ts +++ b/src/plugins/content_management/common/index.ts @@ -19,4 +19,7 @@ export type { SearchIn, } from './rpc'; -export { procedureNames, schemas as rpcSchemas } from './rpc'; +export { procedureNames } from './rpc/constants'; + +// intentionally not exporting schemas to not include @kbn/schema in the public bundle +// export { schemas as rpcSchemas } from './rpc'; diff --git a/src/plugins/content_management/common/schemas.ts b/src/plugins/content_management/common/schemas.ts new file mode 100644 index 0000000000000..172e0f4b28662 --- /dev/null +++ b/src/plugins/content_management/common/schemas.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. + */ + +// exporting schemas separately from the index.ts file to not include @kbn/schema in the public bundle +// should be only used server-side or in jest tests +export { schemas as rpcSchemas } from './rpc'; diff --git a/src/plugins/content_management/public/index.ts b/src/plugins/content_management/public/index.ts index 0bf75e9d1087a..2687287a36c2f 100644 --- a/src/plugins/content_management/public/index.ts +++ b/src/plugins/content_management/public/index.ts @@ -7,6 +7,18 @@ */ import { ContentManagementPlugin } from './plugin'; +export type { CrudClient } from './crud_client'; +export { + ContentClientProvider, + ContentClient, + useCreateContentMutation, + useUpdateContentMutation, + useDeleteContentMutation, + useSearchContentQuery, + useGetContentQuery, + useContentClient, + type QueryOptions, +} from './content_client'; export function plugin() { return new ContentManagementPlugin(); diff --git a/src/plugins/content_management/public/plugin.ts b/src/plugins/content_management/public/plugin.ts index d82e2fadfb3e6..b2798e4224384 100644 --- a/src/plugins/content_management/public/plugin.ts +++ b/src/plugins/content_management/public/plugin.ts @@ -13,8 +13,9 @@ import { SetupDependencies, StartDependencies, } from './types'; -import type { ContentClient } from './content_client'; -import type { ContentTypeRegistry } from './registry'; +import { ContentClient } from './content_client'; +import { ContentTypeRegistry } from './registry'; +import { RpcClient } from './rpc_client'; export class ContentManagementPlugin implements @@ -26,20 +27,17 @@ export class ContentManagementPlugin > { public setup(core: CoreSetup, deps: SetupDependencies) { - // 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 and the registry until it is used to avoid increasing bundle size - // const rpcClient = new RpcClient(core.http); - // 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 }; + const rpcClient = new RpcClient(core.http); + const contentTypeRegistry = new ContentTypeRegistry(); + const contentClient = new ContentClient( + (contentType) => contentTypeRegistry.get(contentType)?.crud ?? rpcClient + ); + return { client: contentClient, registry: contentTypeRegistry }; } } diff --git a/src/plugins/content_management/public/rpc_client/rpc_client.test.ts b/src/plugins/content_management/public/rpc_client/rpc_client.test.ts index 3a76b355795ed..5e75b45be86ec 100644 --- a/src/plugins/content_management/public/rpc_client/rpc_client.test.ts +++ b/src/plugins/content_management/public/rpc_client/rpc_client.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { procedureNames, API_ENDPOINT } from '../../common'; +import { API_ENDPOINT, procedureNames } from '../../common'; import { RpcClient } from './rpc_client'; 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 2d3e6d1ed1cce..9ec27342d45f2 100644 --- a/src/plugins/content_management/public/rpc_client/rpc_client.ts +++ b/src/plugins/content_management/public/rpc_client/rpc_client.ts @@ -18,36 +18,44 @@ import type { ProcedureName, } from '../../common'; import type { CrudClient } from '../crud_client/crud_client'; +import type { + GetResponse, + BulkGetResponse, + CreateItemResponse, + DeleteItemResponse, + UpdateItemResponse, + SearchResponse, +} from '../../server/core/crud'; export class RpcClient implements CrudClient { constructor(private http: { post: HttpSetup['post'] }) {} public get(input: I): Promise { - return this.sendMessage('get', input); + return this.sendMessage>('get', input).then((r) => r.item); } public bulkGet(input: I): Promise { - return this.sendMessage('bulkGet', input); + return this.sendMessage>('bulkGet', input).then((r) => r.items); } public create(input: I): Promise { - return this.sendMessage('create', input); + return this.sendMessage>('create', input).then((r) => r.result); } public update(input: I): Promise { - return this.sendMessage('update', input); + return this.sendMessage>('update', input).then((r) => r.result); } public delete(input: I): Promise { - return this.sendMessage('delete', input); + return this.sendMessage('delete', input).then((r) => r.result); } public search(input: I): Promise { - return this.sendMessage('search', input); + return this.sendMessage('search', input).then((r) => r.result); } - private sendMessage = async (name: ProcedureName, input: any): Promise => { - const { result } = await this.http.post<{ result: any }>(`${API_ENDPOINT}/${name}`, { + private sendMessage = async (name: ProcedureName, input: any): Promise => { + const { result } = await this.http.post<{ result: O }>(`${API_ENDPOINT}/${name}`, { body: JSON.stringify(input), }); return result; diff --git a/src/plugins/content_management/server/core/crud.ts b/src/plugins/content_management/server/core/crud.ts index cde3af9f2c2a2..1ac35769d0444 100644 --- a/src/plugins/content_management/server/core/crud.ts +++ b/src/plugins/content_management/server/core/crud.ts @@ -10,7 +10,7 @@ import type { ContentStorage, StorageContext } from './types'; export interface GetResponse { contentTypeId: string; - item?: T; + item: T; } export interface BulkGetResponse { @@ -33,6 +33,11 @@ export interface DeleteItemResponse { result: T; } +export interface SearchResponse { + contentTypeId: string; + result: T; +} + export class ContentCrud implements ContentStorage { private storage: ContentStorage; private eventBus: EventBus; @@ -245,7 +250,7 @@ export class ContentCrud implements ContentStorage { ctx: StorageContext, query: Query, options?: Options - ): Promise> { + ): Promise> { this.eventBus.emit({ type: 'searchItemStart', contentTypeId: this.contentTypeId, diff --git a/src/plugins/content_management/server/index.ts b/src/plugins/content_management/server/index.ts index e56a3b845fa93..659b59ed6880c 100644 --- a/src/plugins/content_management/server/index.ts +++ b/src/plugins/content_management/server/index.ts @@ -14,3 +14,4 @@ export function plugin(initializerContext: PluginInitializerContext) { } export type { ContentManagementServerSetup, ContentManagementServerStart } from './types'; +export type { ContentStorage, StorageContext } from './core'; diff --git a/src/plugins/content_management/server/rpc/procedures/bulk_get.ts b/src/plugins/content_management/server/rpc/procedures/bulk_get.ts index ee8c27271abfd..83de5d7fcedf4 100644 --- a/src/plugins/content_management/server/rpc/procedures/bulk_get.ts +++ b/src/plugins/content_management/server/rpc/procedures/bulk_get.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { rpcSchemas } from '../../../common'; +import { rpcSchemas } from '../../../common/schemas'; import type { BulkGetIn } from '../../../common'; import type { StorageContext, ContentCrud } from '../../core'; import type { ProcedureDefinition } from '../rpc_service'; diff --git a/src/plugins/content_management/server/rpc/procedures/create.ts b/src/plugins/content_management/server/rpc/procedures/create.ts index fe2f4e0ab7d16..9ff7a55fe560c 100644 --- a/src/plugins/content_management/server/rpc/procedures/create.ts +++ b/src/plugins/content_management/server/rpc/procedures/create.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { rpcSchemas } from '../../../common'; +import { rpcSchemas } from '../../../common/schemas'; import type { CreateIn } from '../../../common'; import type { StorageContext, ContentCrud } from '../../core'; import type { ProcedureDefinition } from '../rpc_service'; diff --git a/src/plugins/content_management/server/rpc/procedures/delete.ts b/src/plugins/content_management/server/rpc/procedures/delete.ts index c10cc02356beb..6260b54468039 100644 --- a/src/plugins/content_management/server/rpc/procedures/delete.ts +++ b/src/plugins/content_management/server/rpc/procedures/delete.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 { rpcSchemas } from '../../../common'; +import { rpcSchemas } from '../../../common/schemas'; import type { DeleteIn } from '../../../common'; import type { StorageContext, ContentCrud } from '../../core'; import type { ProcedureDefinition } from '../rpc_service'; diff --git a/src/plugins/content_management/server/rpc/procedures/get.ts b/src/plugins/content_management/server/rpc/procedures/get.ts index 73960ad8f3a2f..536263b0e9d15 100644 --- a/src/plugins/content_management/server/rpc/procedures/get.ts +++ b/src/plugins/content_management/server/rpc/procedures/get.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { rpcSchemas } from '../../../common'; +import { rpcSchemas } from '../../../common/schemas'; import type { GetIn } from '../../../common'; import type { ContentCrud, StorageContext } from '../../core'; import { validate } from '../../utils'; diff --git a/src/plugins/content_management/server/rpc/procedures/search.ts b/src/plugins/content_management/server/rpc/procedures/search.ts index 4c9d9a4a9b4c9..c0fa0b2c807dc 100644 --- a/src/plugins/content_management/server/rpc/procedures/search.ts +++ b/src/plugins/content_management/server/rpc/procedures/search.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { rpcSchemas } from '../../../common'; +import { rpcSchemas } from '../../../common/schemas'; import type { SearchIn } from '../../../common'; import type { StorageContext, ContentCrud } from '../../core'; import type { ProcedureDefinition } from '../rpc_service'; diff --git a/src/plugins/content_management/server/rpc/procedures/update.ts b/src/plugins/content_management/server/rpc/procedures/update.ts index 4a9a7951079e5..9ea3b0487d58b 100644 --- a/src/plugins/content_management/server/rpc/procedures/update.ts +++ b/src/plugins/content_management/server/rpc/procedures/update.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 { rpcSchemas } from '../../../common'; +import { rpcSchemas } from '../../../common/schemas'; import type { UpdateIn } from '../../../common'; import type { StorageContext, ContentCrud } from '../../core'; import type { ProcedureDefinition } from '../rpc_service'; diff --git a/src/plugins/content_management/server/types.ts b/src/plugins/content_management/server/types.ts index 0f4cc3138b5e9..3d11f487fbe7d 100644 --- a/src/plugins/content_management/server/types.ts +++ b/src/plugins/content_management/server/types.ts @@ -6,11 +6,13 @@ * Side Public License, v 1. */ +import { CoreApi } from './core'; + // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface SetupDependencies {} // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface ContentManagementServerSetup {} +export interface ContentManagementServerSetup extends CoreApi {} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface ContentManagementServerStart {} diff --git a/src/plugins/content_management/tsconfig.json b/src/plugins/content_management/tsconfig.json index dfdb4b0f93f2a..a5316fbfac1c1 100644 --- a/src/plugins/content_management/tsconfig.json +++ b/src/plugins/content_management/tsconfig.json @@ -3,7 +3,7 @@ "compilerOptions": { "outDir": "target/types", }, - "include": ["common/**/*", "public/**/*", "server/**/*", "demo/**/*"], + "include": ["common/**/*", "public/**/*", "server/**/*"], "kbn_references": [ "@kbn/core", "@kbn/config-schema", diff --git a/test/examples/config.js b/test/examples/config.js index fc57b610941d2..2dce755e413b7 100644 --- a/test/examples/config.js +++ b/test/examples/config.js @@ -28,6 +28,7 @@ export default async function ({ readConfigFile }) { require.resolve('./field_formats'), require.resolve('./partial_results'), require.resolve('./search'), + require.resolve('./content_management'), ], services: { ...functionalConfig.get('services'), diff --git a/test/examples/content_management/index.ts b/test/examples/content_management/index.ts new file mode 100644 index 0000000000000..d5e3f14bfc0e6 --- /dev/null +++ b/test/examples/content_management/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 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 { PluginFunctionalProviderContext } from '../../plugin_functional/services'; + +// eslint-disable-next-line import/no-default-export +export default function ({ loadTestFile }: PluginFunctionalProviderContext) { + describe('content management examples', function () { + loadTestFile(require.resolve('./todo_app')); + }); +} diff --git a/test/examples/content_management/todo_app.ts b/test/examples/content_management/todo_app.ts new file mode 100644 index 0000000000000..5c8228540a2de --- /dev/null +++ b/test/examples/content_management/todo_app.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { Key } from 'selenium-webdriver'; + +import { PluginFunctionalProviderContext } from '../../plugin_functional/services'; + +// eslint-disable-next-line import/no-default-export +export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) { + const testSubjects = getService('testSubjects'); + const find = getService('find'); + const retry = getService('retry'); + const PageObjects = getPageObjects(['common']); + + describe('Todo app', () => { + it('Todo app works', async () => { + const appId = 'contentManagementExamples'; + await PageObjects.common.navigateToApp(appId); + + // check that initial state is correct + let todos = await testSubjects.findAll(`~todoItem`); + expect(todos.length).to.be(2); + + // check that filters work + await (await find.byCssSelector('label[title="Completed"]')).click(); + todos = await testSubjects.findAll(`~todoItem`); + expect(todos.length).to.be(1); + + await (await find.byCssSelector('label[title="Todo"]')).click(); + todos = await testSubjects.findAll(`~todoItem`); + expect(todos.length).to.be(1); + + await (await find.byCssSelector('label[title="All"]')).click(); + todos = await testSubjects.findAll(`~todoItem`); + expect(todos.length).to.be(2); + + // check that adding new todo works + await testSubjects.setValue('newTodo', 'New todo'); + await (await testSubjects.find('newTodo')).pressKeys(Key.ENTER); + await retry.tryForTime(1000, async () => { + todos = await testSubjects.findAll(`~todoItem`); + expect(todos.length).to.be(3); + }); + + // check that updating todo works + let newTodo = todos[2]; + expect(await newTodo.getVisibleText()).to.be('New todo'); + let newTodoCheckbox = await newTodo.findByTestSubject('~todoCheckbox'); + expect(await newTodoCheckbox.isSelected()).to.be(false); + await (await newTodo.findByTagName('label')).click(); + + await (await find.byCssSelector('label[title="Completed"]')).click(); + todos = await testSubjects.findAll(`~todoItem`); + expect(todos.length).to.be(2); + newTodo = todos[1]; + expect(await newTodo.getVisibleText()).to.be('New todo'); + newTodoCheckbox = await newTodo.findByTestSubject('~todoCheckbox'); + expect(await newTodoCheckbox.isSelected()).to.be(true); + + // check that deleting todo works + await (await newTodo.findByCssSelector('[aria-label="Delete"]')).click(); + todos = await testSubjects.findAll(`~todoItem`); + expect(todos.length).to.be(1); + }); + }); +} diff --git a/tsconfig.base.json b/tsconfig.base.json index dd09e8ed627e5..1e8bd1ef0ade0 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -160,6 +160,8 @@ "@kbn/console-plugin/*": ["src/plugins/console/*"], "@kbn/content-management-content-editor": ["packages/content-management/content_editor"], "@kbn/content-management-content-editor/*": ["packages/content-management/content_editor/*"], + "@kbn/content-management-examples-plugin": ["examples/content_management_examples"], + "@kbn/content-management-examples-plugin/*": ["examples/content_management_examples/*"], "@kbn/content-management-plugin": ["src/plugins/content_management"], "@kbn/content-management-plugin/*": ["src/plugins/content_management/*"], "@kbn/content-management-table-list": ["packages/content-management/table_list"], diff --git a/yarn.lock b/yarn.lock index d5aba9da63c76..67ee4aa219a87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3057,6 +3057,10 @@ version "0.0.0" uid "" +"@kbn/content-management-examples-plugin@link:examples/content_management_examples": + version "0.0.0" + uid "" + "@kbn/content-management-plugin@link:src/plugins/content_management": version "0.0.0" uid "" @@ -17589,9 +17593,9 @@ inquirer@^8.2.3: wrap-ansi "^7.0.0" install-artifact-from-github@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.1.tgz#eefaad9af35d632e5d912ad1569c1de38c3c2462" - integrity sha512-3l3Bymg2eKDsN5wQuMfgGEj2x6l5MCAv0zPL6rxHESufFVlEAKW/6oY9F1aGgvY/EgWm5+eWGRjINveL4X7Hgg== + version "1.3.2" + resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.2.tgz#1a16d9508e40330523a3017ae0d4713ccc64de82" + integrity sha512-yCFcLvqk0yQdxx0uJz4t9Z3adDMLAYrcGYv546uRXCSvxE+GqNYhhz/KmrGcUKGI/gVLR9n/e/zM9jX/+ASMJQ== internal-slot@^1.0.3: version "1.0.3" From 808dca85741b5ba01910bf87c6cf94a43b27d8b5 Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Tue, 28 Feb 2023 15:10:12 +0100 Subject: [PATCH 052/131] [Defend Workflows] Osquery Take Action against all agents (#152188) fixes https://github.com/elastic/security-team/issues/6125 --------- Co-authored-by: Tomasz Ciecierski Co-authored-by: Patryk Kopycinski --- .../common/utils/replace_params_query.ts | 4 + .../cypress/e2e/all/add_integration.cy.ts | 27 ++-- .../osquery/cypress/e2e/all/alerts.cy.ts | 23 +++- .../cypress/e2e/all/custom_space.cy.ts | 1 + .../osquery/cypress/e2e/all/live_query.cy.ts | 1 + .../osquery/cypress/e2e/all/metrics.cy.ts | 5 +- .../osquery/cypress/e2e/all/packs.cy.ts | 5 +- .../cypress/e2e/all/saved_queries.cy.ts | 6 +- .../plugins/osquery/cypress/screens/fleet.ts | 1 + .../osquery/cypress/tasks/live_query.ts | 2 +- .../osquery/cypress/tasks/navigation.ts | 3 +- x-pack/plugins/osquery/cypress/tasks/packs.ts | 6 +- .../osquery/cypress/tasks/saved_queries.ts | 8 +- .../handlers/action/create_action_handler.ts | 55 ++++----- .../handlers/action/create_queries.test.ts | 85 +++++++------ .../server/handlers/action/create_queries.ts | 72 ++++------- .../live_query/create_live_query_route.ts | 8 +- x-pack/test/osquery_cypress/agent.ts | 40 +++--- .../test/osquery_cypress/artifact_manager.ts | 2 +- x-pack/test/osquery_cypress/config.ts | 2 + x-pack/test/osquery_cypress/fleet_server.ts | 116 ++++++++---------- x-pack/test/osquery_cypress/runner.ts | 12 +- 22 files changed, 246 insertions(+), 238 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 3c99daf5ec3cf..d06be33a87330 100644 --- a/x-pack/plugins/osquery/common/utils/replace_params_query.ts +++ b/x-pack/plugins/osquery/common/utils/replace_params_query.ts @@ -10,6 +10,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) => { + if (!containsDynamicQuery(query)) { + return { result: query, skipped: false }; + } + const matchedBrackets = query.match(new RegExp(CONTAINS_DYNAMIC_PARAMETER_REGEX)); let resultQuery = query; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts index 35c5c2aa15503..aaf5fc319be15 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts @@ -16,7 +16,7 @@ import { addIntegration, closeModalIfVisible, closeToastIfVisible } from '../../ import { login } from '../../tasks/login'; import { findAndClickButton, findFormFieldByRowsLabelAndType } from '../../tasks/live_query'; import { ArchiverMethod, runKbnArchiverScript } from '../../tasks/archiver'; -import { DEFAULT_POLICY } from '../../screens/fleet'; +import { DEFAULT_POLICY, OSQUERY_POLICY } from '../../screens/fleet'; describe('ALL - Add Integration', () => { const integration = 'Osquery Manager'; @@ -43,11 +43,10 @@ describe('ALL - Add Integration', () => { cy.get('[title="Osquery Manager • Integration"]').should('exist').click(); }); - it('should add the old integration and be able to upgrade it', () => { + it.skip('should add the old integration and be able to upgrade it', () => { const oldVersion = '0.7.4'; cy.visit(OLD_OSQUERY_MANAGER); - cy.contains(integration).click(); addIntegration(); cy.contains('osquery_manager-1'); cy.visit('app/fleet/policies'); @@ -94,11 +93,19 @@ describe('ALL - Add Integration', () => { addIntegration(); cy.contains('osquery_manager-'); closeToastIfVisible(); - cy.getBySel('nav-search-input').type('Osquery'); - cy.get('[title="Osquery • Management"]').should('exist').click(); + cy.visit(OSQUERY); cy.contains('Live queries history'); }); + it(`add integration to ${OSQUERY_POLICY}`, () => { + cy.visit(FLEET_AGENT_POLICIES); + cy.contains(OSQUERY_POLICY).click(); + cy.contains('Add integration').click(); + cy.contains(integration).click(); + addIntegration(OSQUERY_POLICY); + cy.contains('osquery_manager-'); + }); + it('should have integration and packs copied when upgrading integration', () => { const packageName = 'osquery_manager'; const oldVersion = '1.2.0'; @@ -110,12 +117,12 @@ describe('ALL - Add Integration', () => { cy.contains('Upgrade'); cy.contains('Agent policy 1').click(); cy.get('tr') - .should('contain', 'osquery_manager-2') + .should('contain', 'osquery_manager-3') .and('contain', 'Osquery Manager') .and('contain', `v${oldVersion}`); cy.contains('Actions').click(); cy.contains('View policy').click(); - cy.contains('name: osquery_manager-2'); + cy.contains('name: osquery_manager-3'); cy.contains(`version: ${oldVersion}`); cy.get('.euiFlyoutFooter').within(() => { cy.contains('Close').click(); @@ -142,19 +149,19 @@ describe('ALL - Add Integration', () => { cy.contains(/^Advanced$/).click(); cy.contains('"Integration":'); cy.contains(/^Upgrade integration$/).click(); - cy.contains(/^osquery_manager-2$/).click(); + cy.contains(/^osquery_manager-3$/).click(); cy.contains(/^Advanced$/).click(); cy.contains('"Integration":'); cy.contains('Cancel').click(); closeModalIfVisible(); cy.get('tr') - .should('contain', 'osquery_manager-2') + .should('contain', 'osquery_manager-3') .and('contain', 'Osquery Manager') .and('contain', 'v') .and('not.contain', `v${oldVersion}`); cy.contains('Actions').click(); cy.contains('View policy').click(); - cy.contains('name: osquery_manager-2'); + cy.contains('name: osquery_manager-3'); // test list of prebuilt queries navigateTo('/app/osquery/saved_queries'); 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 416fdfe5b971a..2f313d1bb9979 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts.cy.ts @@ -58,7 +58,7 @@ describe('Alert Event Details', () => { it('should prepare packs and alert rules', () => { const PACK_NAME = 'testpack'; - navigateTo('/app/osquery/packs'); + navigateTo('/app/osquery/live_queries'); preparePack(PACK_NAME); findAndClickButton('Edit'); cy.contains(`Edit ${PACK_NAME}`); @@ -439,6 +439,27 @@ describe('Alert Event Details', () => { }); }); + it('should be able to run take action query against all enrolled agents', () => { + loadAlertsEvents(); + cy.getBySel('expand-event').first().click({ force: true }); + cy.getBySel('take-action-dropdown-btn').click(); + cy.getBySel('osquery-action-item').click(); + cy.getBySel('agentSelection').within(() => { + cy.getBySel('comboBoxClearButton').click(); + cy.getBySel('comboBoxInput').type('All{downArrow}{enter}{esc}'); + cy.contains('All agents'); + }); + inputQuery("SELECT * FROM os_version where name='{{host.os.name}}';", { + parseSpecialCharSequences: false, + }); + cy.wait(1000); + submitQuery(); + cy.getBySel('flyout-body-osquery').within(() => { + // at least 2 agents should have responded + cy.get('[data-grid-row-index]').should('have.length.at.least', 2); + }); + }); + it('should substitute params in osquery ran from timelines alerts', () => { loadAlertsEvents(); cy.getBySel('send-alert-to-timeline-button').first().click({ force: true }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts index e58f6c689eb55..3aaeff293ac47 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts @@ -29,6 +29,7 @@ describe('ALL - Custom space', () => { id: CUSTOM_SPACE, name: CUSTOM_SPACE, }, + failOnStatusCode: false, headers: { 'kbn-xsrf': 'create-space' }, }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts index 8991858bd7c26..aa21b6142a9df 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts @@ -68,6 +68,7 @@ describe('ALL - Live Query', () => { checkResults(); cy.react('Cell', { props: { columnIndex: 0 } }) .should('exist') + .first() .click(); cy.url().should('include', 'app/fleet/agents/'); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts index 0edefdc24ea42..998d5220e24f4 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts @@ -29,19 +29,20 @@ describe('ALL - Inventory', () => { cy.wait(1000); - cy.getBySel('nodeContainer').click(); + cy.getBySel('nodeContainer').first().click(); cy.contains('Osquery').click(); inputQuery('select * from uptime;'); submitQuery(); checkResults(); }); + it('should be able to run the previously saved query', () => { cy.getBySel('toggleNavButton').click(); cy.getBySel('collapsibleNavAppLink').contains('Infrastructure').click(); cy.wait(500); - cy.getBySel('nodeContainer').click(); + cy.getBySel('nodeContainer').first().click(); cy.contains('Osquery').click(); cy.getBySel('comboBoxInput').first().click(); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts index d402412dcdbd7..74253324acdfb 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs.cy.ts @@ -476,9 +476,8 @@ describe('ALL - Packs', () => { navigateTo('/app/osquery/packs'); }); - it('add global packs to polciies', () => { + it('add global packs to policies', () => { const globalPack = 'globalPack'; - cy.contains('Packs').click(); findAndClickButton('Add pack'); findFormFieldByRowsLabelAndType('Name', globalPack); cy.getBySel('policyIdsComboBox').should('exist'); @@ -517,9 +516,9 @@ describe('ALL - Packs', () => { cy.contains('rev. 2').click(); }); }); + it('add proper shard to policies packs config', () => { const shardPack = 'shardPack'; - cy.contains('Packs').click(); cy.getBySel('pagination-button-next').click(); findAndClickButton('Add pack'); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts index 9605984969c00..8af212661f741 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts @@ -64,10 +64,12 @@ describe('ALL - Saved queries', () => { cy.contains('Snapshot'); }); }); + describe('prebuilt ', () => { before(() => { runKbnArchiverScript(ArchiverMethod.LOAD, 'pack_with_prebuilt_saved_queries'); }); + beforeEach(() => { navigateTo('/app/osquery/saved_queries'); }); @@ -77,7 +79,6 @@ describe('ALL - Saved queries', () => { }); it('checks result type on prebuilt saved query', () => { - cy.contains('Saved queries').click(); cy.react('CustomItemAction', { props: { index: 1, item: { attributes: { id: 'users_elastic' } } }, }).click(); @@ -85,6 +86,7 @@ describe('ALL - Saved queries', () => { cy.contains('Snapshot'); }); }); + it('user can run prebuilt saved query and add to case', () => { cy.react('PlayButtonComponent', { props: { savedQuery: { attributes: { id: 'users_elastic' } } }, @@ -98,7 +100,6 @@ describe('ALL - Saved queries', () => { }); it('user cant delete prebuilt saved query', () => { - cy.contains('Saved queries').click(); cy.react('CustomItemAction', { props: { index: 1, item: { attributes: { id: 'users_elastic' } } }, }).click(); @@ -114,6 +115,7 @@ describe('ALL - Saved queries', () => { }).click(); deleteAndConfirm('query'); }); + it('user can edit prebuilt saved query under pack', () => { const PACK_NAME = 'pack_with_prebuilt_sq'; preparePack(PACK_NAME); diff --git a/x-pack/plugins/osquery/cypress/screens/fleet.ts b/x-pack/plugins/osquery/cypress/screens/fleet.ts index b7cce6484c405..3f5370126f95f 100644 --- a/x-pack/plugins/osquery/cypress/screens/fleet.ts +++ b/x-pack/plugins/osquery/cypress/screens/fleet.ts @@ -10,3 +10,4 @@ export const ADD_AGENT_BUTTON = 'addAgentButton'; export const AGENT_POLICIES_TAB = 'fleet-agent-policies-tab'; export const ENROLLMENT_TOKENS_TAB = 'fleet-enrollment-tokens-tab'; export const DEFAULT_POLICY = 'Default Fleet Server policy'; +export const OSQUERY_POLICY = 'Osquery policy'; diff --git a/x-pack/plugins/osquery/cypress/tasks/live_query.ts b/x-pack/plugins/osquery/cypress/tasks/live_query.ts index 5e1c474da2d78..c37dbc7766bf4 100644 --- a/x-pack/plugins/osquery/cypress/tasks/live_query.ts +++ b/x-pack/plugins/osquery/cypress/tasks/live_query.ts @@ -17,7 +17,7 @@ export const selectAllAgents = () => { }).click(); cy.react('EuiFilterSelectItem').contains('All agents').should('exist'); cy.react('AgentsTable EuiComboBox').type('{downArrow}{enter}{esc}'); - cy.contains('1 agent selected.'); + cy.contains('2 agents selected.'); }; export const clearInputQuery = () => diff --git a/x-pack/plugins/osquery/cypress/tasks/navigation.ts b/x-pack/plugins/osquery/cypress/tasks/navigation.ts index 7b1505eecd698..9cbd0fac297a2 100644 --- a/x-pack/plugins/osquery/cypress/tasks/navigation.ts +++ b/x-pack/plugins/osquery/cypress/tasks/navigation.ts @@ -6,6 +6,7 @@ */ import { TOGGLE_NAVIGATION_BTN } from '../screens/navigation'; +import { closeToastIfVisible } from './integrations'; export const INTEGRATIONS = 'app/integrations#/'; export const FLEET = 'app/fleet/'; @@ -20,7 +21,7 @@ export const navigateTo = (page: string, opts?: Partial) = cy.contains('Loading Elastic').should('not.exist'); // There's a security warning toast that seemingly makes ui elements in the bottom right unavailable, so we close it - cy.get('[data-test-subj="toastCloseButton"]', { timeout: 30000 }).click(); + closeToastIfVisible(); cy.waitForReact(); }; diff --git a/x-pack/plugins/osquery/cypress/tasks/packs.ts b/x-pack/plugins/osquery/cypress/tasks/packs.ts index 6d74ac2110a0c..80f9a497ef6b4 100644 --- a/x-pack/plugins/osquery/cypress/tasks/packs.ts +++ b/x-pack/plugins/osquery/cypress/tasks/packs.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { closeModalIfVisible } from './integrations'; +import { closeModalIfVisible, closeToastIfVisible } from './integrations'; export const preparePack = (packName: string) => { cy.contains('Packs').click(); @@ -21,7 +21,7 @@ export const deactivatePack = (packName: string) => { cy.contains(`Successfully deactivated "${packName}" pack`).should('not.exist'); cy.contains(`Successfully deactivated "${packName}" pack`).should('exist'); - cy.getBySel('toastCloseButton').click(); + closeToastIfVisible(); }; export const activatePack = (packName: string) => { @@ -32,5 +32,5 @@ export const activatePack = (packName: string) => { cy.contains(`Successfully activated "${packName}" pack`).should('not.exist'); cy.contains(`Successfully activated "${packName}" pack`).should('exist'); - cy.getBySel('toastCloseButton').click(); + closeToastIfVisible(); }; diff --git a/x-pack/plugins/osquery/cypress/tasks/saved_queries.ts b/x-pack/plugins/osquery/cypress/tasks/saved_queries.ts index 7c70d8cdb3a2b..780880b838caf 100644 --- a/x-pack/plugins/osquery/cypress/tasks/saved_queries.ts +++ b/x-pack/plugins/osquery/cypress/tasks/saved_queries.ts @@ -6,6 +6,7 @@ */ import { RESULTS_TABLE_BUTTON } from '../screens/live_query'; +import { closeToastIfVisible } from './integrations'; import { checkResults, BIG_QUERY, @@ -15,6 +16,7 @@ import { selectAllAgents, submitQuery, } from './live_query'; +import { navigateTo } from './navigation'; export const getSavedQueriesComplexTest = (savedQueryId: string, savedQueryDescription: string) => it( @@ -71,7 +73,7 @@ export const getSavedQueriesComplexTest = (savedQueryId: string, savedQueryDescr // visit Status results cy.react('EuiTab', { props: { id: 'status' } }).click(); - cy.react('EuiTableRow').should('have.lengthOf', 1); + cy.react('EuiTableRow').should('have.lengthOf', 2); // save new query cy.contains('Exit full screen').should('not.exist'); @@ -81,10 +83,10 @@ export const getSavedQueriesComplexTest = (savedQueryId: string, savedQueryDescr findFormFieldByRowsLabelAndType('Description (optional)', savedQueryDescription); cy.react('EuiButtonDisplay').contains('Save').click(); cy.contains('Successfully saved'); - cy.getBySel('toastCloseButton').click(); + closeToastIfVisible(); // play saved query - cy.contains('Saved queries').click(); + navigateTo('/app/osquery/saved_queries'); cy.contains(savedQueryId); cy.react('PlayButtonComponent', { props: { savedQuery: { attributes: { id: savedQueryId } } }, 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 4974fc21b440b..b2f6ca09234eb 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 @@ -11,11 +11,7 @@ import { filter, flatten, isEmpty, map, omit, pick, pickBy, some } from 'lodash' import { AGENT_ACTIONS_INDEX } from '@kbn/fleet-plugin/common'; 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 { createDynamicQueries, replacedQueries } from './create_queries'; import { getInternalSavedObjectsClient } from '../../routes/utils'; import { parseAgentSelection } from '../../lib/parse_agent_groups'; import { packSavedObjectType } from '../../../common/types'; @@ -94,16 +90,13 @@ export const createActionHandler = async ( : undefined, queries: packSO ? map(convertSOQueriesToPack(packSO.attributes.queries), (packQuery, packQueryId) => { - const dynamicQueryPresent = packQuery.query && containsDynamicQuery(packQuery.query); + const replacedQuery = replacedQueries(packQuery.query, alertData); return pickBy( { action_id: uuidv4(), id: packQueryId, - query: - dynamicQueryPresent && alertData - ? replaceParamsQuery(packQuery.query, alertData).result - : packQuery.query, + ...replacedQuery, ecs_mapping: packQuery.ecs_mapping, version: packQuery.version, platform: packQuery.platform, @@ -112,9 +105,7 @@ export const createActionHandler = async ( (value) => !isEmpty(value) ); }) - : alertData - ? await createDynamicQueries(params, alertData, osqueryContext) - : await createQueries(params, selectedAgents, osqueryContext), + : await createDynamicQueries({ params, alertData, agents: selectedAgents, osqueryContext }), }; const fleetActions = map( @@ -130,31 +121,33 @@ export const createActionHandler = async ( data: pick(query, ['id', 'query', 'ecs_mapping', 'version', 'platform']), }) ); + if (fleetActions.length) { + await esClientInternal.bulk({ + refresh: 'wait_for', + body: flatten( + fleetActions.map((action) => [{ index: { _index: AGENT_ACTIONS_INDEX } }, action]) + ), + }); - await esClientInternal.bulk({ - refresh: 'wait_for', - body: flatten( - fleetActions.map((action) => [{ index: { _index: AGENT_ACTIONS_INDEX } }, action]) - ), - }); + const actionsComponentTemplateExists = await esClientInternal.indices.exists({ + index: `${ACTIONS_INDEX}*`, + }); - const actionsComponentTemplateExists = await esClientInternal.indices.exists({ - index: `${ACTIONS_INDEX}*`, - }); + if (actionsComponentTemplateExists) { + await esClientInternal.bulk({ + refresh: 'wait_for', + body: [{ index: { _index: `${ACTIONS_INDEX}-default` } }, osqueryAction], + }); + } - if (actionsComponentTemplateExists) { - await esClientInternal.bulk({ - refresh: 'wait_for', - body: [{ index: { _index: `${ACTIONS_INDEX}-default` } }, osqueryAction], + osqueryContext.telemetryEventsSender.reportEvent(TELEMETRY_EBT_LIVE_QUERY_EVENT, { + ...omit(osqueryAction, ['type', 'input_type', 'user_id']), + agents: osqueryAction.agents.length, }); } - osqueryContext.telemetryEventsSender.reportEvent(TELEMETRY_EBT_LIVE_QUERY_EVENT, { - ...omit(osqueryAction, ['type', 'input_type', 'user_id']), - agents: osqueryAction.agents.length, - }); - return { response: osqueryAction, + fleetActionsCount: fleetActions.length, }; }; 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 3b88e710fc52b..4956dfd1245bc 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 @@ -5,7 +5,7 @@ * 2.0. */ -import { createDynamicQueries, createQueries } from './create_queries'; +import { createDynamicQueries, PARAMETER_NOT_FOUND } from './create_queries'; import type { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import type { OsqueryAppContext } from '../../lib/osquery_app_context_services'; @@ -18,6 +18,8 @@ describe('create queries', () => { removed: false, snapshot: true, }; + const TEST_AGENT = 'test-agent'; + const mockedQueriesParams = { queries: [ { @@ -49,69 +51,74 @@ describe('create queries', () => { // Info: getting queries by index (eg. [1], [0]) because can't compare whole query object due to unique action_id generated. describe('dynamic', () => { const pid = 123; - it('if queries length it should return replaced list of queries', async () => { - const queries = await createDynamicQueries( - mockedQueriesParams, - { + it('alertData, multi queries, should replace queries and show errors', async () => { + const queries = await createDynamicQueries({ + params: mockedQueriesParams, + agents: [TEST_AGENT], + alertData: { process: { pid, }, } as unknown as ParsedTechnicalFields, - {} as OsqueryAppContext - ); + osqueryContext: {} as OsqueryAppContext, + }); expect(queries[0].query).toBe(`SELECT * FROM processes where pid=${pid};`); + expect(queries[0].error).toBe(undefined); + expect(queries[1].query).toBe('SELECT * FROM processes where pid={{process.not-existing}};'); expect(queries[1].error).toBe( "This query hasn't been called due to parameter used and its value not found in the alert." ); - expect(queries[1].query).toBe('SELECT * FROM processes where pid={{process.not-existing}};'); expect(queries[2].query).toBe('SELECT * FROM processes;'); + expect(queries[2].error).toBe(undefined); }); - it('if single query it should return one replaced query ', async () => { - const queries = await createDynamicQueries( - mockedSingleQueryParams, - { - process: { - pid, - }, + + it('alertData, single query, existing param should return changed query', async () => { + const queries = await createDynamicQueries({ + params: mockedSingleQueryParams, + agents: [TEST_AGENT], + alertData: { + process: { pid }, } as unknown as ParsedTechnicalFields, - {} as OsqueryAppContext - ); + osqueryContext: {} as OsqueryAppContext, + }); expect(queries[0].query).toBe(`SELECT * FROM processes where pid=${pid};`); + expect(queries[0].error).toBe(undefined); }); - it('if single query with not existing parameter it should return query as it is', async () => { - const queries = await createDynamicQueries( - mockedSingleQueryParams, - { + it('alertData, single query, not existing param should return error', async () => { + const queries = await createDynamicQueries({ + params: mockedSingleQueryParams, + agents: [TEST_AGENT], + alertData: { process: {}, } as unknown as ParsedTechnicalFields, - {} as OsqueryAppContext - ); + osqueryContext: {} as OsqueryAppContext, + }); expect(queries[0].query).toBe('SELECT * FROM processes where pid={{process.pid}};'); - expect(queries[0].error).toBe(undefined); + expect(queries[0].error).toBe(PARAMETER_NOT_FOUND); }); - }); - describe('normal', () => { - const TEST_AGENT = 'test-agent'; - it('if queries length it should return not replaced list of queries with agents', async () => { - const queries = await createQueries( - mockedQueriesParams, - [TEST_AGENT], - {} as OsqueryAppContext - ); + it('no alert data, multi query, return unchanged queries no error', async () => { + const queries = await createDynamicQueries({ + params: mockedQueriesParams, + agents: [TEST_AGENT], + osqueryContext: {} as OsqueryAppContext, + }); expect(queries[0].query).toBe('SELECT * FROM processes where pid={{process.pid}};'); expect(queries[0].agents).toContain(TEST_AGENT); + expect(queries[0].error).toBe(undefined); expect(queries[2].query).toBe('SELECT * FROM processes;'); expect(queries[2].agents).toContain(TEST_AGENT); + expect(queries[2].error).toBe(undefined); }); - it('if single query should return not replaced query with agents', async () => { - const queries = await createQueries( - mockedSingleQueryParams, - [TEST_AGENT], - {} as OsqueryAppContext - ); + it('no alert data, single query, return unchanged query and no error', async () => { + const queries = await createDynamicQueries({ + params: mockedSingleQueryParams, + agents: [TEST_AGENT], + osqueryContext: {} as OsqueryAppContext, + }); expect(queries[0].query).toBe('SELECT * FROM processes where pid={{process.pid}};'); expect(queries[0].agents).toContain(TEST_AGENT); + expect(queries[0].error).toBe(undefined); }); }); }); 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 6551b8252e16b..f7d3601722189 100644 --- a/x-pack/plugins/osquery/server/handlers/action/create_queries.ts +++ b/x-pack/plugins/osquery/server/handlers/action/create_queries.ts @@ -15,47 +15,26 @@ import type { CreateLiveQueryRequestBodySchema } from '../../../common/schemas/r import { replaceParamsQuery } from '../../../common/utils/replace_params_query'; import { isSavedQueryPrebuilt } from '../../routes/saved_query/utils'; -export const createQueries = async ( - params: CreateLiveQueryRequestBodySchema, - agents: string[], - osqueryContext: OsqueryAppContext -) => - params.queries?.length - ? map(params.queries, (query) => - pickBy( - { - ...query, - action_id: uuidv4(), - agents, - }, - (value) => !isEmpty(value) || value === true - ) - ) - : [ - pickBy( - { - action_id: uuidv4(), - id: uuidv4(), - query: params.query, - saved_query_id: params.saved_query_id, - saved_query_prebuilt: params.saved_query_id - ? await isSavedQueryPrebuilt( - osqueryContext.service.getPackageService()?.asInternalUser, - params.saved_query_id - ) - : undefined, - ecs_mapping: params.ecs_mapping, - agents, - }, - (value) => !isEmpty(value) - ), - ]; +export const PARAMETER_NOT_FOUND = i18n.translate( + 'xpack.osquery.liveQueryActions.error.notFoundParameters', + { + defaultMessage: + "This query hasn't been called due to parameter used and its value not found in the alert.", + } +); -export const createDynamicQueries = async ( - params: CreateLiveQueryRequestBodySchema, - alertData: ParsedTechnicalFields, - osqueryContext: OsqueryAppContext -) => +interface CreateDynamicQueriesParams { + params: CreateLiveQueryRequestBodySchema; + alertData?: ParsedTechnicalFields; + agents: string[]; + osqueryContext: OsqueryAppContext; +} +export const createDynamicQueries = async ({ + params, + alertData, + agents, + osqueryContext, +}: CreateDynamicQueriesParams) => params.queries?.length ? map(params.queries, ({ query, ...restQuery }) => { const replacedQuery = replacedQueries(query, alertData); @@ -66,7 +45,7 @@ export const createDynamicQueries = async ( ...restQuery, action_id: uuidv4(), alert_ids: params.alert_ids, - agents: params.agent_ids, + agents, }, (value) => !isEmpty(value) || value === true ); @@ -77,8 +56,6 @@ export const createDynamicQueries = async ( action_id: uuidv4(), id: uuidv4(), ...replacedQueries(params.query, alertData), - // just for single queries - we need to overwrite the error property - error: undefined, saved_query_id: params.saved_query_id, saved_query_prebuilt: params.saved_query_id ? await isSavedQueryPrebuilt( @@ -88,13 +65,13 @@ export const createDynamicQueries = async ( : undefined, ecs_mapping: params.ecs_mapping, alert_ids: params.alert_ids, - agents: params.agent_ids, + agents, }, (value) => !isEmpty(value) ), ]; -const replacedQueries = ( +export const replacedQueries = ( query: string | undefined, alertData?: ParsedTechnicalFields ): { query: string | undefined; error?: string } => { @@ -105,10 +82,7 @@ const replacedQueries = ( query: result, ...(skipped ? { - error: i18n.translate('xpack.osquery.liveQueryActions.error.notFoundParameters', { - defaultMessage: - "This query hasn't been called due to parameter used and its value not found in the alert.", - }), + error: PARAMETER_NOT_FOUND, } : {}), }; 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 92ebddf7642e7..9d7ad88da88b6 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 @@ -11,6 +11,7 @@ import markdown from 'remark-parse-no-trim'; import { some, filter } from 'lodash'; import deepEqual from 'fast-deep-equal'; import type { ECSMappingOrUndefined } from '@kbn/osquery-io-ts-types'; +import { PARAMETER_NOT_FOUND } from '../../handlers/action/create_queries'; import { replaceParamsQuery } from '../../../common/utils/replace_params_query'; import { createLiveQueryRequestBodySchema } from '../../../common/schemas/routes/live_query'; import type { CreateLiveQueryRequestBodySchema } from '../../../common/schemas/routes/live_query'; @@ -93,7 +94,7 @@ export const createLiveQueryRoute = (router: IRouter, osqueryContext: OsqueryApp try { const currentUser = await osqueryContext.security.authc.getCurrentUser(request)?.username; - const { response: osqueryAction } = await createActionHandler( + const { response: osqueryAction, fleetActionsCount } = await createActionHandler( osqueryContext, request.body, { @@ -102,6 +103,11 @@ export const createLiveQueryRoute = (router: IRouter, osqueryContext: OsqueryApp alertData, } ); + if (!fleetActionsCount) { + return response.badRequest({ + body: PARAMETER_NOT_FOUND, + }); + } return response.ok({ body: { data: osqueryAction }, diff --git a/x-pack/test/osquery_cypress/agent.ts b/x-pack/test/osquery_cypress/agent.ts index 2bdecd90efdff..e35b2f1bc4d37 100644 --- a/x-pack/test/osquery_cypress/agent.ts +++ b/x-pack/test/osquery_cypress/agent.ts @@ -7,7 +7,7 @@ import { ToolingLog } from '@kbn/tooling-log'; import axios, { AxiosRequestConfig } from 'axios'; -import { ChildProcess, spawn } from 'child_process'; +import execa from 'execa'; import { getLatestVersion } from './artifact_manager'; import { Manager } from './resource_manager'; @@ -22,7 +22,7 @@ export interface AgentManagerParams { export class AgentManager extends Manager { private params: AgentManagerParams; private log: ToolingLog; - private agentProcess?: ChildProcess; + private agentContainerId?: string; private requestOptions: AxiosRequestConfig; constructor(params: AgentManagerParams, log: ToolingLog, requestOptions: AxiosRequestConfig) { super(); @@ -33,34 +33,40 @@ export class AgentManager extends Manager { public async setup() { this.log.info('Running agent preconfig'); - return await axios.post( - `${this.params.kibanaUrl}/api/fleet/agents/setup`, - {}, + + await axios.post( + `${this.params.kibanaUrl}/api/fleet/agent_policies?sys_monitoring=true`, + { + name: 'Osquery policy', + description: '', + namespace: 'default', + monitoring_enabled: ['logs', 'metrics'], + inactivity_timeout: 1209600, + }, this.requestOptions ); - } - public async startAgent() { this.log.info('Getting agent enrollment key'); const { data: apiKeys } = await axios.get( this.params.kibanaUrl + '/api/fleet/enrollment_api_keys', this.requestOptions ); - const policy = apiKeys.items[1]; + const policy = apiKeys.items[0]; this.log.info('Running the agent'); const artifact = `docker.elastic.co/beats/elastic-agent:${await getLatestVersion()}`; this.log.info(artifact); - const args = [ + const dockerArgs = [ 'run', + '--detach', '--add-host', 'host.docker.internal:host-gateway', '--env', 'FLEET_ENROLL=1', '--env', - `FLEET_URL=http://host.docker.internal:8220`, + `FLEET_URL=https://host.docker.internal:8220`, '--env', `FLEET_ENROLLMENT_TOKEN=${policy.api_key}`, '--env', @@ -69,7 +75,7 @@ export class AgentManager extends Manager { artifact, ]; - this.agentProcess = spawn('docker', args, { stdio: 'inherit' }); + this.agentContainerId = (await execa('docker', dockerArgs)).stdout; // Wait til we see the agent is online let done = false; @@ -92,15 +98,11 @@ export class AgentManager extends Manager { protected _cleanup() { this.log.info('Cleaning up the agent process'); - if (this.agentProcess) { - if (!this.agentProcess.kill(9)) { - this.log.warning('Unable to kill agent process'); - } + if (this.agentContainerId) { + this.log.info('Closing agent process'); - this.agentProcess.on('close', () => { - this.log.info('Agent process closed'); - }); - delete this.agentProcess; + execa.sync('docker', ['kill', this.agentContainerId]); + this.log.info('Agent process closed'); } return; } diff --git a/x-pack/test/osquery_cypress/artifact_manager.ts b/x-pack/test/osquery_cypress/artifact_manager.ts index 7ee2680e21f83..2a520c22203c0 100644 --- a/x-pack/test/osquery_cypress/artifact_manager.ts +++ b/x-pack/test/osquery_cypress/artifact_manager.ts @@ -6,5 +6,5 @@ */ export async function getLatestVersion(): Promise { - return '8.6.0-SNAPSHOT'; + return '8.8.0-SNAPSHOT'; } diff --git a/x-pack/test/osquery_cypress/config.ts b/x-pack/test/osquery_cypress/config.ts index 37f7b3f63b36c..76b5c3eca9f89 100644 --- a/x-pack/test/osquery_cypress/config.ts +++ b/x-pack/test/osquery_cypress/config.ts @@ -35,9 +35,11 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...xpackFunctionalTestsConfig.get('kbnTestServer'), serverArgs: [ ...xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs'), + '--csp.warnLegacyBrowsers=false', '--csp.strict=false', // define custom kibana server args here `--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`, + `--xpack.fleet.agents.fleet_server.hosts=["https://host.docker.internal:8220"]`, `--xpack.fleet.agents.elasticsearch.host=http://host.docker.internal:${kibanaCommonTestsConfig.get( 'servers.elasticsearch.port' )}`, diff --git a/x-pack/test/osquery_cypress/fleet_server.ts b/x-pack/test/osquery_cypress/fleet_server.ts index 77ec56cf20960..ce1ff24adc32a 100644 --- a/x-pack/test/osquery_cypress/fleet_server.ts +++ b/x-pack/test/osquery_cypress/fleet_server.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { ChildProcess, spawn } from 'child_process'; import { ToolingLog } from '@kbn/tooling-log'; import axios, { AxiosRequestConfig } from 'axios'; +import execa from 'execa'; import { Manager } from './resource_manager'; import { getLatestVersion } from './artifact_manager'; import { AgentManagerParams } from './agent'; export class FleetManager extends Manager { - private fleetProcess?: ChildProcess; + private fleetContainerId?: string; private config: AgentManagerParams; private log: ToolingLog; private requestOptions: AxiosRequestConfig; @@ -25,77 +25,65 @@ export class FleetManager extends Manager { } public async setup(): Promise { this.log.info('Setting fleet up'); - return new Promise(async (res, rej) => { - try { - // default fleet server policy no longer created by default - const { - data: { - item: { id: policyId }, - }, - } = await axios.post( - `${this.config.kibanaUrl}/api/fleet/agent_policies`, - { - name: 'Default Fleet Server policy', - description: '', - namespace: 'default', - monitoring_enabled: ['logs', 'metrics'], - has_fleet_server: true, - }, - this.requestOptions - ); - const response = await axios.post( - `${this.config.kibanaUrl}/api/fleet/service_tokens`, - {}, - this.requestOptions - ); - const serviceToken = response.data.value; - const artifact = `docker.elastic.co/beats/elastic-agent:${await getLatestVersion()}`; - this.log.info(artifact); + // default fleet server policy no longer created by default + const { + data: { + item: { id: policyId }, + }, + } = await axios.post( + `${this.config.kibanaUrl}/api/fleet/agent_policies`, + { + name: 'Default Fleet Server policy', + description: '', + namespace: 'default', + monitoring_enabled: ['logs', 'metrics'], + has_fleet_server: true, + }, + this.requestOptions + ); - const host = 'host.docker.internal'; + const response = await axios.post( + `${this.config.kibanaUrl}/api/fleet/service_tokens`, + {}, + this.requestOptions + ); + const serviceToken = response.data.value; + const artifact = `docker.elastic.co/beats/elastic-agent:${await getLatestVersion()}`; + this.log.info(artifact); - const args = [ - 'run', - '-p', - `8220:8220`, - '--add-host', - 'host.docker.internal:host-gateway', - '--env', - 'FLEET_SERVER_ENABLE=true', - '--env', - `FLEET_SERVER_ELASTICSEARCH_HOST=http://${host}:${this.config.esPort}`, - '--env', - `FLEET_SERVER_SERVICE_TOKEN=${serviceToken}`, - '--env', - `FLEET_SERVER_POLICY=${policyId}`, - '--rm', - artifact, - ]; - this.log.info('docker ' + args.join(' ')); - this.fleetProcess = spawn('docker', args, { - stdio: 'inherit', - }); - this.fleetProcess.on('error', rej); - setTimeout(res, 15000); - } catch (error) { - rej(error); - } - }); + const host = 'host.docker.internal'; + + const dockerArgs = [ + 'run', + '--detach', + '-p', + `8220:8220`, + '--add-host', + 'host.docker.internal:host-gateway', + '--env', + 'FLEET_SERVER_ENABLE=true', + '--env', + `FLEET_SERVER_ELASTICSEARCH_HOST=http://${host}:${this.config.esPort}`, + '--env', + `FLEET_SERVER_SERVICE_TOKEN=${serviceToken}`, + '--env', + `FLEET_SERVER_POLICY=${policyId}`, + '--rm', + artifact, + ]; + + this.log.info('docker ' + dockerArgs.join(' ')); + this.fleetContainerId = (await execa('docker', dockerArgs)).stdout; } protected _cleanup() { this.log.info('Removing old fleet config'); - if (this.fleetProcess) { + if (this.fleetContainerId) { this.log.info('Closing fleet process'); - if (!this.fleetProcess.kill(9)) { - this.log.warning('Unable to kill fleet server process'); - } - this.fleetProcess.on('close', () => { - this.log.info('Fleet server process closed'); - }); - delete this.fleetProcess; + execa.sync('docker', ['kill', this.fleetContainerId]); + this.log.info('Fleet server process closed'); } } } diff --git a/x-pack/test/osquery_cypress/runner.ts b/x-pack/test/osquery_cypress/runner.ts index 2c97d08b682c3..2cd194c14ea53 100644 --- a/x-pack/test/osquery_cypress/runner.ts +++ b/x-pack/test/osquery_cypress/runner.ts @@ -12,10 +12,7 @@ import { withProcRunner } from '@kbn/dev-proc-runner'; import { FtrProviderContext } from './ftr_provider_context'; -import { - // AgentManager, - AgentManagerParams, -} from './agent'; +import { AgentManager, AgentManagerParams } from './agent'; import { FleetManager } from './fleet_server'; async function withFleetAgent( @@ -47,8 +44,7 @@ async function withFleetAgent( }, }; const fleetManager = new FleetManager(params, log, requestOptions); - - // const agentManager = new AgentManager(params, log, requestOptions); + const agentManager = new AgentManager(params, log, requestOptions); // Since the managers will create uncaughtException event handlers we need to exit manually process.on('uncaughtException', (err) => { @@ -57,13 +53,13 @@ async function withFleetAgent( process.exit(1); }); - // await agentManager.setup(); await fleetManager.setup(); + await agentManager.setup(); try { await runner({}); } finally { + agentManager.cleanup(); fleetManager.cleanup(); - // agentManager.cleanup(); } } From a5030dd90e9cff293ebe3f14b32901c87049cc7a Mon Sep 17 00:00:00 2001 From: Janki Salvi <117571355+js-jankisalvi@users.noreply.github.com> Date: Tue, 28 Feb 2023 15:53:46 +0100 Subject: [PATCH 053/131] [Cases] Set new connector to default (#151884) ## Summary Fixes #136629 This PR sets newly created connector as default selection in dropdown. https://user-images.githubusercontent.com/117571355/221803503-60ebfa62-cc88-4223-a2e2-afe232b8b20d.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 - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../public/components/configure_cases/index.tsx | 16 +++++++++++++++- .../cypress/e2e/cases/connectors.cy.ts | 13 +++++++------ .../cypress/tasks/configure_cases.ts | 4 ++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/cases/public/components/configure_cases/index.tsx b/x-pack/plugins/cases/public/components/configure_cases/index.tsx index e44f61315641c..0f1ee58680129 100644 --- a/x-pack/plugins/cases/public/components/configure_cases/index.tsx +++ b/x-pack/plugins/cases/public/components/configure_cases/index.tsx @@ -94,6 +94,20 @@ export const ConfigureCases: React.FC = React.memo(() => { [refetchActionTypes, refetchCaseConfigure, refetchConnectors, setEditedConnectorItem] ); + const onConnectorCreated = useCallback( + async (createdConnector) => { + const caseConnector = normalizeActionConnector(createdConnector); + + await persistCaseConfigure({ + connector: caseConnector, + closureType, + }); + onConnectorUpdated(createdConnector); + setConnector(caseConnector); + }, + [onConnectorUpdated, closureType, setConnector, persistCaseConfigure] + ); + const isLoadingAny = isLoadingConnectors || persistLoading || loadingCaseConfigure || isLoadingActionTypes; const updateConnectorDisabled = isLoadingAny || !connectorIsValid || connector.id === 'none'; @@ -168,7 +182,7 @@ export const ConfigureCases: React.FC = React.memo(() => { ? triggersActionsUi.getAddConnectorFlyout({ onClose: onCloseAddFlyout, featureId: CasesConnectorFeatureId, - onConnectorCreated: onConnectorUpdated, + onConnectorCreated, }) : null, // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/x-pack/plugins/security_solution/cypress/e2e/cases/connectors.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/cases/connectors.cy.ts index 888b492d28b1d..e85885bb1ab0d 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/cases/connectors.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/cases/connectors.cy.ts @@ -14,7 +14,7 @@ import { cleanKibana, deleteCases } from '../../tasks/common'; import { addServiceNowConnector, openAddNewConnectorOption, - selectLastConnectorCreated, + verifyNewConnectorSelected, } from '../../tasks/configure_cases'; import { login, visitWithoutDateRange } from '../../tasks/login'; @@ -58,7 +58,7 @@ describe('Cases connectors', () => { }); cy.intercept('POST', '/api/actions/connector').as('createConnector'); - cy.intercept('POST', '/api/cases/configure', (req) => { + cy.intercept('PATCH', '/api/cases/configure/*', (req) => { const connector = req.body.connector; req.reply((res) => { res.send(200, { ...configureResult, connector }); @@ -94,14 +94,15 @@ describe('Cases connectors', () => { cy.wait('@createConnector').then(({ response }) => { cy.wrap(response?.statusCode).should('eql', 200); + + verifyNewConnectorSelected(snConnector); + cy.get(TOASTER).should('have.text', "Created 'New connector'"); + cy.get(TOASTER).should('have.text', 'Saved external connection settings'); cy.get(TOASTER).should('not.exist'); - selectLastConnectorCreated(response?.body.id); - - cy.wait('@saveConnector', { timeout: 10000 }).its('response.statusCode').should('eql', 200); + cy.wait('@saveConnector').its('response.statusCode').should('eql', 200); cy.get(SERVICE_NOW_MAPPING).first().should('have.text', 'short_description'); - cy.get(TOASTER).should('have.text', 'Saved external connection settings'); }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts b/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts index 4019468ddc43e..0b2f722204f5f 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/configure_cases.ts @@ -39,6 +39,10 @@ export const openAddNewConnectorOption = () => { }); }; +export const verifyNewConnectorSelected = (connector: Connector) => { + cy.get(CONNECTORS_DROPDOWN).should('have.text', connector.connectorName); +}; + export const selectLastConnectorCreated = (id: string) => { cy.get(CONNECTORS_DROPDOWN).click({ force: true }); cy.get(CONNECTOR(id)).click(); From e99feb800ce66699e0415bd8a70fc29a694cc747 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Feb 2023 10:03:30 -0500 Subject: [PATCH 054/131] Update babel to ^7.21.1 (main) (#152308) 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/generator](https://babel.dev/docs/en/next/babel-generator) ([source](https://togithub.com/babel/babel)) | [`^7.21.0` -> `^7.21.1`](https://renovatebot.com/diffs/npm/@babel%2fgenerator/7.21.1/7.21.1) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.1/compatibility-slim/7.21.1)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fgenerator/7.21.1/confidence-slim/7.21.1)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/parser](https://babel.dev/docs/en/next/babel-parser) ([source](https://togithub.com/babel/babel)) | [`^7.21.0` -> `^7.21.1`](https://renovatebot.com/diffs/npm/@babel%2fparser/7.21.2/7.21.1) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.1/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.1/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.1/compatibility-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.1/confidence-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### 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 these updates 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> --- package.json | 4 ++-- yarn.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f091b8dd3073d..a363b2c162e56 100644 --- a/package.json +++ b/package.json @@ -940,9 +940,9 @@ "@babel/core": "^7.21.0", "@babel/eslint-parser": "^7.19.1", "@babel/eslint-plugin": "^7.19.1", - "@babel/generator": "^7.21.0", + "@babel/generator": "^7.21.1", "@babel/helper-plugin-utils": "^7.20.2", - "@babel/parser": "^7.21.0", + "@babel/parser": "^7.21.1", "@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 67ee4aa219a87..6ffc80f4e34d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -393,7 +393,7 @@ 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.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2": +"@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.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.1", "@babel/parser@^7.21.2": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== From 662bd9a410adf5669aba0f4a2fcb66636e9d548c Mon Sep 17 00:00:00 2001 From: Drew Tate Date: Tue, 28 Feb 2023 09:15:13 -0600 Subject: [PATCH 055/131] [Lens] always retain source order for multi-metric partition chart layers (#151949) --- .../partition_vis_component.test.tsx.snap | 2 +- .../public/utils/layers/get_color.test.ts | 290 ++++++++++++++ .../public/utils/layers/get_layers.test.ts | 366 +++++------------- .../public/utils/layers/get_layers.ts | 8 +- .../public/utils/layers/sort_predicate.ts | 2 +- .../visualizations/partition/to_expression.ts | 24 +- .../partition/visualization.test.ts | 230 ++++++----- .../partition/visualization.tsx | 26 +- 8 files changed, 562 insertions(+), 386 deletions(-) diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/components/__snapshots__/partition_vis_component.test.tsx.snap b/src/plugins/chart_expressions/expression_partition_vis/public/components/__snapshots__/partition_vis_component.test.tsx.snap index c91e491887a99..1a566571b4d6c 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/components/__snapshots__/partition_vis_component.test.tsx.snap +++ b/src/plugins/chart_expressions/expression_partition_vis/public/components/__snapshots__/partition_vis_component.test.tsx.snap @@ -1267,7 +1267,7 @@ exports[`PartitionVisComponent should render correct structure for multi-metric "fillColor": [Function], }, "showAccessor": [Function], - "sortPredicate": undefined, + "sortPredicate": [Function], }, ] } diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts index 225f405bac2ca..06fa1d9aae83b 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts @@ -10,6 +10,15 @@ import type { PaletteOutput, PaletteDefinition } from '@kbn/coloring'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { Datatable } from '@kbn/expressions-plugin/common'; import { byDataColorPaletteMap } from './get_color'; +import { ShapeTreeNode } from '@elastic/charts'; +import type { SeriesLayer } from '@kbn/coloring'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; +import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { getColor } from './get_color'; +import { createMockVisData, createMockBucketColumns, createMockPieParams } from '../../mocks'; +import { generateFormatters } from '../formatters'; +import { ChartTypes } from '../../../common/types'; describe('#byDataColorPaletteMap', () => { let datatable: Datatable; @@ -88,3 +97,284 @@ describe('#byDataColorPaletteMap', () => { ); }); }); + +describe('getColor', () => { + const visData = createMockVisData(); + const buckets = createMockBucketColumns(); + const visParams = createMockPieParams(); + const colors = ['color1', 'color2', 'color3', 'color4']; + const dataMock = dataPluginMock.createStartContract(); + interface RangeProps { + gte: number; + lt: number; + } + const defaultFormatter = jest.fn((...args) => fieldFormatsMock.deserialize(...args)); + const formatters = generateFormatters(visData, defaultFormatter); + + dataMock.fieldFormats = { + deserialize: jest.fn(() => ({ + convert: jest.fn((s: RangeProps) => { + return `≥ ${s.gte} and < ${s.lt}`; + }), + })), + } as unknown as DataPublicPluginStart['fieldFormats']; + + const getPaletteRegistry = () => { + const mockPalette1: jest.Mocked = { + id: 'default', + title: 'My Palette', + getCategoricalColor: jest.fn((layer: SeriesLayer[]) => colors[layer[0].rankAtDepth]), + getCategoricalColors: jest.fn((num: number) => colors), + toExpression: jest.fn(() => ({ + type: 'expression', + chain: [ + { + type: 'function', + function: 'system_palette', + arguments: { + name: ['default'], + }, + }, + ], + })), + }; + + return { + get: () => mockPalette1, + getAll: () => [mockPalette1], + }; + }; + it('should return the correct color based on the parent sortIndex', () => { + const d = { + dataName: 'ES-Air', + depth: 1, + sortIndex: 0, + parent: { + children: [['ES-Air'], ['Kibana Airlines']], + depth: 0, + sortIndex: 0, + }, + } as unknown as ShapeTreeNode; + const color = getColor( + ChartTypes.PIE, + d, + 0, + false, + {}, + buckets, + visData.rows, + visParams, + getPaletteRegistry(), + { getColor: () => undefined }, + false, + false, + dataMock.fieldFormats, + visData.columns[0], + formatters + ); + expect(color).toEqual(colors[0]); + }); + + it('slices with the same label should have the same color for small multiples', () => { + const d = { + dataName: 'ES-Air', + depth: 1, + sortIndex: 0, + parent: { + children: [['ES-Air'], ['Kibana Airlines']], + depth: 0, + sortIndex: 0, + }, + } as unknown as ShapeTreeNode; + const color = getColor( + ChartTypes.PIE, + d, + 0, + true, + {}, + buckets, + visData.rows, + visParams, + getPaletteRegistry(), + { getColor: () => undefined }, + false, + false, + dataMock.fieldFormats, + visData.columns[0], + formatters + ); + expect(color).toEqual('color3'); + }); + it('returns the overwriteColor if exists', () => { + const d = { + dataName: 'ES-Air', + depth: 1, + sortIndex: 0, + parent: { + children: [['ES-Air'], ['Kibana Airlines']], + depth: 0, + sortIndex: 0, + }, + } as unknown as ShapeTreeNode; + const color = getColor( + ChartTypes.PIE, + d, + 0, + true, + { 'ES-Air': '#000028' }, + buckets, + visData.rows, + visParams, + getPaletteRegistry(), + { getColor: () => undefined }, + false, + false, + dataMock.fieldFormats, + visData.columns[0], + formatters + ); + expect(color).toEqual('#000028'); + }); + + it('returns the overwriteColor for older visualizations with formatted values', () => { + const d = { + dataName: { + gte: 1000, + lt: 2000, + }, + depth: 1, + sortIndex: 0, + parent: { + children: [ + [ + { + gte: 1000, + lt: 2000, + }, + ], + [ + { + gte: 2000, + lt: 3000, + }, + ], + ], + depth: 0, + sortIndex: 0, + }, + } as unknown as ShapeTreeNode; + const visParamsNew = { + ...visParams, + distinctColors: true, + }; + const column = { + ...visData.columns[0], + format: { + id: 'range', + params: { + id: 'number', + }, + }, + }; + const color = getColor( + ChartTypes.PIE, + d, + 0, + true, + { '≥ 1000 and < 2000': '#3F6833' }, + buckets, + visData.rows, + visParamsNew, + getPaletteRegistry(), + { getColor: () => undefined }, + false, + false, + dataMock.fieldFormats, + column, + formatters + ); + expect(color).toEqual('#3F6833'); + }); + + it('should only pass the second layer for mosaic', () => { + const d = { + dataName: 'Second level 1', + depth: 2, + sortIndex: 0, + parent: { + children: [['Second level 1'], ['Second level 2']], + depth: 1, + sortIndex: 0, + parent: { + children: [['First level']], + depth: 0, + sortIndex: 0, + }, + }, + } as unknown as ShapeTreeNode; + const registry = getPaletteRegistry(); + getColor( + ChartTypes.MOSAIC, + d, + 1, + true, + {}, + buckets, + visData.rows, + visParams, + registry, + undefined, + true, + false, + dataMock.fieldFormats, + visData.columns[0], + formatters + ); + expect(registry.get().getCategoricalColor).toHaveBeenCalledWith( + [expect.objectContaining({ name: 'Second level 1' })], + expect.anything(), + expect.anything() + ); + }); + + it('should only pass the first layer for treemap', () => { + const d = { + dataName: 'Second level 1', + depth: 2, + sortIndex: 0, + parent: { + children: [['Second level 1'], ['Second level 2']], + depth: 1, + sortIndex: 0, + parent: { + children: [['First level']], + depth: 0, + sortIndex: 0, + }, + }, + } as unknown as ShapeTreeNode; + const registry = getPaletteRegistry(); + getColor( + ChartTypes.TREEMAP, + d, + 1, + true, + {}, + buckets, + visData.rows, + visParams, + registry, + undefined, + true, + false, + dataMock.fieldFormats, + visData.columns[0], + formatters + ); + expect(registry.get().getCategoricalColor).toHaveBeenCalledWith( + [expect.objectContaining({ name: 'First level' })], + expect.anything(), + expect.anything() + ); + }); +}); diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts index d96ada51ba47a..7300aac06329f 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts @@ -5,294 +5,110 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { ShapeTreeNode } from '@elastic/charts'; -import type { PaletteDefinition, SeriesLayer } from '@kbn/coloring'; -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; -import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; -import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { getColor } from './get_color'; -import { createMockVisData, createMockBucketColumns, createMockPieParams } from '../../mocks'; -import { generateFormatters } from '../formatters'; -import { ChartTypes } from '../../../common/types'; - -const visData = createMockVisData(); -const buckets = createMockBucketColumns(); -const visParams = createMockPieParams(); -const colors = ['color1', 'color2', 'color3', 'color4']; -const dataMock = dataPluginMock.createStartContract(); -interface RangeProps { - gte: number; - lt: number; -} -const defaultFormatter = jest.fn((...args) => fieldFormatsMock.deserialize(...args)); -const formatters = generateFormatters(visData, defaultFormatter); -dataMock.fieldFormats = { - deserialize: jest.fn(() => ({ - convert: jest.fn((s: RangeProps) => { - return `≥ ${s.gte} and < ${s.lt}`; - }), - })), -} as unknown as DataPublicPluginStart['fieldFormats']; +import { ArrayEntry, ArrayNode } from '@elastic/charts'; +import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks'; +import { BucketColumns, ChartTypes } from '../../../common/types'; +import { createMockPieParams, createMockVisData } from '../../mocks'; +import { getPaletteRegistry } from '../../__mocks__/palettes'; +import { getLayers } from './get_layers'; -export const getPaletteRegistry = () => { - const mockPalette1: jest.Mocked = { - id: 'default', - title: 'My Palette', - getCategoricalColor: jest.fn((layer: SeriesLayer[]) => colors[layer[0].rankAtDepth]), - getCategoricalColors: jest.fn((num: number) => colors), - toExpression: jest.fn(() => ({ - type: 'expression', - chain: [ - { - type: 'function', - function: 'system_palette', - arguments: { - name: ['default'], +describe('getLayers', () => { + it('preserves slice order for multi-metric layer', () => { + const visData = createMockVisData(); + const columns: BucketColumns[] = [ + { + id: 'col-0-0', + name: 'Normal column', + meta: { type: 'murmur3' }, + }, + { + id: 'col-0-0', + name: 'multi-metric column', + meta: { + type: 'number', + sourceParams: { + consolidatedMetricsColumn: true, }, }, - ], - })), - }; - - return { - get: () => mockPalette1, - getAll: () => [mockPalette1], - }; -}; - -describe('computeColor', () => { - it('should return the correct color based on the parent sortIndex', () => { - const d = { - dataName: 'ES-Air', - depth: 1, - sortIndex: 0, - parent: { - children: [['ES-Air'], ['Kibana Airlines']], - depth: 0, - sortIndex: 0, }, - } as unknown as ShapeTreeNode; - const color = getColor( + ]; + const visParams = createMockPieParams(); + const layers = getLayers( ChartTypes.PIE, - d, - 0, - false, - {}, - buckets, - visData.rows, + columns, visParams, - getPaletteRegistry(), - { getColor: () => undefined }, - false, - false, - dataMock.fieldFormats, - visData.columns[0], - formatters - ); - expect(color).toEqual(colors[0]); - }); - - it('slices with the same label should have the same color for small multiples', () => { - const d = { - dataName: 'ES-Air', - depth: 1, - sortIndex: 0, - parent: { - children: [['ES-Air'], ['Kibana Airlines']], - depth: 0, - sortIndex: 0, - }, - } as unknown as ShapeTreeNode; - const color = getColor( - ChartTypes.PIE, - d, - 0, - true, + visData, {}, - buckets, - visData.rows, - visParams, - getPaletteRegistry(), - { getColor: () => undefined }, - false, - false, - dataMock.fieldFormats, - visData.columns[0], - formatters - ); - expect(color).toEqual('color3'); - }); - it('returns the overwriteColor if exists', () => { - const d = { - dataName: 'ES-Air', - depth: 1, - sortIndex: 0, - parent: { - children: [['ES-Air'], ['Kibana Airlines']], - depth: 0, - sortIndex: 0, - }, - } as unknown as ShapeTreeNode; - const color = getColor( - ChartTypes.PIE, - d, - 0, - true, - { 'ES-Air': '#000028' }, - buckets, - visData.rows, - visParams, + [], getPaletteRegistry(), - { getColor: () => undefined }, - false, + {}, + fieldFormatsMock, false, - dataMock.fieldFormats, - visData.columns[0], - formatters + false ); - expect(color).toEqual('#000028'); - }); - it('returns the overwriteColor for older visualizations with formatted values', () => { - const d = { - dataName: { - gte: 1000, - lt: 2000, - }, - depth: 1, - sortIndex: 0, - parent: { - children: [ - [ - { - gte: 1000, - lt: 2000, - }, - ], - [ - { - gte: 2000, - lt: 3000, - }, - ], - ], - depth: 0, - sortIndex: 0, - }, - } as unknown as ShapeTreeNode; - const visParamsNew = { - ...visParams, - distinctColors: true, - }; - const column = { - ...visData.columns[0], - format: { - id: 'range', - params: { - id: 'number', - }, - }, - }; - const color = getColor( - ChartTypes.PIE, - d, - 0, - true, - { '≥ 1000 and < 2000': '#3F6833' }, - buckets, - visData.rows, - visParamsNew, - getPaletteRegistry(), - { getColor: () => undefined }, - false, - false, - dataMock.fieldFormats, - column, - formatters - ); - expect(color).toEqual('#3F6833'); - }); + expect(layers[0].sortPredicate).toBeUndefined(); + expect(layers[1].sortPredicate).toBeDefined(); - it('should only pass the second layer for mosaic', () => { - const d = { - dataName: 'Second level 1', - depth: 2, - sortIndex: 0, - parent: { - children: [['Second level 1'], ['Second level 2']], - depth: 1, - sortIndex: 0, - parent: { - children: [['First level']], - depth: 0, - sortIndex: 0, - }, - }, - } as unknown as ShapeTreeNode; - const registry = getPaletteRegistry(); - getColor( - ChartTypes.MOSAIC, - d, - 1, - true, - {}, - buckets, - visData.rows, - visParams, - registry, - undefined, - true, - false, - dataMock.fieldFormats, - visData.columns[0], - formatters - ); - expect(registry.get().getCategoricalColor).toHaveBeenCalledWith( - [expect.objectContaining({ name: 'Second level 1' })], - expect.anything(), - expect.anything() - ); - }); + const testNodes: ArrayEntry[] = [ + [ + '', + { + value: 2, + inputIndex: [3], + } as ArrayNode, + ], + [ + '', + { + value: 1, + inputIndex: [2], + } as ArrayNode, + ], - it('should only pass the first layer for treemap', () => { - const d = { - dataName: 'Second level 1', - depth: 2, - sortIndex: 0, - parent: { - children: [['Second level 1'], ['Second level 2']], - depth: 1, - sortIndex: 0, - parent: { - children: [['First level']], - depth: 0, - sortIndex: 0, - }, - }, - } as unknown as ShapeTreeNode; - const registry = getPaletteRegistry(); - getColor( - ChartTypes.TREEMAP, - d, - 1, - true, - {}, - buckets, - visData.rows, - visParams, - registry, - undefined, - true, - false, - dataMock.fieldFormats, - visData.columns[0], - formatters - ); - expect(registry.get().getCategoricalColor).toHaveBeenCalledWith( - [expect.objectContaining({ name: 'First level' })], - expect.anything(), - expect.anything() - ); + [ + '', + { + value: 3, + inputIndex: [1], + } as ArrayNode, + ], + ]; + + const predicate = layers[1].sortPredicate!; + testNodes.sort(predicate); + + expect(testNodes).toMatchInlineSnapshot(` + Array [ + Array [ + "", + Object { + "inputIndex": Array [ + 1, + ], + "value": 3, + }, + ], + Array [ + "", + Object { + "inputIndex": Array [ + 2, + ], + "value": 1, + }, + ], + Array [ + "", + Object { + "inputIndex": Array [ + 3, + ], + "value": 2, + }, + ], + ] + `); }); }); diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts index 646a0e4b45d2e..93a9cc2b6c7d6 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.ts @@ -12,7 +12,7 @@ import { FieldFormat } from '@kbn/field-formats-plugin/common'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { Datatable, DatatableRow } from '@kbn/expressions-plugin/public'; import { BucketColumns, ChartTypes, PartitionVisParams } from '../../../common/types'; -import { sortPredicateByType } from './sort_predicate'; +import { sortPredicateByType, sortPredicateSaveSourceOrder } from './sort_predicate'; import { byDataColorPaletteMap, getColor } from './get_color'; import { getNodeLabel } from './get_node_labels'; @@ -52,7 +52,7 @@ export const getLayers = ( ); } - const sortPredicate = sortPredicateByType(chartType, visParams, visData, columns); + const sortPredicateForType = sortPredicateByType(chartType, visParams, visData, columns); return columns.map((col, layerIndex) => { return { groupByRollup: (d: Datum) => (col.id ? d[col.id] ?? EMPTY_SLICE : col.name), @@ -62,7 +62,9 @@ export const getLayers = ( layerIndex === 0 && chartType === ChartTypes.MOSAIC ? { ...fillLabel, minFontSize: 14, maxFontSize: 14, clipText: true } : fillLabel, - sortPredicate, + sortPredicate: col.meta?.sourceParams?.consolidatedMetricsColumn + ? sortPredicateSaveSourceOrder() + : sortPredicateForType, shape: { fillColor: (d) => getColor( diff --git a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/sort_predicate.ts b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/sort_predicate.ts index 0e4564a9bcfe5..b5992c3b600bf 100644 --- a/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/sort_predicate.ts +++ b/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/sort_predicate.ts @@ -30,7 +30,7 @@ export const extractUniqTermsMap = (dataTable: Datatable, columnId: string) => {} ); -const sortPredicateSaveSourceOrder: SortPredicatePureFn = +export const sortPredicateSaveSourceOrder: SortPredicatePureFn = () => ([, node1], [, node2]) => { const [index1] = node1.inputIndex ?? []; diff --git a/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts b/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts index 188ddfccea0ba..94438f242ec8d 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/to_expression.ts @@ -79,10 +79,10 @@ export const getColumnToLabelMap = ( return columnToLabel; }; -export const getSortedGroups = ( +export const getSortedAccessorsForGroup = ( datasource: DatasourcePublicAPI | undefined, layer: PieLayerState, - accessor: 'primaryGroups' | 'secondaryGroups' = 'primaryGroups' + accessor: 'primaryGroups' | 'secondaryGroups' | 'metrics' ) => { const originalOrder = datasource ?.getTableSpec() @@ -174,7 +174,9 @@ const generateCommonArguments = ( datasourceLayers: DatasourceLayers, paletteService: PaletteRegistry ) => { - const columnToLabelMap = getColumnToLabelMap(layer.metrics, datasourceLayers[layer.layerId]); + const datasource = datasourceLayers[layer.layerId]; + const columnToLabelMap = getColumnToLabelMap(layer.metrics, datasource); + const sortedMetricAccessors = getSortedAccessorsForGroup(datasource, layer, 'metrics'); return { labels: generateCommonLabelsAstArgs(state, attributes, layer, columnToLabelMap), @@ -182,7 +184,7 @@ const generateCommonArguments = ( .filter(({ columnId }) => !isCollapsed(columnId, layer)) .map(({ columnId }) => columnId) .map(prepareDimension), - metrics: (layer.allowMultipleMetrics ? layer.metrics : [layer.metrics[0]]).map( + metrics: (layer.allowMultipleMetrics ? sortedMetricAccessors : [sortedMetricAccessors[0]]).map( prepareDimension ), metricsToLabels: JSON.stringify(columnToLabelMap), @@ -290,16 +292,18 @@ function expressionHelper( const layer = state.layers[0]; const datasource = datasourceLayers[layer.layerId]; - const groups = Array.from( + const accessors = Array.from( new Set( [ - getSortedGroups(datasource, layer, 'primaryGroups'), - layer.secondaryGroups ? getSortedGroups(datasource, layer, 'secondaryGroups') : [], + getSortedAccessorsForGroup(datasource, layer, 'primaryGroups'), + layer.secondaryGroups + ? getSortedAccessorsForGroup(datasource, layer, 'secondaryGroups') + : [], ].flat() ) ); - const operations = groups + const operations = accessors .map((columnId) => ({ columnId, operation: datasource?.getOperationForColumnId(columnId) as Operation | null, @@ -323,11 +327,11 @@ function expressionHelper( type: 'expression', chain: [ ...(datasourceAst ? datasourceAst.chain : []), - ...groups + ...accessors .filter((columnId) => layer.collapseFns?.[columnId]) .map((columnId) => { return buildExpressionFunction('lens_collapse', { - by: groups.filter((chk) => chk !== columnId), + by: accessors.filter((chk) => chk !== columnId), metric: layer.metrics, fn: [layer.collapseFns![columnId]!], }).toAst(); diff --git a/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts b/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts index 2bf830c0028cd..a11c1667f807f 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts +++ b/x-pack/plugins/lens/public/visualizations/partition/visualization.test.ts @@ -448,119 +448,173 @@ describe('pie_visualization', () => { }); }); - it("doesn't count collapsed columns toward the dimension limits", () => { - const colIds = new Array(PartitionChartsMeta.pie.maxBuckets) - .fill(undefined) - .map((_, i) => String(i + 1)); - - const frame = mockFrame(); - frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => - colIds.map((id) => ({ columnId: id, fields: [] })); + it('orders metric accessors by datasource column order', () => { + const colIds = ['1', '2', '3', '4']; const state = getExampleState(); - state.layers[0].primaryGroups = colIds; - - const getConfig = (_state: PieVisualizationState) => - pieVisualization.getConfiguration({ - state: _state, - frame, - layerId: state.layers[0].layerId, - }); - - expect(findPrimaryGroup(getConfig(state))?.supportsMoreColumns).toBeFalsy(); + state.layers[0].metrics = colIds; + state.layers[0].allowMultipleMetrics = true; - const stateWithCollapsed = cloneDeep(state); - stateWithCollapsed.layers[0].collapseFns = { '1': 'sum' }; + const frame = mockFrame(); + frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => + // reverse the column IDs in the datasource + colIds.reverse().map((id) => ({ columnId: id, fields: [] })); + + // this is to make sure the accessors get sorted before palette colors are applied + const palette = paletteServiceMock.get('default'); + palette.getCategoricalColor + .mockReturnValueOnce('color 1') + .mockReturnValueOnce('color 2') + .mockReturnValueOnce('color 3') + .mockReturnValueOnce('color 4'); + + const config = pieVisualization.getConfiguration({ + state, + frame, + layerId: state.layers[0].layerId, + }); - expect(findPrimaryGroup(getConfig(stateWithCollapsed))?.supportsMoreColumns).toBeTruthy(); + expect(findMetricGroup(config)?.accessors).toMatchInlineSnapshot(` + Array [ + Object { + "color": "color 1", + "columnId": "4", + "triggerIconType": "color", + }, + Object { + "color": "color 2", + "columnId": "3", + "triggerIconType": "color", + }, + Object { + "color": "color 3", + "columnId": "2", + "triggerIconType": "color", + }, + Object { + "color": "color 4", + "columnId": "1", + "triggerIconType": "color", + }, + ] + `); }); - it('counts multiple metrics toward the dimension limits when not mosaic', () => { - const colIds = new Array(PartitionChartsMeta.pie.maxBuckets - 1) - .fill(undefined) - .map((_, i) => String(i + 1)); + describe('dimension limits', () => { + it("doesn't count collapsed columns toward the dimension limits", () => { + const colIds = new Array(PartitionChartsMeta.pie.maxBuckets) + .fill(undefined) + .map((_, i) => String(i + 1)); - const frame = mockFrame(); - frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => - colIds.map((id) => ({ columnId: id, fields: [] })); + const frame = mockFrame(); + frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => + colIds.map((id) => ({ columnId: id, fields: [] })); - const state = getExampleState(); - state.layers[0].primaryGroups = colIds; - state.layers[0].allowMultipleMetrics = true; + const state = getExampleState(); + state.layers[0].primaryGroups = colIds; - const getConfig = (_state: PieVisualizationState) => - pieVisualization.getConfiguration({ - state: _state, - frame, - layerId: state.layers[0].layerId, - }); + const getConfig = (_state: PieVisualizationState) => + pieVisualization.getConfiguration({ + state: _state, + frame, + layerId: state.layers[0].layerId, + }); - expect(findPrimaryGroup(getConfig(state))?.supportsMoreColumns).toBeTruthy(); + expect(findPrimaryGroup(getConfig(state))?.supportsMoreColumns).toBeFalsy(); - const stateWithMultipleMetrics = cloneDeep(state); - stateWithMultipleMetrics.layers[0].metrics.push('1', '2'); + const stateWithCollapsed = cloneDeep(state); + stateWithCollapsed.layers[0].collapseFns = { '1': 'sum' }; - expect( - findPrimaryGroup(getConfig(stateWithMultipleMetrics))?.supportsMoreColumns - ).toBeFalsy(); - }); + expect(findPrimaryGroup(getConfig(stateWithCollapsed))?.supportsMoreColumns).toBeTruthy(); + }); - it('does NOT count multiple metrics toward the dimension limits when mosaic', () => { - const frame = mockFrame(); - frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => []; + it('counts multiple metrics toward the dimension limits when not mosaic', () => { + const colIds = new Array(PartitionChartsMeta.pie.maxBuckets - 1) + .fill(undefined) + .map((_, i) => String(i + 1)); - const state = getExampleState(); - state.shape = 'mosaic'; - state.layers[0].primaryGroups = []; - state.layers[0].allowMultipleMetrics = false; // always true for mosaic + const frame = mockFrame(); + frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => + colIds.map((id) => ({ columnId: id, fields: [] })); - const getConfig = (_state: PieVisualizationState) => - pieVisualization.getConfiguration({ - state: _state, - frame, - layerId: state.layers[0].layerId, - }); + const state = getExampleState(); + state.layers[0].primaryGroups = colIds; + state.layers[0].allowMultipleMetrics = true; - expect(findPrimaryGroup(getConfig(state))?.supportsMoreColumns).toBeTruthy(); + const getConfig = (_state: PieVisualizationState) => + pieVisualization.getConfiguration({ + state: _state, + frame, + layerId: state.layers[0].layerId, + }); - const stateWithMultipleMetrics = cloneDeep(state); - stateWithMultipleMetrics.layers[0].metrics.push('1', '2'); + expect(findPrimaryGroup(getConfig(state))?.supportsMoreColumns).toBeTruthy(); - expect( - findPrimaryGroup(getConfig(stateWithMultipleMetrics))?.supportsMoreColumns - ).toBeTruthy(); - }); + const stateWithMultipleMetrics = cloneDeep(state); + stateWithMultipleMetrics.layers[0].metrics.push('1', '2'); - it('reports too many metric dimensions if multiple not enabled', () => { - const colIds = ['1', '2', '3', '4']; + expect( + findPrimaryGroup(getConfig(stateWithMultipleMetrics))?.supportsMoreColumns + ).toBeFalsy(); + }); - const frame = mockFrame(); - frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => - colIds.map((id) => ({ columnId: id, fields: [] })); + it('does NOT count multiple metrics toward the dimension limits when mosaic', () => { + const frame = mockFrame(); + frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => []; - const state = getExampleState(); - state.layers[0].metrics = colIds; - state.layers[0].allowMultipleMetrics = false; - expect( - findMetricGroup( - pieVisualization.getConfiguration({ - state, - frame, - layerId: state.layers[0].layerId, - }) - )?.dimensionsTooMany - ).toBe(3); + const state = getExampleState(); + state.shape = 'mosaic'; + state.layers[0].primaryGroups = []; + state.layers[0].allowMultipleMetrics = false; // always true for mosaic - state.layers[0].allowMultipleMetrics = true; - expect( - findMetricGroup( + const getConfig = (_state: PieVisualizationState) => pieVisualization.getConfiguration({ - state, + state: _state, frame, layerId: state.layers[0].layerId, - }) - )?.dimensionsTooMany - ).toBe(0); + }); + + expect(findPrimaryGroup(getConfig(state))?.supportsMoreColumns).toBeTruthy(); + + const stateWithMultipleMetrics = cloneDeep(state); + stateWithMultipleMetrics.layers[0].metrics.push('1', '2'); + + expect( + findPrimaryGroup(getConfig(stateWithMultipleMetrics))?.supportsMoreColumns + ).toBeTruthy(); + }); + + it('reports too many metric dimensions if multiple not enabled', () => { + const colIds = ['1', '2', '3', '4']; + + const frame = mockFrame(); + frame.datasourceLayers[LAYER_ID]!.getTableSpec = () => + colIds.map((id) => ({ columnId: id, fields: [] })); + + const state = getExampleState(); + state.layers[0].metrics = colIds; + state.layers[0].allowMultipleMetrics = false; + expect( + findMetricGroup( + pieVisualization.getConfiguration({ + state, + frame, + layerId: state.layers[0].layerId, + }) + )?.dimensionsTooMany + ).toBe(3); + + state.layers[0].allowMultipleMetrics = true; + expect( + findMetricGroup( + pieVisualization.getConfiguration({ + state, + frame, + layerId: state.layers[0].layerId, + }) + )?.dimensionsTooMany + ).toBe(0); + }); }); it.each(Object.values(PieChartTypes).filter((type) => type !== 'mosaic'))( diff --git a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx index cedfb12f72df7..a5c218a6483e1 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx @@ -29,7 +29,7 @@ import type { } from '../../types'; import { getColumnToLabelMap, - getSortedGroups, + getSortedAccessorsForGroup, toExpression, toPreviewExpression, } from './to_expression'; @@ -91,12 +91,13 @@ export const getDefaultColorForMultiMetricDimension = ({ datasource: DatasourcePublicAPI | undefined; }) => { const columnToLabelMap = datasource ? getColumnToLabelMap(layer.metrics, datasource) : {}; + const sortedMetrics = getSortedAccessorsForGroup(datasource, layer, 'metrics'); return paletteService.get('default').getCategoricalColor([ { name: columnToLabelMap[columnId], - rankAtDepth: layer.metrics.indexOf(columnId), - totalSeriesAtDepth: layer.metrics.length, + rankAtDepth: sortedMetrics.indexOf(columnId), + totalSeriesAtDepth: sortedMetrics.length, }, ]) as string; }; @@ -167,7 +168,7 @@ export const getPieVisualization = ({ const datasource = frame.datasourceLayers[layer.layerId]; const getPrimaryGroupConfig = (): VisualizationDimensionGroupConfig => { - const originalOrder = getSortedGroups(datasource, layer); + const originalOrder = getSortedAccessorsForGroup(datasource, layer, 'primaryGroups'); // When we add a column it could be empty, and therefore have no order const accessors = originalOrder.map((accessor) => ({ columnId: accessor, @@ -273,7 +274,11 @@ export const getPieVisualization = ({ }; const getSecondaryGroupConfig = (): VisualizationDimensionGroupConfig | undefined => { - const originalSecondaryOrder = getSortedGroups(datasource, layer, 'secondaryGroups'); + const originalSecondaryOrder = getSortedAccessorsForGroup( + datasource, + layer, + 'secondaryGroups' + ); const accessors = originalSecondaryOrder.map((accessor) => ({ columnId: accessor, triggerIconType: isCollapsed(accessor, layer) ? 'aggregate' : undefined, @@ -317,7 +322,11 @@ export const getPieVisualization = ({ const getMetricGroupConfig = (): VisualizationDimensionGroupConfig => { const hasSliceBy = layer.primaryGroups.length + (layer.secondaryGroups?.length ?? 0); - const accessors: AccessorConfig[] = layer.metrics.map((columnId, index) => ({ + const accessors: AccessorConfig[] = getSortedAccessorsForGroup( + datasource, + layer, + 'metrics' + ).map((columnId) => ({ columnId, ...(layer.allowMultipleMetrics ? hasSliceBy @@ -371,7 +380,7 @@ export const getPieVisualization = ({ }; }, - setDimension({ prevState, layerId, columnId, groupId }) { + setDimension({ prevState, layerId, columnId, groupId, previousColumn }) { return { ...prevState, layers: prevState.layers.map((l) => { @@ -393,7 +402,8 @@ export const getPieVisualization = ({ ], }; } - return { ...l, metrics: [...l.metrics.filter((metric) => metric !== columnId), columnId] }; + const metrics = [...l.metrics.filter((metric) => metric !== columnId), columnId]; + return { ...l, metrics }; }), }; }, From a6d988ab8d1888da59ca3971850a47f9282d0240 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Tue, 28 Feb 2023 09:03:38 -0700 Subject: [PATCH 056/131] Adding support for negative filter ratios for TSVB (#152053) ## Summary This PR fixes #150738 by adding support for negative denominators for TSVB's filter ratios. ### 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: Stratoula Kalafateli --- .../lib/vis_data/request_processors/series/filter_ratios.js | 2 +- .../vis_data/request_processors/series/filter_ratios.test.js | 4 ++-- .../lib/vis_data/request_processors/table/filter_ratios.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js index 0aaf011053718..34d933c2e9ae4 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.js @@ -62,7 +62,7 @@ export function ratios(req, panel, series, esQueryConfig, seriesIndex) { denominator: denominatorPath, }, script: - 'params.numerator != null && params.denominator != null && params.denominator > 0 ? params.numerator / params.denominator : 0', + 'params.numerator != null && params.denominator != null && params.denominator != 0 ? params.numerator / params.denominator : 0', }, }); }); diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js index a93827ba82cd6..e11414d88fd5c 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/series/filter_ratios.test.js @@ -73,7 +73,7 @@ describe('ratios(req, panel, series, esQueryConfig, seriesIndex)', () => { }, script: 'params.numerator != null && params.denominator != null &&' + - ' params.denominator > 0 ? params.numerator / params.denominator : 0', + ' params.denominator != 0 ? params.numerator / params.denominator : 0', }, }, 'metric-1-denominator': { @@ -150,7 +150,7 @@ describe('ratios(req, panel, series, esQueryConfig, seriesIndex)', () => { }, script: 'params.numerator != null && params.denominator != null &&' + - ' params.denominator > 0 ? params.numerator / params.denominator : 0', + ' params.denominator != 0 ? params.numerator / params.denominator : 0', }, }, 'metric-1-denominator': { diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/filter_ratios.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/filter_ratios.ts index a897232b27554..3f69c7ec0b99b 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/filter_ratios.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/request_processors/table/filter_ratios.ts @@ -63,7 +63,7 @@ export const filterRatios: TableRequestProcessorsFunction = ({ denominator: denominatorPath, }, script: - 'params.numerator != null && params.denominator != null && params.denominator > 0 ? params.numerator / params.denominator : 0', + 'params.numerator != null && params.denominator != null && params.denominator != 0 ? params.numerator / params.denominator : 0', }, }); }); From 3b6177debf09593742479b3ed7f5b4d8f7d81b2e Mon Sep 17 00:00:00 2001 From: Marco Antonio Ghiani Date: Tue, 28 Feb 2023 17:10:49 +0100 Subject: [PATCH 057/131] [Infrastructure UI] Functional tests Hosts View Alerts tab (#152228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📓 Summary Closes #150741 - Add infra alerts mock file - Add initial functional tests for the Alerts Tab - Remove duplicated tests by the role as they are inclusive of the same privileges - Restructure existing tests to **cut execution time by ~50%** Before | After :-------------------------:|:-------------------------: before | after --------- Co-authored-by: Marco Antonio Ghiani --- .../tabs/alerts/alerts_tab_content.tsx | 2 +- .../components/tabs/alerts_tab_badge.tsx | 6 +- .../test/functional/apps/infra/constants.ts | 2 + .../test/functional/apps/infra/hosts_view.ts | 267 +++--- .../es_archives/infra/alerts/data.json.gz | Bin 0 -> 1990 bytes .../es_archives/infra/alerts/mappings.json | 776 ++++++++++++++++++ .../page_objects/infra_hosts_view.ts | 27 + 7 files changed, 956 insertions(+), 124 deletions(-) create mode 100644 x-pack/test/functional/es_archives/infra/alerts/data.json.gz create mode 100644 x-pack/test/functional/es_archives/infra/alerts/mappings.json diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx index cb31f2c5e9102..7933d3bdb9f3c 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts/alerts_tab_content.tsx @@ -49,7 +49,7 @@ export const AlertsTabContent = () => { return ( - + diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts_tab_badge.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts_tab_badge.tsx index 534d28e671fe3..1333c5b5c3439 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts_tab_badge.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/tabs/alerts_tab_badge.tsx @@ -40,7 +40,11 @@ export const AlertsTabBadge = () => { typeof alertsCount?.activeAlertCount === 'number' && alertsCount.activeAlertCount > 0; return shouldRenderBadge ? ( - + {alertsCount?.activeAlertCount} ) : null; diff --git a/x-pack/test/functional/apps/infra/constants.ts b/x-pack/test/functional/apps/infra/constants.ts index 248c4f49a16c7..b1739f9a489d7 100644 --- a/x-pack/test/functional/apps/infra/constants.ts +++ b/x-pack/test/functional/apps/infra/constants.ts @@ -42,3 +42,5 @@ export const ML_JOB_IDS = [ ]; export const HOSTS_LINK_LOCAL_STORAGE_KEY = 'inventoryUI:hostsLinkClicked'; + +export const HOSTS_VIEW_PATH = 'metrics/hosts'; diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/test/functional/apps/infra/hosts_view.ts index 4f3166c80afb9..1f1773505ffef 100644 --- a/x-pack/test/functional/apps/infra/hosts_view.ts +++ b/x-pack/test/functional/apps/infra/hosts_view.ts @@ -6,9 +6,11 @@ */ import expect from '@kbn/expect'; +import { enableInfrastructureHostsView } from '@kbn/observability-plugin/common'; +import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED } from '@kbn/rule-data-utils'; import moment from 'moment'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { DATES, HOSTS_LINK_LOCAL_STORAGE_KEY } from './constants'; +import { DATES, HOSTS_LINK_LOCAL_STORAGE_KEY, HOSTS_VIEW_PATH } from './constants'; const START_DATE = moment.utc(DATES.metricsAndLogs.hosts.min); const END_DATE = moment.utc(DATES.metricsAndLogs.hosts.max); @@ -18,6 +20,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); const browser = getService('browser'); + const find = getService('find'); const security = getService('security'); const pageObjects = getPageObjects([ 'common', @@ -29,9 +32,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ]); // Helpers + const setHostViewEnabled = (value: boolean = true) => + kibanaServer.uiSettings.update({ [enableInfrastructureHostsView]: value }); - const loginWithReadOnlyUserAndNavigateToInfra = async () => { - await security.role.create('global_hosts_read_privileges_role', { + const loginWithReadOnlyUser = async () => { + const roleCreation = security.role.create('global_hosts_read_privileges_role', { elasticsearch: { indices: [{ names: ['metricbeat-*'], privileges: ['read', 'view_index_metadata'] }], }, @@ -46,13 +51,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ], }); - await security.user.create('global_hosts_read_privileges_user', { + const userCreation = security.user.create('global_hosts_read_privileges_user', { password: 'global_hosts_read_privileges_user-password', roles: ['global_hosts_read_privileges_role'], full_name: 'test user', }); - await pageObjects.security.forceLogout(); + const logout = pageObjects.security.forceLogout(); + + await Promise.all([roleCreation, userCreation, logout]); await pageObjects.security.login( 'global_hosts_read_privileges_user', @@ -61,87 +68,55 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expectSpaceSelector: false, } ); - - await browser.removeLocalStorageItem(HOSTS_LINK_LOCAL_STORAGE_KEY); - await pageObjects.common.navigateToApp('infraOps'); }; - const logoutAndDeleteReadOnlyUser = async () => { - await pageObjects.security.forceLogout(); - await Promise.all([ + const logoutAndDeleteReadOnlyUser = () => + Promise.all([ + pageObjects.security.forceLogout(), security.role.delete('global_hosts_read_privileges_role'), security.user.delete('global_hosts_read_privileges_user'), ]); - }; - const navigateAndDisableHostView = async () => { - await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - await browser.removeLocalStorageItem(HOSTS_LINK_LOCAL_STORAGE_KEY); - await pageObjects.common.navigateToApp('infraOps'); - await pageObjects.common.navigateToUrl('management', 'kibana/settings', { - basePath: `/s/default`, - ensureCurrentUrl: false, - shouldLoginIfPrompted: false, - shouldUseHashForSubUrl: false, - }); - await pageObjects.settings.toggleAdvancedSettingCheckbox( - 'observability:enableInfrastructureHostsView', - false - ); - return esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - }; - - const navigateAndEnableHostView = async () => { - await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - await browser.removeLocalStorageItem(HOSTS_LINK_LOCAL_STORAGE_KEY); - await pageObjects.common.navigateToApp('infraOps'); - await pageObjects.infraHome.clickDismissKubernetesTourButton(); - await pageObjects.infraHostsView.clickTryHostViewLink(); - await pageObjects.infraHostsView.clickEnableHostViewButton(); - }; + const enableHostView = () => pageObjects.infraHostsView.clickEnableHostViewButton(); // Tests - describe('Hosts view', function () { + describe('Hosts View', function () { this.tags('includeFirefox'); + before(async () => { - await kibanaServer.savedObjects.cleanStandardList(); + await Promise.all([ + esArchiver.load('x-pack/test/functional/es_archives/infra/alerts'), + esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'), + kibanaServer.savedObjects.cleanStandardList(), + ]); }); - describe('shows hosts view landing page for admin', () => { - before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - await pageObjects.common.navigateToApp('infraOps'); - await pageObjects.infraHome.clickDismissKubernetesTourButton(); - await pageObjects.infraHostsView.clickTryHostViewBadge(); - }); - after(async () => { - await browser.removeLocalStorageItem(HOSTS_LINK_LOCAL_STORAGE_KEY); - return esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - }); + after(() => { + esArchiver.unload('x-pack/test/functional/es_archives/infra/alerts'); + esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + browser.removeLocalStorageItem(HOSTS_LINK_LOCAL_STORAGE_KEY); + }); - it('should show hosts landing page with enable button when the hosts view is disabled', async () => { - const landingPageEnableButton = - await pageObjects.infraHostsView.getHostsLandingPageEnableButton(); - const landingPageEnableButtonText = await landingPageEnableButton.getVisibleText(); - expect(landingPageEnableButtonText).to.eql('Enable hosts view'); - }); + it('should be accessible from the Inventory page', async () => { + await pageObjects.common.navigateToApp('infraOps'); + await pageObjects.infraHome.clickDismissKubernetesTourButton(); + await pageObjects.infraHostsView.clickTryHostViewBadge(); + + const pageUrl = await browser.getCurrentUrl(); + + expect(pageUrl).to.contain(HOSTS_VIEW_PATH); }); - describe('should show hosts view landing page for user with read permission', () => { - before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs'); - await loginWithReadOnlyUserAndNavigateToInfra(); - await pageObjects.infraHome.clickDismissKubernetesTourButton(); - await pageObjects.infraHostsView.clickTryHostViewBadge(); - }); - after(async () => { - // NOTE: Logout needs to happen before anything else to avoid flaky behavior - await logoutAndDeleteReadOnlyUser(); - return esArchiver.unload('x-pack/test/functional/es_archives/infra/metrics_and_logs'); + describe('#Landing page', () => { + beforeEach(() => { + setHostViewEnabled(false); }); - it('should show hosts landing page with callout when the hosts view is disabled', async () => { + it('as a user with read permission, should show hosts landing page with callout when the hosts view is disabled', async () => { + await loginWithReadOnlyUser(); + await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); + const landingPageDisabled = await pageObjects.infraHostsView.getHostsLandingPageDisabled(); const learnMoreDocsUrl = await pageObjects.infraHostsView.getHostsLandingPageDocsLink(); const parsedUrl = new URL(learnMoreDocsUrl); @@ -151,33 +126,57 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(landingPageDisabled).to.contain( 'Your user role doesn’t have sufficient privileges to enable this feature' ); + + await logoutAndDeleteReadOnlyUser(); + }); + + it('as an admin, should see an enable button when the hosts view is disabled', async () => { + await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); + + const landingPageEnableButton = + await pageObjects.infraHostsView.getHostsLandingPageEnableButton(); + const landingPageEnableButtonText = await landingPageEnableButton.getVisibleText(); + expect(landingPageEnableButtonText).to.eql('Enable hosts view'); + }); + + it('as an admin, should be able to enable the hosts view feature', async () => { + await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); + await enableHostView(); + + const titleElement = await find.byCssSelector('h1'); + const title = await titleElement.getVisibleText(); + + expect(title).to.contain('Hosts'); }); }); - describe('enables hosts view page and checks content', () => { + describe('#Page Content', () => { before(async () => { - await navigateAndEnableHostView(); + await setHostViewEnabled(true); + await loginWithReadOnlyUser(); + await pageObjects.common.navigateToApp(HOSTS_VIEW_PATH); await pageObjects.timePicker.setAbsoluteRange( START_DATE.format(timepickerFormat), END_DATE.format(timepickerFormat) ); }); + after(async () => { - await navigateAndDisableHostView(); + await logoutAndDeleteReadOnlyUser(); }); - describe('should show hosts page for admin user and see the page content', async () => { - it('should render the correct page title', async () => { - const documentTitle = await browser.getTitle(); - expect(documentTitle).to.contain('Hosts - Infrastructure - Observability - Elastic'); - }); + it('should render the correct page title', async () => { + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain('Hosts - Infrastructure - Observability - Elastic'); + }); - it('should have six hosts', async () => { - const hosts = await pageObjects.infraHostsView.getHostsTableData(); - expect(hosts.length).to.equal(6); - }); + it('should render a table with 6 hosts', async () => { + const hosts = await pageObjects.infraHostsView.getHostsTableData(); + expect(hosts.length).to.equal(6); + }); - it('should load 5 metrics trend tiles', async () => { + describe('KPI tiles', () => { + it('should render 5 metrics trend tiles', async () => { const hosts = await pageObjects.infraHostsView.getAllMetricsTrendTiles(); expect(hosts.length).to.equal(5); }); @@ -195,56 +194,80 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); }); - }); - describe('should show hosts page for read only user and see the page content', async () => { - before(async () => { - await navigateAndEnableHostView(); - await loginWithReadOnlyUserAndNavigateToInfra(); - await browser.removeLocalStorageItem(HOSTS_LINK_LOCAL_STORAGE_KEY); - await pageObjects.infraHostsView.clickTryHostViewLink(); - await pageObjects.timePicker.setAbsoluteRange( - START_DATE.format(timepickerFormat), - END_DATE.format(timepickerFormat) - ); - }); - after(async () => { - // NOTE: Logout needs to happen before anything else to avoid flaky behavior - await logoutAndDeleteReadOnlyUser(); - await navigateAndDisableHostView(); - }); + describe('Metrics Tab', () => { + it('should load 8 lens metric charts', async () => { + const metricCharts = await pageObjects.infraHostsView.getAllMetricsCharts(); + expect(metricCharts.length).to.equal(8); + }); - it('should have six hosts', async () => { - const hosts = await pageObjects.infraHostsView.getHostsTableData(); - expect(hosts.length).to.equal(6); + it('should have an option to open the chart in lens', async () => { + await pageObjects.infraHostsView.getOpenInLensOption(); + }); }); - it('should load 5 metrics trend tiles', async () => { - const hosts = await pageObjects.infraHostsView.getAllMetricsTrendTiles(); - expect(hosts.length).to.equal(5); - }); + describe('Alerts Tab', () => { + const observability = getService('observability'); + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + + const ACTIVE_ALERTS = 6; + const RECOVERED_ALERTS = 4; + const ALL_ALERTS = ACTIVE_ALERTS + RECOVERED_ALERTS; + const COLUMNS = 5; - [ - { metric: 'hosts', value: '6' }, - { metric: 'cpu', value: '0.8%' }, - { metric: 'memory', value: '16.8%' }, - { metric: 'tx', value: '0 bit/s' }, - { metric: 'rx', value: '0 bit/s' }, - ].forEach(({ metric, value }) => { - it(`${metric} tile should show ${value}`, async () => { - const tileValue = await pageObjects.infraHostsView.getMetricsTrendTileValue(metric); - expect(tileValue).to.eql(value); + before(async () => { + await pageObjects.infraHostsView.visitAlertTab(); }); - }); - describe('Lens charts', () => { - it('should load 8 lens metric charts', async () => { - const metricCharts = await pageObjects.infraHostsView.getAllMetricsCharts(); - expect(metricCharts.length).to.equal(8); + it('should correctly load the Alerts tab section when clicking on it', async () => { + testSubjects.existOrFail('hostsView-alerts'); }); - it('should have an option to open the chart in lens', async () => { - await pageObjects.infraHostsView.getOpenInLensOption(); + it('should correctly render a badge with the active alerts count', async () => { + const alertsCountBadge = await pageObjects.infraHostsView.getAlertsTabCountBadge(); + const alertsCount = await alertsCountBadge.getVisibleText(); + + expect(alertsCount).to.be('6'); + }); + + describe('#FilterButtonGroup', () => { + it('can be filtered to only show "active" alerts using the filter button', async () => { + await pageObjects.infraHostsView.setAlertStatusFilter(ALERT_STATUS_ACTIVE); + await retry.try(async () => { + const tableRows = await observability.alerts.common.getTableCellsInRows(); + expect(tableRows.length).to.be(ACTIVE_ALERTS); + }); + }); + + it('can be filtered to only show "recovered" alerts using the filter button', async () => { + await pageObjects.infraHostsView.setAlertStatusFilter(ALERT_STATUS_RECOVERED); + await retry.try(async () => { + const tableRows = await observability.alerts.common.getTableCellsInRows(); + expect(tableRows.length).to.be(RECOVERED_ALERTS); + }); + }); + + it('can be filtered to only show "all" alerts using the filter button', async () => { + await pageObjects.infraHostsView.setAlertStatusFilter(); + await retry.try(async () => { + const tableRows = await observability.alerts.common.getTableCellsInRows(); + expect(tableRows.length).to.be(ALL_ALERTS); + }); + }); + }); + + describe('#AlertsTable', () => { + it('should correctly render', async () => { + await observability.alerts.common.getTableOrFail(); + }); + + it('should renders the correct number of cells', async () => { + await retry.try(async () => { + const cells = await observability.alerts.common.getTableCells(); + expect(cells.length).to.be(ALL_ALERTS * COLUMNS); + }); + }); }); }); }); diff --git a/x-pack/test/functional/es_archives/infra/alerts/data.json.gz b/x-pack/test/functional/es_archives/infra/alerts/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..5410bb6abe5b0374ef051943ecc65f6b009971c5 GIT binary patch literal 1990 zcmV;%2RZm3iwFoLz5HVU17u-zVJ>QOZ*BnXoLg_>xE06W=Tis<7MLlP0`DU8P!#CX z0$rd$cVD_040v^fv8_~+GffBc-Sy%g$uaMeG^NA;YwMFD0cyInqj1+XDDdzjaQkBOtsmY94jCG z+hj`fRUOKeS)^tW%DO^@twMQYY`)0r+jLRPt4)j#(X1CW!p#@iSgMM3=^p9=A%Cm$ zWvFViyl!iSi9!S;lKn#T1!otOrjY;NcljZGxCyH|HLlK!Rg=RliYh#f{tPv4BCC83 zm3@f)oLjRpT@_QmE=^-4U00BnF-0iP2$c46^3a)lQbX~)hL3YKjo%ehUzMS{Di)2I zOuU+W(`$;qoHSoStF2r}yZ-#kmI{=?R9#Cco<07BBc6%7JDL4$&4Tg^^)~lTbuGd{=tvt(|z=&Zg5h1}L zg`-Era}tEoT*2w_Z#w0^VRKuot42AH=zvM8hlg90iOQU#FwJ{92doxPYtp-(+q>rH+q-vP z`(w^2uC%}&Nf#vI&|OGFw?Ko_m}TDkjObIqT=U<}J~&6HByD96#VgKrFJQ%d5o|Cu znwM%WU!@nA9g43c7G?6dn8On7HTGCk@>as&K)e2^0y!#CAP$|w-eltI=qj54N`w9XJ{it~b; z7K{;jNXlW^4|A{2%NkRsIx~ArviJ3u;y3}8St&VVEx_zi0&IW}j}KrBdn+wWQ6+H} zapyg<%sRxQ-!Fp4uxRW=l0{rLsMX;1h9OWWvmTJSpB*%xOMkZ-xSef;$=#+Y(4Gk@C%Id z%h|SFoxrU)pm-qfdyYE$LD4QX!!b>V1JEr^bJSad1cOEZU_ zp0@+C%XTxroPGP&RH*ZspSr|%jsZ9TxTsA=siAt(f}UDnpqH;gFEMx_=|R*$ zu#`VngI7zR!+S7|tU0nMFbcg}AW+8Kp3y3YK$@(Tu6V`>=nK96WCM z?-ql>Do_TWSG`2wdCJ4A2t-PsYrt!TPZBUmz`07m01A#z0x0Ie1#ggaBEWJeMr52L z$Z^kMNo1AA_CzFLZz}@MNqd-}pBTKp>0I4bby%hVBCsFI^xD<0p`8%%!wYaHoZipy zx0d^qbwY*aI}SO0*MapDn%PSE(q8v8vz=zP)68~@g7k;z_!LB7 zn9oz{5U4yw+)jAPpJ^pB z>Byub+jV3BO2?-okwvAYX*!2E#I54UXs?lXhR5iG;ri@$w3NnV$BXx4f2a;Bl1&fQ zClQ%MWPpea;OO{7#8K%ChA#1jw4X0%k@Z3&!xW~3$e+gbIZL^x;oSDLSf;Qz@B!a9eOrN%`-kPz z+X|=qwnAT?4RGo4@r-I=sqr2;#Vo*FLJ#qvkzztxA>dk{-3tp!10Q{STbPmio!<#( Date: Tue, 28 Feb 2023 09:23:42 -0700 Subject: [PATCH 058/131] =?UTF-8?q?unskip=20Chrome=20UI=20Functional=20Tes?= =?UTF-8?q?ts.test/functional/apps/dashboard/group3/dashboard=5Fstate?= =?UTF-8?q?=C2=B7ts=20(#152245)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes https://github.com/elastic/kibana/issues/139762 flaky test runner https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/1965 2 changes where required to get functional tests running * Switch application state updating from string replace to rison decode/encode. `_a` is not longer provided in the URL unless there are unsaved changes to simple string replace did not work in some cases. Using rison decode/encode was easier then handling a lot of if statements around whether `_a` exists before attempting string replace, plus rison decode/encode is a lot more maintainable and robust. * Fix bug where appending `&_a=(panels:())` to URL would not remove panels. Updated logic in sync_dashboard_url_state to handle case where panels has no length. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../url/sync_dashboard_url_state.ts | 29 ++-- .../apps/dashboard/group3/dashboard_state.ts | 142 ++++++++++++++++-- 2 files changed, 145 insertions(+), 26 deletions(-) diff --git a/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts b/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts index 6d90316098fb5..cbfc7271aef41 100644 --- a/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts +++ b/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts @@ -37,28 +37,35 @@ export const isPanelVersionTooOld = (panels: SavedDashboardPanel[]) => { return false; }; +function getPanelsMap(appStateInUrl: SharedDashboardState): DashboardPanelMap | undefined { + if (!appStateInUrl.panels) { + return undefined; + } + + if (appStateInUrl.panels.length === 0) { + return {}; + } + + if (isPanelVersionTooOld(appStateInUrl.panels)) { + pluginServices.getServices().notifications.toasts.addWarning(getPanelTooOldErrorString()); + return undefined; + } + + return convertSavedPanelsToPanelMap(appStateInUrl.panels); +} + /** * Loads any dashboard state from the URL, and removes the state from the URL. */ export const loadAndRemoveDashboardState = ( kbnUrlStateStorage: IKbnUrlStateStorage ): Partial => { - const { - notifications: { toasts }, - } = pluginServices.getServices(); const rawAppStateInUrl = kbnUrlStateStorage.get( DASHBOARD_STATE_STORAGE_KEY ); if (!rawAppStateInUrl) return {}; - let panelsMap: DashboardPanelMap | undefined; - if (rawAppStateInUrl.panels && rawAppStateInUrl.panels.length > 0) { - if (isPanelVersionTooOld(rawAppStateInUrl.panels)) { - toasts.addWarning(getPanelTooOldErrorString()); - } else { - panelsMap = convertSavedPanelsToPanelMap(rawAppStateInUrl.panels); - } - } + const panelsMap = getPanelsMap(rawAppStateInUrl); const nextUrl = replaceUrlHashQuery(window.location.href, (hashQuery) => { delete hashQuery[DASHBOARD_STATE_STORAGE_KEY]; diff --git a/test/functional/apps/dashboard/group3/dashboard_state.ts b/test/functional/apps/dashboard/group3/dashboard_state.ts index c280de155be82..7839315cb2239 100644 --- a/test/functional/apps/dashboard/group3/dashboard_state.ts +++ b/test/functional/apps/dashboard/group3/dashboard_state.ts @@ -8,13 +8,15 @@ import expect from '@kbn/expect'; import chroma from 'chroma-js'; - +import rison from '@kbn/rison'; import { DEFAULT_PANEL_WIDTH } from '@kbn/dashboard-plugin/public/dashboard_constants'; +import type { SharedDashboardState } from '@kbn/dashboard-plugin/common'; import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME } from '../../../page_objects/dashboard_page'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ + 'common', 'dashboard', 'visualize', 'header', @@ -31,6 +33,36 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const elasticChart = getService('elasticChart'); const dashboardAddPanel = getService('dashboardAddPanel'); const xyChartSelector = 'xyVisChart'; + const log = getService('log'); + + const updateAppStateQueryParam = ( + url: string, + setAppState: (appState: Partial) => Partial + ) => { + log.debug(`updateAppStateQueryParam, before url: ${url}`); + + // Using lastIndexOf because URL may have 2 sets of query parameters. + // 1) server query parameters, '_t' + // 2) client query parameters, '_g' and '_a'. Anything after the '#' in a URL is used by the client + // Example shape of URL http://localhost:5620/app/dashboards?_t=12345#/create?_g=() + const clientQueryParamsStartIndex = url.lastIndexOf('?'); + if (clientQueryParamsStartIndex === -1) { + throw Error(`Unable to locate query parameters in URL: ${url}`); + } + const urlBeforeClientQueryParams = url.substring(0, clientQueryParamsStartIndex); + const urlParams = new URLSearchParams(url.substring(clientQueryParamsStartIndex + 1)); + const appState: Partial = urlParams.has('_a') + ? (rison.decode(urlParams.get('_a')!) as Partial) + : {}; + const newAppState = { + ...appState, + ...setAppState(appState), + }; + urlParams.set('_a', rison.encode(newAppState)); + const newUrl = urlBeforeClientQueryParams + '?' + urlParams.toString(); + log.debug(`updateAppStateQueryParam, after url: ${newUrl}`); + return newUrl; + }; const enableNewChartLibraryDebug = async (force = false) => { if ((await PageObjects.visChart.isNewChartsLibraryEnabled()) || force) { @@ -39,10 +71,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } }; - // Failing: See https://github.com/elastic/kibana/issues/139762 - describe.skip('dashboard state', function describeIndexTests() { - // Used to track flag before and after reset - + describe('dashboard state', function () { before(async function () { await PageObjects.dashboard.initTests(); await PageObjects.dashboard.preserveCrossAppState(); @@ -140,8 +169,17 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('Saved search will update when the query is changed in the URL', async () => { const currentQuery = await queryBar.getQueryString(); expect(currentQuery).to.equal(''); - const currentUrl = await getUrlFromShare(); - const newUrl = currentUrl.replace(`query:''`, `query:'abc12345678910'`); + const newUrl = updateAppStateQueryParam( + await getUrlFromShare(), + (appState: Partial) => { + return { + query: { + language: 'kuery', + query: 'abc12345678910', + }, + }; + } + ); // We need to add a timestamp to the URL because URL changes now only work with a hard refresh. await browser.get(newUrl.toString()); @@ -153,9 +191,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); const getUrlFromShare = async () => { + log.debug(`getUrlFromShare`); await PageObjects.share.clickShareTopNavButton(); const sharedUrl = await PageObjects.share.getSharedUrl(); await PageObjects.share.clickShareTopNavButton(); + log.debug(`sharedUrl: ${sharedUrl}`); return sharedUrl; }; @@ -177,11 +217,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const changeQuery = async (useHardRefresh: boolean, newQuery: string) => { await queryBar.clickQuerySubmitButton(); - const oldQuery = await queryBar.getQueryString(); const currentUrl = await getUrlFromShare(); - const newUrl = currentUrl.replace(`query:'${oldQuery}'`, `query:'${newQuery}'`); + const newUrl = updateAppStateQueryParam( + currentUrl, + (appState: Partial) => { + return { + query: { + language: 'kuery', + query: newQuery, + }, + }; + } + ); await browser.get(newUrl.toString(), !useHardRefresh); + await PageObjects.dashboard.waitForRenderComplete(); const queryBarContentsAfterRefresh = await queryBar.getQueryString(); expect(queryBarContentsAfterRefresh).to.equal(newQuery); }; @@ -202,9 +252,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await dashboardAddPanel.addVisualization(PIE_CHART_VIS_NAME); const currentUrl = await getUrlFromShare(); const currentPanelDimensions = await PageObjects.dashboard.getPanelDimensions(); - const newUrl = currentUrl.replace( - `w:${DEFAULT_PANEL_WIDTH}`, - `w:${DEFAULT_PANEL_WIDTH * 2}` + const newUrl = updateAppStateQueryParam( + currentUrl, + (appState: Partial) => { + log.debug(JSON.stringify(appState, null, ' ')); + return { + panels: (appState.panels ?? []).map((panel) => { + return { + ...panel, + gridData: { + ...panel.gridData, + w: + panel.gridData.w === DEFAULT_PANEL_WIDTH + ? DEFAULT_PANEL_WIDTH * 2 + : panel.gridData.w, + }, + }; + }), + }; + } ); await hardRefresh(newUrl); @@ -229,7 +295,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('when removing a panel', async function () { await PageObjects.dashboard.waitForRenderComplete(); const currentUrl = await getUrlFromShare(); - const newUrl = currentUrl.replace(/panels:\!\(.*\),query/, 'panels:!(),query'); + const newUrl = updateAppStateQueryParam( + currentUrl, + (appState: Partial) => { + return { + panels: [], + }; + } + ); await hardRefresh(newUrl); await retry.try(async () => { @@ -255,7 +328,28 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); await PageObjects.visChart.selectNewLegendColorChoice('#F9D9F9'); const currentUrl = await getUrlFromShare(); - const newUrl = currentUrl.replace('F9D9F9', 'FFFFFF'); + const newUrl = updateAppStateQueryParam( + currentUrl, + (appState: Partial) => { + return { + panels: (appState.panels ?? []).map((panel) => { + return { + ...panel, + embeddableConfig: { + ...(panel.embeddableConfig ?? {}), + vis: { + ...((panel.embeddableConfig?.vis as object) ?? {}), + colors: { + ...((panel.embeddableConfig?.vis as { colors: object })?.colors ?? {}), + ['80000']: 'FFFFFF', + }, + }, + }, + }; + }), + }; + } + ); await hardRefresh(newUrl); await PageObjects.header.waitUntilLoadingHasFinished(); @@ -280,7 +374,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('resets a pie slice color to the original when removed', async function () { const currentUrl = await getUrlFromShare(); - const newUrl = currentUrl.replace(`'80000':%23FFFFFF`, ''); + const newUrl = updateAppStateQueryParam( + currentUrl, + (appState: Partial) => { + return { + panels: (appState.panels ?? []).map((panel) => { + return { + ...panel, + embeddableConfig: { + ...(panel.embeddableConfig ?? {}), + vis: { + ...((panel.embeddableConfig?.vis as object) ?? {}), + colors: {}, + }, + }, + }; + }), + }; + } + ); await hardRefresh(newUrl); await PageObjects.header.waitUntilLoadingHasFinished(); From 391220a8158529bcb5394da7002b26ec9d416788 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 28 Feb 2023 09:29:47 -0700 Subject: [PATCH 059/131] [maps] remove Maps data view telemetry (#152124) Fixes https://github.com/elastic/kibana/issues/152121 Removes data view telemetry collection --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../maps/server/kibana_server_services.ts | 9 +- .../maps_telemetry/collectors/register.ts | 4 - .../server/maps_telemetry/find_maps.test.ts | 4 +- .../index_pattern_stats/index.ts | 9 -- .../index_pattern_stats_collector.test.ts | 94 ------------- .../index_pattern_stats_collector.ts | 130 ------------------ .../index_pattern_stats/types.ts | 13 -- .../server/maps_telemetry/maps_telemetry.ts | 22 +-- x-pack/plugins/maps/server/plugin.ts | 2 +- x-pack/plugins/maps/tsconfig.json | 1 - .../schema/xpack_plugins.json | 12 -- .../apis/maps/maps_telemetry.ts | 21 ++- 12 files changed, 23 insertions(+), 298 deletions(-) delete mode 100644 x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index.ts delete mode 100644 x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.test.ts delete mode 100644 x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.ts delete mode 100644 x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/types.ts diff --git a/x-pack/plugins/maps/server/kibana_server_services.ts b/x-pack/plugins/maps/server/kibana_server_services.ts index 84cedeb721824..ef12c3edaa81f 100644 --- a/x-pack/plugins/maps/server/kibana_server_services.ts +++ b/x-pack/plugins/maps/server/kibana_server_services.ts @@ -6,19 +6,12 @@ */ import { CoreStart } from '@kbn/core/server'; -import { StartDeps } from './types'; let coreStart: CoreStart; -let pluginsStart: StartDeps; -export function setStartServices(core: CoreStart, plugins: StartDeps) { +export function setStartServices(core: CoreStart) { coreStart = core; - pluginsStart = plugins; } export const getSavedObjectClient = (extraTypes?: string[]) => { return coreStart.savedObjects.createInternalRepository(extraTypes); }; - -export const getIndexPatternsServiceFactory = () => - pluginsStart.data.indexPatterns.dataViewsServiceFactory; -export const getElasticsearch = () => coreStart.elasticsearch; diff --git a/x-pack/plugins/maps/server/maps_telemetry/collectors/register.ts b/x-pack/plugins/maps/server/maps_telemetry/collectors/register.ts index 9f2e520c428a2..77d1112f89817 100644 --- a/x-pack/plugins/maps/server/maps_telemetry/collectors/register.ts +++ b/x-pack/plugins/maps/server/maps_telemetry/collectors/register.ts @@ -18,10 +18,6 @@ export function registerMapsUsageCollector(usageCollection?: UsageCollectionSetu isReady: () => true, fetch: async () => await getMapsTelemetry(), schema: { - indexPatternsWithGeoFieldCount: { type: 'long' }, - indexPatternsWithGeoPointFieldCount: { type: 'long' }, - indexPatternsWithGeoShapeFieldCount: { type: 'long' }, - geoShapeAggLayersCount: { type: 'long' }, mapsTotalCount: { type: 'long' }, timeCaptured: { type: 'date' }, layerTypes: { diff --git a/x-pack/plugins/maps/server/maps_telemetry/find_maps.test.ts b/x-pack/plugins/maps/server/maps_telemetry/find_maps.test.ts index acc9d11c66d4a..64215045bd3eb 100644 --- a/x-pack/plugins/maps/server/maps_telemetry/find_maps.test.ts +++ b/x-pack/plugins/maps/server/maps_telemetry/find_maps.test.ts @@ -29,7 +29,7 @@ function getMockSavedObjectsClient(perPage: number) { } as unknown as ISavedObjectsRepository; } -test('should process all map saved objects with single page', async () => { +test('should process all map saved objects with a single page', async () => { const foundMapIds: string[] = []; await findMaps(getMockSavedObjectsClient(20), async (savedObject) => { foundMapIds.push(savedObject.id); @@ -43,7 +43,7 @@ test('should process all map saved objects with single page', async () => { ]); }); -test('should process all map saved objects with with paging', async () => { +test('should process all map saved objects with paging', async () => { const foundMapIds: string[] = []; await findMaps(getMockSavedObjectsClient(2), async (savedObject) => { foundMapIds.push(savedObject.id); diff --git a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index.ts b/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index.ts deleted file mode 100644 index 9e4c0ef21fdea..0000000000000 --- a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export { IndexPatternStatsCollector } from './index_pattern_stats_collector'; -export type { IndexPatternStats } from './types'; diff --git a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.test.ts b/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.test.ts deleted file mode 100644 index 9877c29bc5951..0000000000000 --- a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.test.ts +++ /dev/null @@ -1,94 +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 { asyncForEach } from '@kbn/std'; -// @ts-ignore -import mapSavedObjects from '../../../common/telemetry/test_resources/sample_map_saved_objects.json'; -import { DataViewsService } from '@kbn/data-views-plugin/common'; -import { IndexPatternStatsCollector } from './index_pattern_stats_collector'; - -test('returns zeroed telemetry data when there are no saved objects', async () => { - const mockIndexPatternService = { - getIds: () => { - return []; - }, - } as unknown as DataViewsService; - const statsCollector = new IndexPatternStatsCollector(mockIndexPatternService); - const stats = await statsCollector.getStats(); - expect(stats).toEqual({ - geoShapeAggLayersCount: 0, - indexPatternsWithGeoFieldCount: 0, - indexPatternsWithGeoPointFieldCount: 0, - indexPatternsWithGeoShapeFieldCount: 0, - }); -}); - -test('returns expected telemetry data from saved objects', async () => { - const mockIndexPatternService = { - get: (id: string) => { - if (id === 'd3d7af60-4c81-11e8-b3d7-01146121b73d') { - return { - getFieldByName: (name: string) => { - return { type: 'geo_point' }; - }, - fields: { - getByType: (type: string) => { - return type === 'geo_point' ? [{}] : []; - }, - }, - }; - } - - if (id === '4a7f6010-0aed-11ea-9dd2-95afd7ad44d4') { - return { - getFieldByName: (name: string) => { - return { type: 'geo_shape' }; - }, - fields: { - getByType: (type: string) => { - return type === 'geo_shape' ? [{}] : []; - }, - }, - }; - } - - if (id === 'indexPatternWithNoGeoFields') { - return { - getFieldByName: (name: string) => { - return null; - }, - fields: { - getByType: (type: string) => { - return []; - }, - }, - }; - } - - throw new Error('Index pattern not found'); - }, - getIds: () => { - return [ - 'd3d7af60-4c81-11e8-b3d7-01146121b73d', - '4a7f6010-0aed-11ea-9dd2-95afd7ad44d4', - 'indexPatternWithNoGeoFields', - 'missingIndexPattern', - ]; - }, - } as unknown as DataViewsService; - const statsCollector = new IndexPatternStatsCollector(mockIndexPatternService); - await asyncForEach(mapSavedObjects, async (savedObject) => { - await statsCollector.push(savedObject); - }); - const stats = await statsCollector.getStats(); - expect(stats).toEqual({ - geoShapeAggLayersCount: 2, // index pattern '4a7f6010-0aed-11ea-9dd2-95afd7ad44d4' with geo_shape field is used in 2 maps with geo_tile_grid aggregation - indexPatternsWithGeoFieldCount: 2, - indexPatternsWithGeoPointFieldCount: 1, - indexPatternsWithGeoShapeFieldCount: 1, - }); -}); 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 deleted file mode 100644 index 2b8047cdaf41f..0000000000000 --- a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/index_pattern_stats_collector.ts +++ /dev/null @@ -1,130 +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 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 { SCALING_TYPES, SOURCE_TYPES } from '../../../common/constants'; -import { injectReferences } from '../../../common/migrations/references'; -import { - ESGeoGridSourceDescriptor, - ESSearchSourceDescriptor, - LayerDescriptor, -} from '../../../common/descriptor_types'; -import type { MapSavedObjectAttributes } from '../../../common/map_saved_object_type'; -import { IndexPatternStats } from './types'; - -/* - * Use IndexPatternStatsCollector instance to track index pattern geospatial field stats. - */ -export class IndexPatternStatsCollector { - private _geoShapeAggCount = 0; - private _indexPatternsService: DataViewsService; - - constructor(indexPatternService: DataViewsService) { - this._indexPatternsService = indexPatternService; - } - - async push(savedObject: SavedObject) { - let layerList: LayerDescriptor[] = []; - try { - const { attributes } = injectReferences(savedObject); - if (!attributes.layerListJSON) { - return; - } - layerList = JSON.parse(attributes.layerListJSON); - } catch (e) { - return; - } - - let geoShapeAggCountPerMap = 0; - await asyncForEach(layerList, async (layerDescriptor) => { - if (await this._isGeoShapeAggLayer(layerDescriptor)) { - geoShapeAggCountPerMap++; - } - }); - this._geoShapeAggCount += geoShapeAggCountPerMap; - } - - async getStats(): Promise { - let geoCount = 0; - let pointCount = 0; - let shapeCount = 0; - - const indexPatternIds = await this._indexPatternsService.getIds(); - await asyncForEach(indexPatternIds, async (indexPatternId) => { - let indexPattern; - try { - indexPattern = await this._indexPatternsService.get(indexPatternId); - } catch (e) { - return; - } - const pointFields = indexPattern.fields.getByType(KBN_FIELD_TYPES.GEO_POINT); - const shapeFields = indexPattern.fields.getByType(KBN_FIELD_TYPES.GEO_SHAPE); - if (pointFields.length || shapeFields.length) { - geoCount++; - } - if (pointFields.length) { - pointCount++; - } - if (shapeFields.length) { - shapeCount++; - } - }); - - return { - // Tracks whether user uses Gold+ functionality of aggregating on geo_shape field - geoShapeAggLayersCount: this._geoShapeAggCount, - indexPatternsWithGeoFieldCount: geoCount, - indexPatternsWithGeoPointFieldCount: pointCount, - indexPatternsWithGeoShapeFieldCount: shapeCount, - }; - } - - async _isFieldGeoShape(indexPatternId: string, geoField: string | undefined): Promise { - if (!geoField || !indexPatternId) { - return false; - } - - let indexPattern; - try { - indexPattern = await this._indexPatternsService.get(indexPatternId); - } catch (e) { - return false; - } - - const field = indexPattern.getFieldByName(geoField); - return !!field && field.type === KBN_FIELD_TYPES.GEO_SHAPE; - } - - async _isGeoShapeAggLayer(layer: LayerDescriptor): Promise { - if (!layer.sourceDescriptor) { - return false; - } - - const sourceDescriptor = layer.sourceDescriptor; - if (sourceDescriptor.type === SOURCE_TYPES.ES_GEO_GRID) { - return await this._isFieldGeoShape( - (sourceDescriptor as ESGeoGridSourceDescriptor).indexPatternId, - (sourceDescriptor as ESGeoGridSourceDescriptor).geoField - ); - } - - if ( - sourceDescriptor.type === SOURCE_TYPES.ES_SEARCH && - (sourceDescriptor as ESSearchSourceDescriptor).scalingType === SCALING_TYPES.CLUSTERS - ) { - return await this._isFieldGeoShape( - (sourceDescriptor as ESSearchSourceDescriptor).indexPatternId, - (sourceDescriptor as ESSearchSourceDescriptor).geoField - ); - } - - return false; - } -} diff --git a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/types.ts b/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/types.ts deleted file mode 100644 index 0a0060606b423..0000000000000 --- a/x-pack/plugins/maps/server/maps_telemetry/index_pattern_stats/types.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export interface IndexPatternStats { - indexPatternsWithGeoFieldCount: number; - indexPatternsWithGeoPointFieldCount: number; - indexPatternsWithGeoShapeFieldCount: number; - geoShapeAggLayersCount: number; -} diff --git a/x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts b/x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts index b7497c010f15f..462f8ca57d692 100644 --- a/x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts +++ b/x-pack/plugins/maps/server/maps_telemetry/maps_telemetry.ts @@ -5,37 +5,19 @@ * 2.0. */ -import { SavedObjectsClient } from '@kbn/core/server'; -import { - getElasticsearch, - getIndexPatternsServiceFactory, - getSavedObjectClient, -} from '../kibana_server_services'; +import { getSavedObjectClient } from '../kibana_server_services'; import { MapStats, MapStatsCollector } from './map_stats'; -import { IndexPatternStats, IndexPatternStatsCollector } from './index_pattern_stats'; import { findMaps } from './find_maps'; -export type MapsUsage = MapStats & IndexPatternStats; - -async function getReadOnlyIndexPatternsService() { - const factory = getIndexPatternsServiceFactory(); - return factory( - new SavedObjectsClient(getSavedObjectClient()), - getElasticsearch().client.asInternalUser - ); -} +export type MapsUsage = MapStats; export async function getMapsTelemetry(): Promise { const mapStatsCollector = new MapStatsCollector(); - const indexPatternService = await getReadOnlyIndexPatternsService(); - const indexPatternStatsCollector = new IndexPatternStatsCollector(indexPatternService); await findMaps(getSavedObjectClient(), async (savedObject) => { mapStatsCollector.push(savedObject.attributes); - await indexPatternStatsCollector.push(savedObject); }); return { - ...(await indexPatternStatsCollector.getStats()), ...mapStatsCollector.getStats(), }; } diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 0fe317beef05e..1dc497a87fdd9 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -207,6 +207,6 @@ export class MapsPlugin implements Plugin { } start(core: CoreStart, plugins: StartDeps) { - setStartServices(core, plugins); + setStartServices(core); } } diff --git a/x-pack/plugins/maps/tsconfig.json b/x-pack/plugins/maps/tsconfig.json index 0505ffb7473c1..8d32c7229a4e0 100644 --- a/x-pack/plugins/maps/tsconfig.json +++ b/x-pack/plugins/maps/tsconfig.json @@ -62,7 +62,6 @@ "@kbn/safer-lodash-set", "@kbn/custom-integrations-plugin", "@kbn/config-schema", - "@kbn/field-types", "@kbn/controls-plugin", "@kbn/shared-ux-router", ], diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 5a94f1361380c..99e466ebbb357 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -5502,18 +5502,6 @@ }, "maps": { "properties": { - "indexPatternsWithGeoFieldCount": { - "type": "long" - }, - "indexPatternsWithGeoPointFieldCount": { - "type": "long" - }, - "indexPatternsWithGeoShapeFieldCount": { - "type": "long" - }, - "geoShapeAggLayersCount": { - "type": "long" - }, "mapsTotalCount": { "type": "long" }, diff --git a/x-pack/test/api_integration/apis/maps/maps_telemetry.ts b/x-pack/test/api_integration/apis/maps/maps_telemetry.ts index d4d4c48c60336..1d63f8872776f 100644 --- a/x-pack/test/api_integration/apis/maps/maps_telemetry.ts +++ b/x-pack/test/api_integration/apis/maps/maps_telemetry.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { estypes } from '@elastic/elasticsearch'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { @@ -24,14 +25,26 @@ export default function ({ getService }: FtrProviderContext) { }) .expect(200); + const geoPointFieldStats = apiResponse.cluster_stats.indices.mappings.field_types.find( + (fieldStat: estypes.ClusterStatsFieldTypes) => { + return fieldStat.name === 'geo_point'; + } + ); + expect(geoPointFieldStats.count).to.be(7); + expect(geoPointFieldStats.index_count).to.be(6); + + const geoShapeFieldStats = apiResponse.cluster_stats.indices.mappings.field_types.find( + (fieldStat: estypes.ClusterStatsFieldTypes) => { + return fieldStat.name === 'geo_shape'; + } + ); + expect(geoShapeFieldStats.count).to.be(3); + expect(geoShapeFieldStats.index_count).to.be(3); + const mapUsage = apiResponse.stack_stats.kibana.plugins.maps; delete mapUsage.timeCaptured; expect(mapUsage).eql({ - geoShapeAggLayersCount: 1, - indexPatternsWithGeoFieldCount: 6, - indexPatternsWithGeoPointFieldCount: 4, - indexPatternsWithGeoShapeFieldCount: 2, mapsTotalCount: 27, basemaps: {}, joins: { term: { min: 1, max: 1, total: 3, avg: 0.1111111111111111 } }, From 1607f812eb50127b56b6a1bace86a76c91b6ee3c Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 28 Feb 2023 09:16:33 -0800 Subject: [PATCH 060/131] [DOCS] Add stub for find case activity API (#152041) --- docs/api/cases.asciidoc | 2 ++ .../cases-api-find-case-activity.asciidoc | 20 +++++++++++++++++++ .../cases-api-get-case-activity.asciidoc | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 docs/api/cases/cases-api-find-case-activity.asciidoc diff --git a/docs/api/cases.asciidoc b/docs/api/cases.asciidoc index 9ffe69997f714..4caef82f3207b 100644 --- a/docs/api/cases.asciidoc +++ b/docs/api/cases.asciidoc @@ -8,6 +8,7 @@ these APIs: * <> * <> * <> +* <> * <> * <> * <> @@ -33,6 +34,7 @@ include::cases/cases-api-create.asciidoc[leveloffset=+1] include::cases/cases-api-delete-cases.asciidoc[leveloffset=+1] include::cases/cases-api-delete-comments.asciidoc[leveloffset=+1] //FIND +include::cases/cases-api-find-case-activity.asciidoc[leveloffset=+1] include::cases/cases-api-find-cases.asciidoc[leveloffset=+1] include::cases/cases-api-find-connectors.asciidoc[leveloffset=+1] //GET diff --git a/docs/api/cases/cases-api-find-case-activity.asciidoc b/docs/api/cases/cases-api-find-case-activity.asciidoc new file mode 100644 index 0000000000000..e59540c654e28 --- /dev/null +++ b/docs/api/cases/cases-api-find-case-activity.asciidoc @@ -0,0 +1,20 @@ +[[cases-api-find-case-activity]] +== Find case activity API +++++ +Find case activity +++++ + +Finds user activity for a case. + +[NOTE] +==== +For the most up-to-date API details, refer to the +{kib-repo}/tree/{branch}/x-pack/plugins/cases/docs/openapi[open API specification]. For a preview, check out <>. +==== + +=== {api-request-title} + +`GET :/api/cases//user_actions/_find` + +`GET :/s//api/cases//user_actions/_find` + diff --git a/docs/api/cases/cases-api-get-case-activity.asciidoc b/docs/api/cases/cases-api-get-case-activity.asciidoc index da23e845164db..db5835709a6ab 100644 --- a/docs/api/cases/cases-api-get-case-activity.asciidoc +++ b/docs/api/cases/cases-api-get-case-activity.asciidoc @@ -6,7 +6,7 @@ Returns all user activity for a case. -deprecated::[8.1.0] +deprecated::[8.1.0,Use <> instead.] [NOTE] ==== From b75b272a883a46990f6329044e263704c0e2ebcc Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 28 Feb 2023 09:17:02 -0800 Subject: [PATCH 061/131] [DOCS] Add deprecation details to case APIs (#152033) --- .../cases/case-apis-passthru.asciidoc | 670 +++++++++--------- .../plugins/cases/docs/openapi/bundled.json | 12 +- .../plugins/cases/docs/openapi/bundled.yaml | 12 +- .../paths/s@{spaceid}@api@cases@_find.yaml | 2 +- ...@api@cases@configure@connectors@_find.yaml | 2 +- .../paths/s@{spaceid}@api@cases@status.yaml | 1 + .../paths/s@{spaceid}@api@cases@{caseid}.yaml | 2 +- ...{spaceid}@api@cases@{caseid}@comments.yaml | 2 + ...ceid}@api@cases@{caseid}@user_actions.yaml | 1 + 9 files changed, 354 insertions(+), 350 deletions(-) diff --git a/docs/api-generated/cases/case-apis-passthru.asciidoc b/docs/api-generated/cases/case-apis-passthru.asciidoc index d6d5b0d589ac1..1d22d5cd5a906 100644 --- a/docs/api-generated/cases/case-apis-passthru.asciidoc +++ b/docs/api-generated/cases/case-apis-passthru.asciidoc @@ -24,17 +24,17 @@ Any modifications made to this file will be overwritten.
  • delete /s/{spaceId}/api/cases/{caseId}/comments/{commentId}
  • delete /s/{spaceId}/api/cases/{caseId}/comments
  • get /s/{spaceId}/api/cases/{caseId}/user_actions/_find
  • +
  • get /s/{spaceId}/api/cases/configure/connectors/_find
  • +
  • get /s/{spaceId}/api/cases/_find
  • get /s/{spaceId}/api/cases/{caseId}/comments
  • get /s/{spaceId}/api/cases/{caseId}
  • get /s/{spaceId}/api/cases/{caseId}/user_actions
  • get /s/{spaceId}/api/cases/{caseId}/alerts
  • get /s/{spaceId}/api/cases/{caseId}/comments/{commentId}
  • get /s/{spaceId}/api/cases/configure
  • -
  • get /s/{spaceId}/api/cases/configure/connectors/_find
  • get /s/{spaceId}/api/cases/reporters
  • get /s/{spaceId}/api/cases/status
  • get /s/{spaceId}/api/cases/tags
  • -
  • get /s/{spaceId}/api/cases/_find
  • get /s/{spaceId}/api/cases/alerts/{alertId}
  • post /s/{spaceId}/api/cases/{caseId}/connector/{connectorId}/_push
  • post /s/{spaceId}/api/cases/configure
  • @@ -530,12 +530,270 @@ Any modifications made to this file will be overwritten. 4xx_response

+
+
+ Up +
get /s/{spaceId}/api/cases/configure/connectors/_find
+
Retrieves information about connectors. (findCaseConnectors)
+
In particular, only the connectors that are supported for use in cases are returned. You must have read privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
+ +

Path parameters

+
+
spaceId (required)
+ +
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
+
+ + + + + + +

Return type

+ + + + +

Example data

+
Content-Type: application/json
+
{
+  "isPreconfigured" : true,
+  "isDeprecated" : true,
+  "actionTypeId" : ".none",
+  "referencedByCount" : 0,
+  "name" : "name",
+  "id" : "id",
+  "config" : {
+    "projectKey" : "projectKey",
+    "apiUrl" : "apiUrl"
+  },
+  "isMissingSecrets" : true
+}
+ +

Produces

+ This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
    +
  • application/json
  • +
+ +

Responses

+

200

+ Indicates a successful call. + +

401

+ Authorization information is missing or invalid. + 4xx_response +
+
+
+
+ Up +
get /s/{spaceId}/api/cases/_find
+
Retrieves a paginated subset of cases. (findCases)
+
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
+ +

Path parameters

+
+
spaceId (required)
+ +
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
+
+ + + + +

Query parameters

+
+
assignees (optional)
+ +
Query Parameter — Filters the returned cases by assignees. Valid values are none or unique identifiers for the user profiles. These identifiers can be found by using the suggest user profile API. default: null
defaultSearchOperator (optional)
+ +
Query Parameter — The default operator to use for the simple_query_string. default: OR
fields (optional)
+ +
Query Parameter — The fields in the entity to return in the response. default: null
from (optional)
+ +
Query Parameter — [preview] Returns only cases that were created after a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
owner (optional)
+ +
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
page (optional)
+ +
Query Parameter — The page number to return. default: 1
perPage (optional)
+ +
Query Parameter — The number of cases to return per page. default: 20
reporters (optional)
+ +
Query Parameter — Filters the returned cases by the user name of the reporter. default: null
search (optional)
+ +
Query Parameter — An Elasticsearch simple_query_string query that filters the objects in the response. default: null
searchFields (optional)
+ +
Query Parameter — The fields to perform the simple_query_string parsed query against. default: null
severity (optional)
+ +
Query Parameter — The severity of the case. default: null
sortField (optional)
+ +
Query Parameter — Determines which field is used to sort the results. default: createdAt
sortOrder (optional)
+ +
Query Parameter — Determines the sort order. default: desc
status (optional)
+ +
Query Parameter — Filters the returned cases by state. default: null
tags (optional)
+ +
Query Parameter — Filters the returned cases by tags. default: null
to (optional)
+ +
Query Parameter — [preview] Returns only cases that were created before a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
+
+ + +

Return type

+ + + + +

Example data

+
Content-Type: application/json
+
{
+  "count_in_progress_cases" : 6,
+  "per_page" : 5,
+  "total" : 2,
+  "cases" : [ {
+    "owner" : "cases",
+    "totalComment" : 0,
+    "settings" : {
+      "syncAlerts" : true
+    },
+    "totalAlerts" : 0,
+    "closed_at" : "2000-01-23T04:56:07.000+00:00",
+    "comments" : [ null, null ],
+    "assignees" : [ {
+      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
+    }, {
+      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
+    } ],
+    "created_at" : "2022-05-13T09:16:17.416Z",
+    "description" : "A case description.",
+    "title" : "Case title 1",
+    "created_by" : {
+      "full_name" : "full_name",
+      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+      "email" : "email",
+      "username" : "elastic"
+    },
+    "version" : "WzUzMiwxXQ==",
+    "closed_by" : {
+      "full_name" : "full_name",
+      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+      "email" : "email",
+      "username" : "elastic"
+    },
+    "tags" : [ "tag-1" ],
+    "duration" : 120,
+    "updated_at" : "2000-01-23T04:56:07.000+00:00",
+    "updated_by" : {
+      "full_name" : "full_name",
+      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+      "email" : "email",
+      "username" : "elastic"
+    },
+    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
+    "external_service" : {
+      "external_title" : "external_title",
+      "pushed_by" : {
+        "full_name" : "full_name",
+        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+        "email" : "email",
+        "username" : "elastic"
+      },
+      "external_url" : "external_url",
+      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
+      "connector_id" : "connector_id",
+      "external_id" : "external_id",
+      "connector_name" : "connector_name"
+    }
+  }, {
+    "owner" : "cases",
+    "totalComment" : 0,
+    "settings" : {
+      "syncAlerts" : true
+    },
+    "totalAlerts" : 0,
+    "closed_at" : "2000-01-23T04:56:07.000+00:00",
+    "comments" : [ null, null ],
+    "assignees" : [ {
+      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
+    }, {
+      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
+    } ],
+    "created_at" : "2022-05-13T09:16:17.416Z",
+    "description" : "A case description.",
+    "title" : "Case title 1",
+    "created_by" : {
+      "full_name" : "full_name",
+      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+      "email" : "email",
+      "username" : "elastic"
+    },
+    "version" : "WzUzMiwxXQ==",
+    "closed_by" : {
+      "full_name" : "full_name",
+      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+      "email" : "email",
+      "username" : "elastic"
+    },
+    "tags" : [ "tag-1" ],
+    "duration" : 120,
+    "updated_at" : "2000-01-23T04:56:07.000+00:00",
+    "updated_by" : {
+      "full_name" : "full_name",
+      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+      "email" : "email",
+      "username" : "elastic"
+    },
+    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
+    "external_service" : {
+      "external_title" : "external_title",
+      "pushed_by" : {
+        "full_name" : "full_name",
+        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
+        "email" : "email",
+        "username" : "elastic"
+      },
+      "external_url" : "external_url",
+      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
+      "connector_id" : "connector_id",
+      "external_id" : "external_id",
+      "connector_name" : "connector_name"
+    }
+  } ],
+  "count_open_cases" : 1,
+  "count_closed_cases" : 0,
+  "page" : 5
+}
+ +

Produces

+ This API call produces the following media types according to the Accept request header; + the media type will be conveyed by the Content-Type response header. +
    +
  • application/json
  • +
+ +

Responses

+

200

+ Indicates a successful call. + findCases_200_response +

401

+ Authorization information is missing or invalid. + 4xx_response +
+
Up
get /s/{spaceId}/api/cases/{caseId}/comments
Retrieves all the comments from a case. (getAllCaseComments)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.
+
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; instead, use the get case comment API, which requires a comment identifier in the path. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.

Path parameters

@@ -656,7 +914,7 @@ Any modifications made to this file will be overwritten.
includeComments (optional)
-
Query Parameter — Determines whether case comments are returned. default: true
+
Query Parameter — Deprecated in 8.1.0. This parameter is deprecated and will be removed in a future release. It determines whether case comments are returned. default: true
@@ -747,7 +1005,7 @@ Any modifications made to this file will be overwritten. Up
get /s/{spaceId}/api/cases/{caseId}/user_actions
Returns all user activity for a case. (getCaseActivity)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.
+
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the case you're seeking.

Path parameters

@@ -997,65 +1255,6 @@ Any modifications made to this file will be overwritten. 4xx_response

-
-
- Up -
get /s/{spaceId}/api/cases/configure/connectors/_find
-
Retrieves information about connectors. (getCaseConnectors)
-
In particular, only the connectors that are supported for use in cases are returned. You must have read privileges for the Actions and Connectors feature in the Management section of the Kibana feature privileges.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - - - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "isPreconfigured" : true,
-  "isDeprecated" : true,
-  "actionTypeId" : ".none",
-  "referencedByCount" : 0,
-  "name" : "name",
-  "id" : "id",
-  "config" : {
-    "projectKey" : "projectKey",
-    "apiUrl" : "apiUrl"
-  },
-  "isMissingSecrets" : true
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - -

401

- Authorization information is missing or invalid. - 4xx_response -
-
Up @@ -1117,66 +1316,9 @@ Any modifications made to this file will be overwritten.
Up -
get /s/{spaceId}/api/cases/status
-
Returns the number of cases that are open, closed, and in progress. (getCaseStatus)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
- -

Path parameters

-
-
spaceId (required)
- -
Path Parameter — An identifier for the space. If /s/ and the identifier are omitted from the path, the default space is used. default: null
-
- - - - -

Query parameters

-
-
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
-
- - -

Return type

- - - - -

Example data

-
Content-Type: application/json
-
{
-  "count_in_progress_cases" : 6,
-  "count_open_cases" : 1,
-  "count_closed_cases" : 0
-}
- -

Produces

- This API call produces the following media types according to the Accept request header; - the media type will be conveyed by the Content-Type response header. -
    -
  • application/json
  • -
- -

Responses

-

200

- Indicates a successful call. - getCaseStatus_200_response -

401

- Authorization information is missing or invalid. - 4xx_response -
-
-
-
- Up -
get /s/{spaceId}/api/cases/tags
-
Aggregates and returns a list of case tags. (getCaseTags)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
+
get /s/{spaceId}/api/cases/status
+
Returns the number of cases that are open, closed, and in progress. (getCaseStatus)
+
Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.

Path parameters

@@ -1192,21 +1334,25 @@ Any modifications made to this file will be overwritten.
owner (optional)
-
Query Parameter — A filter to limit the retrieved case statistics to a specific set of applications. If this parameter is omitted, the response contains tags from all cases that the user has access to read. default: null
+
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null

Return type

+ getCaseStatus_200_response - array[String]

Example data

Content-Type: application/json
-
""
+
{
+  "count_in_progress_cases" : 6,
+  "count_open_cases" : 1,
+  "count_closed_cases" : 0
+}

Produces

This API call produces the following media types according to the Accept request header; @@ -1218,18 +1364,18 @@ Any modifications made to this file will be overwritten.

Responses

200

Indicates a successful call. - + getCaseStatus_200_response

401

Authorization information is missing or invalid. 4xx_response

-
+
Up -
get /s/{spaceId}/api/cases/_find
-
Retrieves a paginated subset of cases. (getCases)
-
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.
+
get /s/{spaceId}/api/cases/tags
+
Aggregates and returns a list of case tags. (getCaseTags)
+
You must have read privileges for the Cases feature in the Management, Observability, or Security section of the Kibana feature privileges, depending on the owner of the cases you're seeking.

Path parameters

@@ -1243,169 +1389,23 @@ Any modifications made to this file will be overwritten.

Query parameters

-
assignees (optional)
- -
Query Parameter — Filters the returned cases by assignees. Valid values are none or unique identifiers for the user profiles. These identifiers can be found by using the suggest user profile API. default: null
defaultSearchOperator (optional)
- -
Query Parameter — The default operator to use for the simple_query_string. default: OR
fields (optional)
- -
Query Parameter — The fields in the entity to return in the response. default: null
from (optional)
- -
Query Parameter — [preview] Returns only cases that were created after a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
owner (optional)
- -
Query Parameter — A filter to limit the response to a specific set of applications. If this parameter is omitted, the response contains information about all the cases that the user has access to read. default: null
page (optional)
- -
Query Parameter — The page number to return. default: 1
perPage (optional)
- -
Query Parameter — The number of cases to return per page. default: 20
reporters (optional)
- -
Query Parameter — Filters the returned cases by the user name of the reporter. default: null
search (optional)
- -
Query Parameter — An Elasticsearch simple_query_string query that filters the objects in the response. default: null
searchFields (optional)
- -
Query Parameter — The fields to perform the simple_query_string parsed query against. default: null
severity (optional)
- -
Query Parameter — The severity of the case. default: null
sortField (optional)
- -
Query Parameter — Determines which field is used to sort the results. default: createdAt
sortOrder (optional)
- -
Query Parameter — Determines the sort order. default: desc
status (optional)
- -
Query Parameter — Filters the returned cases by state. default: null
tags (optional)
- -
Query Parameter — Filters the returned cases by tags. default: null
to (optional)
+
owner (optional)
-
Query Parameter — [preview] Returns only cases that were created before a specific date. The date must be specified as a KQL data range or date match expression. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. default: null
+
Query Parameter — A filter to limit the retrieved case statistics to a specific set of applications. If this parameter is omitted, the response contains tags from all cases that the user has access to read. default: null

Return type

- getCases_200_response + array[String]

Example data

Content-Type: application/json
-
{
-  "count_in_progress_cases" : 6,
-  "per_page" : 5,
-  "total" : 2,
-  "cases" : [ {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  }, {
-    "owner" : "cases",
-    "totalComment" : 0,
-    "settings" : {
-      "syncAlerts" : true
-    },
-    "totalAlerts" : 0,
-    "closed_at" : "2000-01-23T04:56:07.000+00:00",
-    "comments" : [ null, null ],
-    "assignees" : [ {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    }, {
-      "uid" : "u_0wpfV1MqYDaXzLtRVY-gLMrddKDEmfz51Fszhj7hWC8_0"
-    } ],
-    "created_at" : "2022-05-13T09:16:17.416Z",
-    "description" : "A case description.",
-    "title" : "Case title 1",
-    "created_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "version" : "WzUzMiwxXQ==",
-    "closed_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "tags" : [ "tag-1" ],
-    "duration" : 120,
-    "updated_at" : "2000-01-23T04:56:07.000+00:00",
-    "updated_by" : {
-      "full_name" : "full_name",
-      "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-      "email" : "email",
-      "username" : "elastic"
-    },
-    "id" : "66b9aa00-94fa-11ea-9f74-e7e108796192",
-    "external_service" : {
-      "external_title" : "external_title",
-      "pushed_by" : {
-        "full_name" : "full_name",
-        "profile_uid" : "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0",
-        "email" : "email",
-        "username" : "elastic"
-      },
-      "external_url" : "external_url",
-      "pushed_at" : "2000-01-23T04:56:07.000+00:00",
-      "connector_id" : "connector_id",
-      "external_id" : "external_id",
-      "connector_name" : "connector_name"
-    }
-  } ],
-  "count_open_cases" : 1,
-  "count_closed_cases" : 0,
-  "page" : 5
-}
+
""

Produces

This API call produces the following media types according to the Accept request header; @@ -1417,7 +1417,7 @@ Any modifications made to this file will be overwritten.

Responses

200

Indicates a successful call. - getCases_200_response +

401

Authorization information is missing or invalid. 4xx_response @@ -2094,19 +2094,19 @@ Any modifications made to this file will be overwritten.
  • create_case_request_connector -
  • external_service -
  • findCaseActivity_200_response -
  • +
  • findCaseConnectors_200_response_inner -
  • +
  • findCaseConnectors_200_response_inner_config -
  • +
  • findCases_200_response -
  • +
  • findCases_assignees_parameter -
  • +
  • findCases_owner_parameter -
  • getCaseComment_200_response -
  • getCaseConfiguration_200_response_inner -
  • getCaseConfiguration_200_response_inner_connector -
  • getCaseConfiguration_200_response_inner_created_by -
  • getCaseConfiguration_200_response_inner_mappings_inner -
  • getCaseConfiguration_200_response_inner_updated_by -
  • -
  • getCaseConnectors_200_response_inner -
  • -
  • getCaseConnectors_200_response_inner_config -
  • getCaseStatus_200_response -
  • getCasesByAlert_200_response_inner -
  • -
  • getCases_200_response -
  • -
  • getCases_assignees_parameter -
  • -
  • getCases_owner_parameter -
  • owners -
  • payload_alert_comment -
  • payload_alert_comment_comment -
  • @@ -2557,6 +2557,53 @@ Any modifications made to this file will be overwritten.
    userActions (optional)
    +
    +

    findCaseConnectors_200_response_inner - Up

    +
    +
    +
    actionTypeId (optional)
    +
    config (optional)
    +
    id (optional)
    +
    isDeprecated (optional)
    +
    isMissingSecrets (optional)
    +
    isPreconfigured (optional)
    +
    name (optional)
    +
    referencedByCount (optional)
    +
    +
    +
    +

    findCaseConnectors_200_response_inner_config - Up

    +
    +
    +
    apiUrl (optional)
    +
    projectKey (optional)
    +
    +
    +
    +

    findCases_200_response - Up

    +
    +
    +
    cases (optional)
    +
    count_closed_cases (optional)
    +
    count_in_progress_cases (optional)
    +
    count_open_cases (optional)
    +
    page (optional)
    +
    per_page (optional)
    +
    total (optional)
    +
    +
    + +

    getCaseComment_200_response - Up

    @@ -2635,28 +2682,6 @@ Any modifications made to this file will be overwritten.
    profile_uid (optional)
    -
    -

    getCaseConnectors_200_response_inner - Up

    -
    -
    -
    actionTypeId (optional)
    -
    config (optional)
    -
    id (optional)
    -
    isDeprecated (optional)
    -
    isMissingSecrets (optional)
    -
    isPreconfigured (optional)
    -
    name (optional)
    -
    referencedByCount (optional)
    -
    -
    -
    -

    getCaseConnectors_200_response_inner_config - Up

    -
    -
    -
    apiUrl (optional)
    -
    projectKey (optional)
    -
    -

    getCaseStatus_200_response - Up

    @@ -2674,31 +2699,6 @@ Any modifications made to this file will be overwritten.
    title (optional)
    String The case title.
    -
    -

    getCases_200_response - Up

    -
    -
    -
    cases (optional)
    -
    count_closed_cases (optional)
    -
    count_in_progress_cases (optional)
    -
    count_open_cases (optional)
    -
    page (optional)
    -
    per_page (optional)
    -
    total (optional)
    -
    -
    - -

    owners - Up

    The application that owns the cases: Stack Management, Observability, or Elastic Security.
    diff --git a/x-pack/plugins/cases/docs/openapi/bundled.json b/x-pack/plugins/cases/docs/openapi/bundled.json index 37647324ccf7a..2a188586b6389 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.json +++ b/x-pack/plugins/cases/docs/openapi/bundled.json @@ -209,7 +209,7 @@ "/s/{spaceId}/api/cases/_find": { "get": { "summary": "Retrieves a paginated subset of cases.", - "operationId": "getCases", + "operationId": "findCases", "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", "tags": [ "cases" @@ -1201,7 +1201,7 @@ "/s/{spaceId}/api/cases/configure/connectors/_find": { "get": { "summary": "Retrieves information about connectors.", - "operationId": "getCaseConnectors", + "operationId": "findCaseConnectors", "description": "In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges.\n", "tags": [ "cases" @@ -1371,7 +1371,7 @@ "get": { "summary": "Returns the number of cases that are open, closed, and in progress.", "operationId": "getCaseStatus", - "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", + "description": "Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", "deprecated": true, "tags": [ "cases" @@ -1525,7 +1525,7 @@ { "in": "query", "name": "includeComments", - "description": "Determines whether case comments are returned.", + "description": "Deprecated in 8.1.0. This parameter is deprecated and will be removed in a future release. It determines whether case comments are returned.", "deprecated": true, "schema": { "type": "boolean", @@ -1806,7 +1806,7 @@ "get": { "summary": "Retrieves all the comments from a case.", "operationId": "getAllCaseComments", - "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", + "description": "Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; instead, use the get case comment API, which requires a comment identifier in the path. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking.\n", "deprecated": true, "tags": [ "cases" @@ -2034,7 +2034,7 @@ "/s/{spaceId}/api/cases/{caseId}/user_actions": { "get": { "summary": "Returns all user activity for a case.", - "description": "You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking.\n", + "description": "Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking.\n", "deprecated": true, "operationId": "getCaseActivity", "tags": [ diff --git a/x-pack/plugins/cases/docs/openapi/bundled.yaml b/x-pack/plugins/cases/docs/openapi/bundled.yaml index 8098a2d8787ff..511898bfff1cd 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.yaml +++ b/x-pack/plugins/cases/docs/openapi/bundled.yaml @@ -124,7 +124,7 @@ paths: /s/{spaceId}/api/cases/_find: get: summary: Retrieves a paginated subset of cases. - operationId: getCases + operationId: findCases description: | You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. tags: @@ -783,7 +783,7 @@ paths: /s/{spaceId}/api/cases/configure/connectors/_find: get: summary: Retrieves information about connectors. - operationId: getCaseConnectors + operationId: findCaseConnectors description: | In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and Connectors** feature in the **Management** section of the Kibana feature privileges. tags: @@ -889,7 +889,7 @@ paths: summary: Returns the number of cases that are open, closed, and in progress. operationId: getCaseStatus description: | - You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. + Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. deprecated: true tags: - cases @@ -977,7 +977,7 @@ paths: - $ref: '#/components/parameters/space_id' - in: query name: includeComments - description: Determines whether case comments are returned. + description: Deprecated in 8.1.0. This parameter is deprecated and will be removed in a future release. It determines whether case comments are returned. deprecated: true schema: type: boolean @@ -1139,7 +1139,7 @@ paths: summary: Retrieves all the comments from a case. operationId: getAllCaseComments description: | - You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking. + Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; instead, use the get case comment API, which requires a comment identifier in the path. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking. deprecated: true tags: - cases @@ -1263,7 +1263,7 @@ paths: get: summary: Returns all user activity for a case. description: | - You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking. + Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking. deprecated: true operationId: getCaseActivity tags: diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml index f64fdbf0b9bf8..6e61d14a27110 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@_find.yaml @@ -1,6 +1,6 @@ get: summary: Retrieves a paginated subset of cases. - operationId: getCases + operationId: findCases description: > You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml index 7cdd1bf63ae61..bfe60072b8f50 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@configure@connectors@_find.yaml @@ -1,6 +1,6 @@ get: summary: Retrieves information about connectors. - operationId: getCaseConnectors + operationId: findCaseConnectors description: > In particular, only the connectors that are supported for use in cases are returned. You must have `read` privileges for the **Actions and Connectors** diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@status.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@status.yaml index a9db413e2eaef..d3c4b40fa3aea 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@status.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@status.yaml @@ -2,6 +2,7 @@ get: summary: Returns the number of cases that are open, closed, and in progress. operationId: getCaseStatus description: > + Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}.yaml index aca09f4a74420..856a5dc24096f 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}.yaml @@ -12,7 +12,7 @@ get: - $ref: '../components/parameters/space_id.yaml' - in: query name: includeComments - description: Determines whether case comments are returned. + description: Deprecated in 8.1.0. This parameter is deprecated and will be removed in a future release. It determines whether case comments are returned. deprecated: true schema: type: boolean diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml index 1b69926377ffb..9c50a70619b41 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@comments.yaml @@ -111,6 +111,8 @@ get: summary: Retrieves all the comments from a case. operationId: getAllCaseComments description: > + Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; + instead, use the get case comment API, which requires a comment identifier in the path. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases with the comments you're seeking. diff --git a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@user_actions.yaml b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@user_actions.yaml index a21988cd5434f..4aa52bdbc44b5 100644 --- a/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@user_actions.yaml +++ b/x-pack/plugins/cases/docs/openapi/paths/s@{spaceid}@api@cases@{caseid}@user_actions.yaml @@ -1,6 +1,7 @@ get: summary: Returns all user activity for a case. description: > + Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking. From 124b5bee90eddfceb687cd1ec5da6ce66c9ad255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Efe=20G=C3=BCrkan=20YALAMAN?= Date: Tue, 28 Feb 2023 18:17:34 +0100 Subject: [PATCH 062/131] [Enterprise Search] Consistent spacing fixes (#151866) ## Summary Introduces a new page introduction component to be used in various places. This way we ensure spacing are correct and consistent in between configuration tabs. https://user-images.githubusercontent.com/1410658/221848745-989687b4-1826-48b2-b9c8-fe5750d57c6e.mov ### 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 - [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)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- .../authentication_panel.tsx | 33 ++--- .../crawl_rules_table.test.tsx | 1 + .../crawl_rules_table.tsx | 22 +-- .../crawler_domain_detail_tabs.tsx | 60 ++++---- .../deduplication_panel.test.tsx | 8 +- .../deduplication_panel.tsx | 52 ++++--- .../entry_points_table.tsx | 13 +- .../extraction_rules/extraction_rules.tsx | 94 ++++++------- .../crawler_domain_detail/sitemaps_table.tsx | 10 +- .../page_introduction.test.tsx | 129 ++++++++++++++++++ .../page_introduction/page_introduction.tsx | 69 ++++++++++ .../inline_editable_table.test.tsx | 19 +-- .../inline_editable_table.tsx | 40 ++---- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 16 files changed, 381 insertions(+), 175 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx index f7022a3d48304..822c95a0b9598 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx @@ -9,10 +9,12 @@ import React from 'react'; import { useValues } from 'kea'; -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; +import { EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; + import { AuthenticationPanelDeleteConfirmationModal } from './auth_panel_delete_confirm_modal'; import { AuthenticationPanelActions } from './authentication_panel_actions'; import { AuthenticationPanelEditContent } from './authentication_panel_edit_content'; @@ -27,8 +29,17 @@ export const AuthenticationPanel: React.FC = () => { return ( <>
    - - + ]} + description={ +

    + +

    + } + title={

    {i18n.translate('xpack.enterpriseSearch.crawler.authenticationPanel.title', { @@ -36,19 +47,9 @@ export const AuthenticationPanel: React.FC = () => { })}

    -
    - - - -
    - -

    - -

    -
    + } + /> + {isEditing ? : }
    {isModalVisible && } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx index 7eb4c04db4480..e2c3074f41750 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx @@ -30,6 +30,7 @@ describe('CrawlRulesTable', () => { crawlRules, domainId: '6113e1407a2f2e6f42489794', indexName, + title: 'Crawl rules', }; beforeEach(() => { jest.clearAllMocks(); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx index db98f1fb987f7..5c96617e1fb2d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx @@ -18,6 +18,7 @@ import { EuiLink, EuiSelect, EuiText, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -39,6 +40,7 @@ export interface CrawlRulesTableProps { description?: React.ReactNode; domainId: string; indexName: string; + title?: React.ReactNode; } export const getReadableCrawlerRule = (rule: CrawlerRules) => { @@ -99,17 +101,14 @@ const DEFAULT_DESCRIPTION = (

    - {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.descriptionLinkText', { - defaultMessage: 'Learn more about crawl rules', - })} - - ), - }} + defaultMessage="Create a crawl rule to include or exclude pages whose URL matches the rule. Rules run in sequential order, and each URL is evaluated according to the first match." /> + + + {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.descriptionLinkText', { + defaultMessage: 'Learn more about crawl rules', + })} +

    ); @@ -119,6 +118,7 @@ export const CrawlRulesTable: React.FC = ({ indexName, crawlRules, defaultCrawlRule, + title, }) => { const { updateCrawlRules } = useActions(CrawlerDomainDetailLogic); @@ -251,7 +251,7 @@ export const CrawlRulesTable: React.FC = ({ updateCrawlRules(newCrawlRules as CrawlRule[]); clearFlashMessages(); }} - title="" + title={title || ''} uneditableItems={defaultCrawlRule ? [defaultCrawlRule] : undefined} canRemoveLastItem /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx index 9ca36ba97f7b4..a00c353eaab0b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx @@ -43,14 +43,20 @@ export const CrawlerDomainDetailTabs: React.FC = ( content: ( <> - -

    - {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.title', { - defaultMessage: 'Entry points', - })} -

    -
    - + +

    + {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.title', { + defaultMessage: 'Entry points', + })} +

    + + } + /> ), id: CrawlerDomainTabId.ENTRY_POINTS, @@ -74,14 +80,20 @@ export const CrawlerDomainDetailTabs: React.FC = ( content: ( <> - -

    - {i18n.translate('xpack.enterpriseSearch.crawler.sitemapsTable.title', { - defaultMessage: 'Sitemaps', - })} -

    -
    - + +

    + {i18n.translate('xpack.enterpriseSearch.crawler.sitemapsTable.title', { + defaultMessage: 'Sitemaps', + })} +

    + + } + /> ), id: CrawlerDomainTabId.SITE_MAPS, @@ -93,18 +105,20 @@ export const CrawlerDomainDetailTabs: React.FC = ( content: ( <> - -

    - {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.title', { - defaultMessage: 'Crawl rules', - })} -

    -
    +

    + {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.title', { + defaultMessage: 'Crawl rules', + })} +

    + + } /> ), diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx index 54c93ff744ede..a7ffe1bc81bd3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx @@ -14,7 +14,6 @@ import { shallow } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { - EuiButton, EuiButtonEmpty, EuiContextMenuItem, EuiPopover, @@ -26,6 +25,8 @@ import { import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; + import { rerender } from '../../../../../../test_helpers'; import { DeduplicationPanel } from './deduplication_panel'; @@ -61,8 +62,11 @@ describe('DeduplicationPanel', () => { it('contains a button to reset to defaults', () => { const wrapper = shallow(); + const dedupeButton = shallow( +
    {wrapper.find(PageIntroduction).prop('actions')}
    + ).children(); - wrapper.find('EuiFlexGroup').first().dive().find(EuiButton).simulate('click'); + dedupeButton.simulate('click'); expect(MOCK_ACTIONS.submitDeduplicationUpdate).toHaveBeenCalledWith({ fields: [], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx index e17815765169e..c4bedce7a43c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx @@ -21,7 +21,6 @@ import { EuiSelectable, EuiSpacer, EuiSwitch, - EuiText, EuiTitle, } from '@elastic/eui'; @@ -31,6 +30,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { docLinks } from '../../../../../../shared/doc_links'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; import { CrawlerDomainDetailLogic } from '../crawler_domain_detail_logic'; import { getCheckedOptionLabels, getSelectableOptions } from './utils'; @@ -55,8 +55,8 @@ export const DeduplicationPanel: React.FC = () => { return (
    - - +

    {i18n.translate('xpack.enterpriseSearch.crawler.deduplicationPanel.title', { @@ -64,8 +64,8 @@ export const DeduplicationPanel: React.FC = () => { })}

    -
    - + } + actions={ { } )} - -
    - - -

    - - {i18n.translate( - 'xpack.enterpriseSearch.crawler.deduplicationPanel.learnMoreMessage', - { - defaultMessage: 'Learn more about content hashing', - } - )} - - ), - }} - /> -

    -
    + documents on this domain." + /> +

    + } + links={ + + {i18n.translate('xpack.enterpriseSearch.crawler.deduplicationPanel.learnMoreMessage', { + defaultMessage: 'Learn more about content hashing', + })} + + } + /> = ({ domain, indexName, items }) => { +export const EntryPointsTable: React.FC = ({ + domain, + indexName, + items, + title, +}) => { const { onAdd, onDelete, onUpdate } = useActions(EntryPointsTableLogic); const field = 'value'; @@ -76,7 +82,8 @@ export const EntryPointsTable: React.FC = ({ domain, inde {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.description', { defaultMessage: 'Include the most important URLs for your website here. Entry point URLs will be the first pages to be indexed and processed for links to other pages.', - })}{' '} + })} + {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.learnMoreLinkText', { defaultMessage: 'Learn more about entry points.', @@ -130,7 +137,7 @@ export const EntryPointsTable: React.FC = ({ domain, inde onAdd={onAdd} onDelete={onDelete} onUpdate={onUpdate} - title="" + title={title} disableReordering /> ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx index b8fdab12acbc6..0887db23c7789 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx @@ -13,9 +13,8 @@ import { EuiButton, EuiConfirmModal, EuiEmptyPrompt, - EuiFlexGroup, - EuiFlexItem, EuiLink, + EuiFlexGroup, EuiSpacer, EuiText, EuiTitle, @@ -26,6 +25,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { CANCEL_BUTTON_LABEL } from '../../../../../../shared/constants'; import { docLinks } from '../../../../../../shared/doc_links'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; import { EditExtractionRule } from './edit_extraction_rule'; import { ExtractionRulesLogic } from './extraction_rules_logic'; @@ -81,56 +81,56 @@ export const ExtractionRules: React.FC = () => { )} - - -

    - {i18n.translate('xpack.enterpriseSearch.content.crawler.extractionRules.title', { - defaultMessage: 'Extraction rules', - })} -

    -
    -
    - {extractionRules.length === 0 ? ( - <> - ) : ( - - + +

    + {i18n.translate('xpack.enterpriseSearch.content.crawler.extractionRules.title', { + defaultMessage: 'Extraction rules', + })} +

    + + } + description={ +

    + +

    + } + links={ + {i18n.translate( - 'xpack.enterpriseSearch.content.crawler.extractionRulesTable.addRuleLabel', + 'xpack.enterpriseSearch.content.crawler.extractionRules.learnMoreLink', { - defaultMessage: 'Add extraction rule', + defaultMessage: 'Learn more about content extraction rules.', } )} -
    -
    - )} +
    + } + actions={ + extractionRules.length === 0 + ? [] + : [ + + {i18n.translate( + 'xpack.enterpriseSearch.content.crawler.extractionRulesTable.addRuleLabel', + { + defaultMessage: 'Add extraction rule', + } + )} + , + ] + } + /> - - -

    - - {i18n.translate( - 'xpack.enterpriseSearch.content.crawler.extractionRules.learnMoreLink', - { - defaultMessage: 'Learn more about content extraction rules.', - } - )} - - ), - }} - /> -

    -
    - + {editingExtractionRule ? ( = ({ domain, indexName, items }) => { +export const SitemapsTable: React.FC = ({ + domain, + indexName, + items, + title, +}) => { const { updateSitemaps } = useActions(CrawlerDomainDetailLogic); const field = 'url'; @@ -113,7 +119,7 @@ export const SitemapsTable: React.FC = ({ domain, indexName, updateSitemaps(newSitemaps as Sitemap[]); clearFlashMessages(); }} - title="" + title={title || ''} disableReordering /> ); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.test.tsx new file mode 100644 index 0000000000000..4077dac076839 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.test.tsx @@ -0,0 +1,129 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { mount } from 'enzyme'; + +import { EuiLink } from '@elastic/eui'; + +import { PageIntroduction } from './page_introduction'; + +describe('PageIntroduction component', () => { + it('renders with title as a string', () => { + const wrapper = mount(); + // .hostNodes is required due to Emotion injection causing problems with enzyme + const titleContainer = wrapper + .find('[data-test-subj="pageIntroductionTitleContainer"]') + .hostNodes(); + expect(titleContainer).toHaveLength(1); + + expect(titleContainer.text()).toEqual('string title'); + }); + + it('renders title as React node', () => { + const wrapper = mount( + react node title} + description="some description" + /> + ); + // .hostNodes is required due to Emotion injection causing problems with enzyme + const titleContainer = wrapper.find('[data-test-subj="injected"]').hostNodes(); + expect(titleContainer).toHaveLength(1); + + expect(titleContainer.text()).toEqual('react node title'); + }); + + it('renders with description only', () => { + const wrapper = mount(); + // .hostNodes is required due to Emotion injection causing problems with enzyme + const titleContainer = wrapper + .find('[data-test-subj="pageIntroductionTitleContainer"]') + .hostNodes(); + + const descriptionContainer = wrapper + .find('[data-test-subj="pageIntroductionDescriptionText"]') + .hostNodes(); + expect(titleContainer).toHaveLength(1); + expect(descriptionContainer).toHaveLength(1); + + expect(titleContainer.text()).toEqual(''); + expect(descriptionContainer.text()).toEqual('some description'); + }); + + it('renders with single link', () => { + const wrapper = mount( + + test link to nowhere + + } + /> + ); + const links = wrapper.find(EuiLink); + expect(links).toHaveLength(1); + expect(links.prop('href')).toEqual('testlink'); + // due to accesibility injections text includes screen reader text as well + expect(links.text().startsWith('test link to nowhere')).toBe(true); + }); + + it('renders with multiple links', () => { + const wrapper = mount( + + test link to nowhere + , + + test link to nowhere2 + , + ]} + /> + ); + const links = wrapper.find(EuiLink); + expect(links).toHaveLength(2); + expect(links.at(0).prop('href')).toEqual('testlink'); + // due to accesibility injections text includes screen reader text as well + expect(links.at(0).text().startsWith('test link to nowhere')).toBe(true); + expect(links.at(1).prop('href')).toEqual('testlink2'); + // due to accesibility injections text includes screen reader text as well + expect(links.at(1).text().startsWith('test link to nowhere2')).toBe(true); + }); + + it('renders with single actions', () => { + const wrapper = mount( + some action} + /> + ); + const actions = wrapper.find('button'); + expect(actions).toHaveLength(1); + expect(actions.text()).toEqual('some action'); + }); + + it('renders with multiple action', () => { + const wrapper = mount( + some action, ]} + /> + ); + const actions = wrapper.find('button'); + expect(actions).toHaveLength(2); + expect(actions.at(0).text()).toEqual('some action'); + expect(actions.at(1).text()).toEqual('another action'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.tsx new file mode 100644 index 0000000000000..1f2e5951bb94f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { EuiText, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; + +export interface PageIntroductionProps { + actions?: React.ReactNode | React.ReactNode[]; + description: React.ReactNode | string; + links?: React.ReactNode | React.ReactNode[]; + title?: string | React.ReactNode; +} + +export const PageIntroduction: React.FC = ({ + actions, + description, + links, + title = '', +}) => { + return ( + + + + + {typeof title === 'string' ? ( + +

    {title}

    +
    + ) : ( + title + )} +
    + + + + {description} + + + {!!links && ( + <> + + + + {Array.isArray(links) ? links.map((link) => link) : links} + + + + )} +
    +
    + + + {Array.isArray(actions) + ? actions?.map((action, index) => ( + + {action} + + )) + : actions} + + +
    + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx index 9725abcd6eba7..3d2a243664edf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx @@ -12,6 +12,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { BindLogic } from 'kea'; +import { PageIntroduction } from '../../page_introduction/page_introduction'; import { ReorderableTable } from '../reorderable_table'; jest.mock('./get_updated_columns', () => ({ @@ -86,18 +87,19 @@ describe('InlineEditableTable', () => { it('renders a ReorderableTable', () => { const wrapper = shallow(); const reorderableTable = wrapper.find(ReorderableTable); + const addButton = shallow( +
    {wrapper.find(PageIntroduction).prop('actions')}
    + ).children(); expect(reorderableTable.exists()).toBe(true); expect(reorderableTable.prop('items')).toEqual(items); - expect( - wrapper.find('[data-test-subj="inlineEditableTableActionButton"]').children().text() - ).toEqual('New row'); + expect(addButton.children().text()).toEqual('New row'); }); it('renders a title if one is provided', () => { const wrapper = shallow( Some Description

    } /> ); - expect(wrapper.find('[data-test-subj="inlineEditableTableTitle"]').exists()).toBe(true); + expect(wrapper.find(PageIntroduction).prop('title')).toEqual(requiredParams.title); }); it('does not render a title if none is provided', () => { @@ -114,7 +116,7 @@ describe('InlineEditableTable', () => { const wrapper = shallow( Some Description

    } /> ); - expect(wrapper.find('[data-test-subj="inlineEditableTableDescription"]').exists()).toBe(true); + expect(wrapper.find(PageIntroduction).prop('description')).toEqual(

    Some Description

    ); }); it('renders no description if none is provided', () => { @@ -141,9 +143,10 @@ describe('InlineEditableTable', () => { const wrapper = shallow( ); - expect( - wrapper.find('[data-test-subj="inlineEditableTableActionButton"]').children().text() - ).toEqual('Add a new row custom text'); + const addButton = shallow( +
    {wrapper.find(PageIntroduction).prop('actions')}
    + ).children(); + expect(addButton.children().text()).toEqual('Add a new row custom text'); }); describe('when a user is editing an unsaved item', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx index 232ad491b1397..d14acc91ac581 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx @@ -11,9 +11,11 @@ import classNames from 'classnames'; import { useActions, useValues, BindLogic } from 'kea'; -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; +import { EuiButton, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { PageIntroduction } from '../../page_introduction/page_introduction'; + import { ReorderableTable } from '../reorderable_table'; import { ItemWithAnID } from '../types'; @@ -29,7 +31,7 @@ export interface InlineEditableTableProps { items: Item[]; defaultItem?: Partial; emptyPropertyAllowed?: boolean; - title: string; + title: string | React.ReactNode; addButtonText?: string; canRemoveLastItem?: boolean; className?: string; @@ -129,28 +131,10 @@ export const InlineEditableTableContents = ({ return ( <> - - - {!!title && ( - -

    {title}

    -
    - )} - {!!description && ( - <> - - - {description} - - - )} -
    - + ({ i18n.translate('xpack.enterpriseSearch.inlineEditableTable.newRowButtonLabel', { defaultMessage: 'New row', })} - - -
    - + , + ]} + /> + Date: Tue, 28 Feb 2023 10:46:08 -0700 Subject: [PATCH 063/131] Removes FindQueryHTTP['fields'] option in Saved Objects Management (#152306) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/saved_objects_management/common/types/v1.ts | 7 ------- .../objects_table/saved_objects_table.tsx | 1 - src/plugins/saved_objects_management/server/routes/find.ts | 7 ------- test/api_integration/apis/saved_objects_management/find.ts | 2 +- .../test_suites/saved_objects_hidden_type/find.ts | 4 ++-- .../test_suites/saved_objects_management/find.ts | 4 +--- .../saved_objects_management/hidden_from_http_apis.ts | 4 +--- 7 files changed, 5 insertions(+), 24 deletions(-) diff --git a/src/plugins/saved_objects_management/common/types/v1.ts b/src/plugins/saved_objects_management/common/types/v1.ts index 78bd4a50c036e..241188d035a6e 100644 --- a/src/plugins/saved_objects_management/common/types/v1.ts +++ b/src/plugins/saved_objects_management/common/types/v1.ts @@ -129,13 +129,6 @@ export interface FindQueryHTTP { sortOrder?: FindSortOrderHTTP; hasReference?: ReferenceHTTP | ReferenceHTTP[]; hasReferenceOperator?: FindSearchOperatorHTTP; - /** - * It is not clear who might be using this API option, the SOM UI only ever passes in "id" here. - * - * TODO: Determine use. If not in use we should remove this option. If in use we must deprecate and eventually - * remove. - */ - fields?: string | string[]; } export interface FindResponseHTTP { diff --git a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx index 264823dd8e991..48d428a9f087f 100644 --- a/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx +++ b/src/plugins/saved_objects_management/public/management_section/objects_table/saved_objects_table.tsx @@ -236,7 +236,6 @@ export class SavedObjectsTable extends Component typeRegistry.isImportableAndExportable(type) @@ -90,9 +86,6 @@ export const registerFindRoute = ( saved_objects: savedObjects.map((so) => { const obj = injectMetaAttributes(so, managementService); const result = { ...obj, attributes: {} as Record }; - for (const field of includedFields) { - result.attributes[field] = (obj.attributes as Record)[field]; - } return result; }), total: findResponse.total, diff --git a/test/api_integration/apis/saved_objects_management/find.ts b/test/api_integration/apis/saved_objects_management/find.ts index ca891986f609a..ca78702925d5c 100644 --- a/test/api_integration/apis/saved_objects_management/find.ts +++ b/test/api_integration/apis/saved_objects_management/find.ts @@ -37,7 +37,7 @@ export default function ({ getService }: FtrProviderContext) { it('should return 200 with individual responses', async () => await supertest - .get('/api/kibana/management/saved_objects/_find?type=visualization&fields=title') + .get('/api/kibana/management/saved_objects/_find?type=visualization') .expect(200) .then((resp: Response) => { expect(resp.body.saved_objects.map((so: { id: string }) => so.id)).to.eql([ diff --git a/test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts b/test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts index 5a31da2b57a8e..c73edfc106668 100644 --- a/test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts +++ b/test/plugin_functional/test_suites/saved_objects_hidden_type/find.ts @@ -27,7 +27,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { it('returns empty response for importableAndExportable types', async () => await supertest - .get('/api/saved_objects/_find?type=test-hidden-importable-exportable&fields=title') + .get('/api/saved_objects/_find?type=test-hidden-importable-exportable') .set('kbn-xsrf', 'true') .expect(200) .then((resp) => { @@ -41,7 +41,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { it('returns empty response for non importableAndExportable types', async () => await supertest - .get('/api/saved_objects/_find?type=test-hidden-non-importable-exportable&fields=title') + .get('/api/saved_objects/_find?type=test-hidden-non-importable-exportable') .set('kbn-xsrf', 'true') .expect(200) .then((resp) => { diff --git a/test/plugin_functional/test_suites/saved_objects_management/find.ts b/test/plugin_functional/test_suites/saved_objects_management/find.ts index fdeb2c6f8b124..6492f7439079b 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/find.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/find.ts @@ -27,9 +27,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { ); it('returns saved objects with importableAndExportable types', async () => await supertest - .get( - '/api/kibana/management/saved_objects/_find?type=test-hidden-importable-exportable&fields=title' - ) + .get('/api/kibana/management/saved_objects/_find?type=test-hidden-importable-exportable') .set('kbn-xsrf', 'true') .expect(200) .then((resp) => { diff --git a/test/plugin_functional/test_suites/saved_objects_management/hidden_from_http_apis.ts b/test/plugin_functional/test_suites/saved_objects_management/hidden_from_http_apis.ts index ce441d9d1b353..d9516ee0331c4 100644 --- a/test/plugin_functional/test_suites/saved_objects_management/hidden_from_http_apis.ts +++ b/test/plugin_functional/test_suites/saved_objects_management/hidden_from_http_apis.ts @@ -107,9 +107,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { describe('find', () => { it('returns saved objects registered as hidden from the http Apis', async () => { await supertest - .get( - `/api/kibana/management/saved_objects/_find?type=${hiddenFromHttpApisType.type}&fields=title` - ) + .get(`/api/kibana/management/saved_objects/_find?type=${hiddenFromHttpApisType.type}`) .set('kbn-xsrf', 'true') .expect(200) .then((resp) => { From e4ea6359c9df7d2ee175775e4015403483cf6801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:42:35 +0100 Subject: [PATCH 064/131] [Guided onboarding] Update readme with steps to register a new guide (#152232) --- src/plugins/guided_onboarding/README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/plugins/guided_onboarding/README.md b/src/plugins/guided_onboarding/README.md index 8f9a428beb1fd..7dbf443f7f86e 100755 --- a/src/plugins/guided_onboarding/README.md +++ b/src/plugins/guided_onboarding/README.md @@ -2,9 +2,11 @@ This plugin contains the code for the Guided Onboarding project. Guided onboarding consists of guides for Solutions (Enterprise Search, Observability, Security) that can be completed as a checklist of steps. The guides help users to ingest their data and to navigate to the correct Solutions pages. -The guided onboarding plugin includes a client-side code for the UI and the server-side code for the internal API. The server-side code is not intended for external use. +The guided onboarding plugin includes a client-side code for the UI and the server-side code for the internal API. -The client-side code registers a button in the Kibana header that controls the guided onboarding panel (checklist) depending on the current state. There is also an API service exposed from the client-side start contract. The API service is intended for external use by other plugins. +The client-side code registers a button in the Kibana header that controls the guided onboarding panel (checklist) depending on the current state. There is also an API service exposed from the client-side start contract. The API service is intended for external use by other plugins that need to react to the guided onboarding state, for example hide or display UI elements if a guide step is active. + +Besides the internal API routes, the server-side code also exposes a function to register guide configs from the server-side setup start contract. This function is intended for external use by any plugin that need to add a new guide or modify an existing one. --- ## Current functionality @@ -106,3 +108,13 @@ The guided onboarding exposes a function `registerGuideConfig(guideId: GuideId, - observability: `x-pack/plugins/observability/server/plugin.ts` - security solution: `x-pack/plugins/security_solution/server/plugin.ts` + +## Adding a new guide +Follow these simple steps to add a new guide to the guided onboarding framework. For more detailed information about framework functionality and architecture and about API services exposed by the plugin, please read the full readme. + +1. Declare the `guidedOnboarding` plugin as a dependency in your plugin's `kibana.json` file. Add the guided onboarding plugin's client-side start contract to your plugin's client-side start dependencies and the guided onboarding plugin's server-side setup contract to your plugin's server-side dependencies. +2. Define the configuration for your guide. At a high level, this includes a title, description, and list of steps. See this [example config](https://github.com/elastic/kibana/blob/main/packages/kbn-guided-onboarding/src/common/test_guide_config.ts) or consult the `GuideConfig` interface. +3. Register your guide during your plugin's server-side setup by calling a function exposed by the guided onboarding plugin: `registerGuideConfig(guideId: GuideId, guideConfig: GuideConfig)`. For an example, see this [example plugin](https://github.com/elastic/kibana/blob/main/examples/guided_onboarding_example/server/plugin.ts). +4. Update the cards on the landing page to include your guide in the use case selection. Make sure that the card doesn't have the property `navigateTo` because that is only used for cards that redirect to Kibana pages and don't start a guide. Also add the same value to the property `guideId` as used in the guide config. Landing page cards are configured in this [kbn-guided-onboarding package](https://github.com/elastic/kibana/blob/main/packages/kbn-guided-onboarding/src/components/landing_page/guide_cards.constants.tsx). +5. Integrate the new guide into your Kibana pages by using the guided onboarding client-side API service. Make sure your Kibana pages correctly display UI elements depending on the active guide step and the UI flow is straight forward to complete the guide. See existing guides for an example and read more about the API service in this file, the section "Client-side: API service". +6. Optionally, update the example plugin's [form](https://github.com/elastic/kibana/blob/main/examples/guided_onboarding_example/public/components/main.tsx#L38) to be able to start your guide from that page and activate any step in your guide (useful to test your guide steps). From a87f440588b49b0a63c35bd2292e92698a93bde4 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau Date: Tue, 28 Feb 2023 17:02:46 -0500 Subject: [PATCH 065/131] [RAM] Fix flaky test for update api key tests (#152277) ## Summary Bring back update api key test ### 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 --- ...update_api_key_modal_confirmation.test.tsx | 131 ++++++++++++++++++ .../rules_list/components/rules_list.test.tsx | 47 +------ 2 files changed, 134 insertions(+), 44 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/components/update_api_key_modal_confirmation.test.tsx diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/update_api_key_modal_confirmation.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/update_api_key_modal_confirmation.test.tsx new file mode 100644 index 0000000000000..2c1b10fca0c6c --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/update_api_key_modal_confirmation.test.tsx @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as React from 'react'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { IToasts } from '@kbn/core/public'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { UpdateApiKeyModalConfirmation } from './update_api_key_modal_confirmation'; +import { useKibana } from '../../common/lib/kibana'; + +const Providers = ({ children }: { children: any }) => ( + {children} +); + +const renderWithProviders = (ui: any) => { + return render(ui, { wrapper: Providers }); +}; + +jest.mock('../../common/lib/kibana'); +const useKibanaMock = useKibana as jest.Mocked; + +describe('Update Api Key', () => { + const onCancel = jest.fn(); + const apiUpdateApiKeyCall = jest.fn(); + const setIsLoadingState = jest.fn(); + const onUpdated = jest.fn(); + const onSearchPopulate = jest.fn(); + + const addSuccess = jest.fn(); + const addError = jest.fn(); + + beforeAll(() => { + useKibanaMock().services.notifications.toasts = { + addSuccess, + addError, + } as unknown as IToasts; + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('Render modal updates Api Key', async () => { + renderWithProviders( + + ); + + expect( + await screen.findByText('You will not be able to recover the old API key') + ).toBeInTheDocument(); + }); + + it('Cancel modal updates Api Key', async () => { + renderWithProviders( + + ); + + fireEvent.click(await screen.findByText('Cancel')); + expect(onCancel).toHaveBeenCalled(); + }); + + it('Update an Api Key', async () => { + apiUpdateApiKeyCall.mockResolvedValue({}); + renderWithProviders( + + ); + + fireEvent.click(await screen.findByText('Update')); + expect(setIsLoadingState).toBeCalledTimes(1); + expect(apiUpdateApiKeyCall).toHaveBeenLastCalledWith(expect.objectContaining({ ids: ['2'] })); + await waitFor(() => { + expect(setIsLoadingState).toBeCalledTimes(2); + expect(onUpdated).toHaveBeenCalled(); + }); + }); + + it('Failed to update an Api Key', async () => { + apiUpdateApiKeyCall.mockRejectedValue(500); + renderWithProviders( + + ); + + fireEvent.click(await screen.findByText('Update')); + expect(setIsLoadingState).toBeCalledTimes(1); + expect(apiUpdateApiKeyCall).toHaveBeenLastCalledWith(expect.objectContaining({ ids: ['2'] })); + await waitFor(() => { + expect(setIsLoadingState).toBeCalledTimes(2); + expect(addError).toHaveBeenCalled(); + expect(addError.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + 500, + Object { + "title": "Failed to update the API key", + }, + ] + `); + }); + }); +}); 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 f70437b33c451..2775b200cb6c6 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 @@ -146,10 +146,7 @@ const renderWithProviders = (ui: any) => { return render(ui, { wrapper: AllTheProviders }); }; -// FLAKY: https://github.com/elastic/kibana/issues/134922 -// FLAKY: https://github.com/elastic/kibana/issues/134923 - -describe.skip('Update Api Key', () => { +describe('Update Api Key', () => { const addSuccess = jest.fn(); const addError = jest.fn(); @@ -177,7 +174,7 @@ describe.skip('Update Api Key', () => { cleanup(); }); - it('Updates the Api Key successfully', async () => { + it('Have the option to update API key', async () => { bulkUpdateAPIKey.mockResolvedValueOnce({ errors: [], total: 1, rules: [], skipped: [] }); renderWithProviders(); @@ -186,45 +183,7 @@ describe.skip('Update Api Key', () => { fireEvent.click((await screen.findAllByTestId('selectActionButton'))[1]); expect(screen.getByTestId('collapsedActionPanel')).toBeInTheDocument(); - fireEvent.click(await screen.findByText('Update API key')); - expect(screen.getByText('You will not be able to recover the old API key')).toBeInTheDocument(); - - fireEvent.click(await screen.findByText('Cancel')); - expect( - screen.queryByText('You will not be able to recover the old API key') - ).not.toBeInTheDocument(); - - fireEvent.click((await screen.findAllByTestId('selectActionButton'))[1]); - expect(screen.getByTestId('collapsedActionPanel')).toBeInTheDocument(); - - fireEvent.click(await screen.findByText('Update API key')); - - fireEvent.click(await screen.findByTestId('confirmModalConfirmButton')); - await waitFor(() => expect(addSuccess).toHaveBeenCalledWith('Updated API key for 1 rule.')); - expect(bulkUpdateAPIKey).toHaveBeenCalledWith(expect.objectContaining({ ids: ['2'] })); - expect(screen.queryByText("You can't recover the old API key")).not.toBeInTheDocument(); - }); - - it('Update API key fails', async () => { - bulkUpdateAPIKey.mockRejectedValueOnce(500); - renderWithProviders(); - - expect(await screen.findByText('test rule ok')).toBeInTheDocument(); - - fireEvent.click((await screen.findAllByTestId('selectActionButton'))[1]); - expect(screen.getByTestId('collapsedActionPanel')).toBeInTheDocument(); - - fireEvent.click(await screen.findByText('Update API key')); - expect(screen.getByText('You will not be able to recover the old API key')).toBeInTheDocument(); - - fireEvent.click(await screen.findByText('Update')); - await waitFor(() => - expect(addError).toHaveBeenCalledWith(500, { title: 'Failed to update the API key' }) - ); - expect(bulkUpdateAPIKey).toHaveBeenCalledWith(expect.objectContaining({ ids: ['2'] })); - expect( - screen.queryByText('You will not be able to recover the old API key') - ).not.toBeInTheDocument(); + expect(screen.queryByText('Update API key')).toBeInTheDocument(); }); }); From 6be7e3df0b8f55e45a114e8da66c2dd1927ca341 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Wed, 1 Mar 2023 02:23:04 +0400 Subject: [PATCH 066/131] [Enterprise Search] Show error for crawlers without a connector document (#150928) ## Summary This shows an error for broken crawlers, where a connector document has been deleted. It offers users the choice to recreate the connector or delete their index. https://user-images.githubusercontent.com/94373878/221916920-f75299b4-f88d-4cba-89a2-92fe62366050.mov https://user-images.githubusercontent.com/94373878/221916935-b416a782-92b4-4795-a1af-73e97fa523c8.mov --- ...create_crawler_connector_api_logic.test.ts | 33 +++ .../recreate_crawler_connector_api_logic.ts | 33 +++ .../api/index/delete_index_api_logic.ts | 4 +- .../header_actions/header_actions.tsx | 2 +- .../crawler/no_connector_record.tsx | 94 +++++++++ .../crawler/no_connector_record_logic.test.ts | 37 ++++ .../crawler/no_connector_record_logic.ts | 48 +++++ .../components/search_index/search_index.tsx | 17 +- .../search_indices/indices_logic.test.ts | 4 +- .../search_indices/indices_logic.ts | 10 +- .../search_indices/indices_table.tsx | 4 +- .../utils/indices.ts | 2 +- .../server/lib/connectors/add_connector.ts | 98 ++------- .../server/lib/crawler/post_connector.test.ts | 108 ++++++++++ .../server/lib/crawler/post_connector.ts | 35 ++++ .../enterprise_search/crawler/crawler.ts | 32 +++ .../utils/create_connector_document.test.ts | 195 ++++++++++++++++++ .../server/utils/create_connector_document.ts | 103 +++++++++ 18 files changed, 757 insertions(+), 102 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.ts create mode 100644 x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.test.ts create mode 100644 x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.ts create mode 100644 x-pack/plugins/enterprise_search/server/utils/create_connector_document.test.ts create mode 100644 x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.test.ts new file mode 100644 index 0000000000000..340a089bf3c10 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.test.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockHttpValues } from '../../../__mocks__/kea_logic'; + +import { nextTick } from '@kbn/test-jest-helpers'; + +import { recreateCrawlerConnector } from './recreate_crawler_connector_api_logic'; + +describe('CreateCrawlerIndexApiLogic', () => { + const { http } = mockHttpValues; + beforeEach(() => { + jest.clearAllMocks(); + }); + describe('createCrawlerIndex', () => { + it('calls correct api', async () => { + const indexName = 'elastic-co-crawler'; + http.post.mockReturnValue(Promise.resolve({ connector_id: 'connectorId' })); + + const result = recreateCrawlerConnector({ indexName }); + await nextTick(); + + expect(http.post).toHaveBeenCalledWith( + '/internal/enterprise_search/indices/elastic-co-crawler/crawler/connector' + ); + await expect(result).resolves.toEqual({ connector_id: 'connectorId' }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.ts new file mode 100644 index 0000000000000..6982850b00661 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/crawler/recreate_crawler_connector_api_logic.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Actions, createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { HttpLogic } from '../../../shared/http'; + +export interface RecreateCrawlerConnectorArgs { + indexName: string; +} + +export interface RecreateCrawlerConnectorResponse { + created: string; // the name of the newly created index +} + +export const recreateCrawlerConnector = async ({ indexName }: RecreateCrawlerConnectorArgs) => { + const route = `/internal/enterprise_search/indices/${indexName}/crawler/connector`; + + return await HttpLogic.values.http.post(route); +}; + +export const RecreateCrawlerConnectorApiLogic = createApiLogic( + ['recreate_crawler_connector_api_logic'], + recreateCrawlerConnector +); + +export type RecreateCrawlerConnectorActions = Actions< + RecreateCrawlerConnectorArgs, + RecreateCrawlerConnectorResponse +>; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts index 391e3e102383a..7c3f80b05e7a1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/delete_index_api_logic.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; -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 DeleteIndexApiLogicArgs { @@ -36,3 +36,5 @@ export const DeleteIndexApiLogic = createApiLogic(['delete_index_api_logic'], de }, }), }); + +export type DeleteIndexApiActions = Actions; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx index 0bf12fa6e200d..f6cb956478fde 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/components/header_actions/header_actions.tsx @@ -18,7 +18,7 @@ import { SyncsContextMenu } from './syncs_context_menu'; export const getHeaderActions = (indexData?: ElasticsearchIndexWithIngestion) => { const ingestionMethod = getIngestionMethod(indexData); return [ - ...(isCrawlerIndex(indexData) ? [] : []), + ...(isCrawlerIndex(indexData) && indexData.connector ? [] : []), ...(isConnectorIndex(indexData) ? [] : []), { + const { indexName } = useValues(IndexViewLogic); + const { isDeleteLoading } = useValues(IndicesLogic); + const { openDeleteModal } = useActions(IndicesLogic); + const { makeRequest } = useActions(RecreateCrawlerConnectorApiLogic); + const { status } = useValues(RecreateCrawlerConnectorApiLogic); + NoConnectorRecordLogic.mount(); + const buttonsDisabled = status === Status.LOADING || isDeleteLoading; + + return ( + <> + + + + {i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.noCrawlerConnectorFound.title', + { + defaultMessage: "This index's connector configuration has been removed", + } + )} + + } + body={ +

    + {i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.noCrawlerConnectorFound.description', + { + defaultMessage: + 'We could not find a connector configuration for this crawler index. The record should be recreated, or the index should be deleted.', + } + )} +

    + } + actions={[ + makeRequest({ indexName })} + > + {i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.noCrawlerConnectorFound.recreateConnectorRecord', + { + defaultMessage: 'Recreate connector record', + } + )} + , + openDeleteModal(indexName)} + > + {i18n.translate( + 'xpack.enterpriseSearch.content.searchIndex.noCrawlerConnectorFound.deleteIndex', + { + defaultMessage: 'Delete index', + } + )} + , + ]} + /> + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.test.ts new file mode 100644 index 0000000000000..3d9ce1c235fb4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.test.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { LogicMounter } from '../../../../__mocks__/kea_logic'; + +import { KibanaLogic } from '../../../../shared/kibana'; + +import { RecreateCrawlerConnectorApiLogic } from '../../../api/crawler/recreate_crawler_connector_api_logic'; +import { DeleteIndexApiLogic } from '../../../api/index/delete_index_api_logic'; +import { SEARCH_INDICES_PATH } from '../../../routes'; + +import { NoConnectorRecordLogic } from './no_connector_record_logic'; + +describe('NoConnectorRecordLogic', () => { + const { mount: deleteMount } = new LogicMounter(DeleteIndexApiLogic); + const { mount: recreateMount } = new LogicMounter(RecreateCrawlerConnectorApiLogic); + const { mount } = new LogicMounter(NoConnectorRecordLogic); + beforeEach(() => { + deleteMount(); + recreateMount(); + mount(); + }); + it('should redirect to search indices on delete', () => { + KibanaLogic.values.navigateToUrl = jest.fn(); + DeleteIndexApiLogic.actions.apiSuccess({} as any); + expect(KibanaLogic.values.navigateToUrl).toHaveBeenCalledWith(SEARCH_INDICES_PATH); + }); + it('should fetch index on recreate', () => { + NoConnectorRecordLogic.actions.fetchIndex = jest.fn(); + RecreateCrawlerConnectorApiLogic.actions.apiSuccess({} as any); + expect(NoConnectorRecordLogic.actions.fetchIndex).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.ts new file mode 100644 index 0000000000000..a3d1d1a653ec0 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/no_connector_record_logic.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { kea, MakeLogicType } from 'kea'; + +import { KibanaLogic } from '../../../../shared/kibana'; + +import { + RecreateCrawlerConnectorActions, + RecreateCrawlerConnectorApiLogic, +} from '../../../api/crawler/recreate_crawler_connector_api_logic'; +import { + DeleteIndexApiActions, + DeleteIndexApiLogic, +} from '../../../api/index/delete_index_api_logic'; +import { SEARCH_INDICES_PATH } from '../../../routes'; +import { IndexViewActions, IndexViewLogic } from '../index_view_logic'; + +type NoConnectorRecordActions = RecreateCrawlerConnectorActions['apiSuccess'] & { + deleteSuccess: DeleteIndexApiActions['apiSuccess']; + fetchIndex: IndexViewActions['fetchIndex']; +}; + +export const NoConnectorRecordLogic = kea>({ + connect: { + actions: [ + RecreateCrawlerConnectorApiLogic, + ['apiSuccess'], + IndexViewLogic, + ['fetchIndex'], + DeleteIndexApiLogic, + ['apiSuccess as deleteSuccess'], + ], + }, + listeners: ({ actions }) => ({ + apiSuccess: () => { + actions.fetchIndex(); + }, + deleteSuccess: () => { + KibanaLogic.values.navigateToUrl(SEARCH_INDICES_PATH); + }, + }), + path: ['enterprise_search', 'content', 'no_connector_record'], +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx index 0643cce0f8173..52ae6628f8081 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/search_index.tsx @@ -38,6 +38,7 @@ import { AutomaticCrawlScheduler } from './crawler/automatic_crawl_scheduler/aut import { CrawlCustomSettingsFlyout } from './crawler/crawl_custom_settings_flyout/crawl_custom_settings_flyout'; import { CrawlerConfiguration } from './crawler/crawler_configuration/crawler_configuration'; import { SearchIndexDomainManagement } from './crawler/domain_management/domain_management'; +import { NoConnectorRecord } from './crawler/no_connector_record'; import { SearchIndexDocuments } from './documents'; import { SearchIndexIndexMappings } from './index_mappings'; import { IndexNameLogic } from './index_name_logic'; @@ -224,12 +225,16 @@ export const SearchIndex: React.FC = () => { rightSideItems: getHeaderActions(index), }} > - <> - {indexName === index?.name && ( - - )} - {isCrawlerIndex(index) && } - + {isCrawlerIndex(index) && !index.connector ? ( + + ) : ( + <> + {indexName === index?.name && ( + + )} + {isCrawlerIndex(index) && } + + )} ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts index 16ee5faff914a..89043f1d7c0c8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.test.ts @@ -85,7 +85,7 @@ describe('IndicesLogic', () => { describe('openDeleteModal', () => { it('should set deleteIndexName and set isDeleteModalVisible to true', () => { IndicesLogic.actions.fetchIndexDetails = jest.fn(); - IndicesLogic.actions.openDeleteModal(connectorIndex); + IndicesLogic.actions.openDeleteModal(connectorIndex.name); expect(IndicesLogic.values).toEqual({ ...DEFAULT_VALUES, deleteModalIndexName: 'connector', @@ -98,7 +98,7 @@ describe('IndicesLogic', () => { }); describe('closeDeleteModal', () => { it('should set deleteIndexName to empty and set isDeleteModalVisible to false', () => { - IndicesLogic.actions.openDeleteModal(connectorIndex); + IndicesLogic.actions.openDeleteModal(connectorIndex.name); IndicesLogic.actions.fetchIndexDetails = jest.fn(); IndicesLogic.actions.closeDeleteModal(); expect(IndicesLogic.values).toEqual({ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts index 953fce853904b..9489a005d0b15 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_logic.ts @@ -69,7 +69,7 @@ export interface IndicesActions { }): { meta: Meta; returnHiddenIndices: boolean; searchQuery?: string }; makeRequest: typeof FetchIndicesAPILogic.actions.makeRequest; onPaginate(newPageIndex: number): { newPageIndex: number }; - openDeleteModal(index: ElasticsearchViewIndex): { index: ElasticsearchViewIndex }; + openDeleteModal(indexName: string): { indexName: string }; setIsFirstRequest(): void; } export interface IndicesValues { @@ -102,7 +102,7 @@ export const IndicesLogic = kea>({ searchQuery, }), onPaginate: (newPageIndex) => ({ newPageIndex }), - openDeleteModal: (index) => ({ index }), + openDeleteModal: (indexName) => ({ indexName }), setIsFirstRequest: true, }, connect: { @@ -137,8 +137,8 @@ export const IndicesLogic = kea>({ await breakpoint(150); actions.makeRequest(input); }, - openDeleteModal: ({ index }) => { - actions.fetchIndexDetails({ indexName: index.name }); + openDeleteModal: ({ indexName }) => { + actions.fetchIndexDetails({ indexName }); }, }), path: ['enterprise_search', 'content', 'indices_logic'], @@ -147,7 +147,7 @@ export const IndicesLogic = kea>({ '', { closeDeleteModal: () => '', - openDeleteModal: (_, { index: { name } }) => name, + openDeleteModal: (_, { indexName }) => indexName, }, ], isDeleteModalVisible: [ diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx index fd0bc55fdc7e3..c73f567f31edb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_indices/indices_table.tsx @@ -38,7 +38,7 @@ interface IndicesTableProps { isLoading?: boolean; meta: Meta; onChange: (criteria: CriteriaWithPagination) => void; - onDelete: (index: ElasticsearchViewIndex) => void; + onDelete: (indexName: string) => void; } export const IndicesTable: React.FC = ({ @@ -175,7 +175,7 @@ export const IndicesTable: React.FC = ({ }, } ), - onClick: (index) => onDelete(index), + onClick: (index) => onDelete(index.name), type: 'icon', }, ], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts index fd87b60bd99a8..f88620faf5b16 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/utils/indices.ts @@ -81,7 +81,7 @@ export function getIngestionStatus(index?: ElasticsearchIndexWithIngestion): Ing if (!index || isApiIndex(index)) { return IngestionStatus.CONNECTED; } - if (isConnectorIndex(index) || isCrawlerIndex(index)) { + if (isConnectorIndex(index) || (isCrawlerIndex(index) && index.connector)) { if ( index.connector.last_seen && moment(index.connector.last_seen).isBefore(moment().subtract(30, 'minutes')) diff --git a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts index 507ec3fd0bb4f..2019cd06e0089 100644 --- a/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts +++ b/x-pack/plugins/enterprise_search/server/lib/connectors/add_connector.ts @@ -8,18 +8,13 @@ import { IScopedClusterClient } from '@kbn/core/server'; import { CONNECTORS_INDEX, CONNECTORS_VERSION } from '../..'; -import { - ConnectorDocument, - ConnectorStatus, - FilteringPolicy, - FilteringRuleRule, - FilteringValidationState, -} from '../../../common/types/connectors'; +import { ConnectorDocument } from '../../../common/types/connectors'; import { ErrorCode } from '../../../common/types/error_codes'; import { DefaultConnectorsPipelineMeta, setupConnectorsIndices, } from '../../index_management/setup_indices'; +import { createConnectorDocument } from '../../utils/create_connector_document'; import { fetchCrawlerByIndexName } from '../crawler/fetch_crawlers'; import { createIndex } from '../indices/create_index'; @@ -85,89 +80,24 @@ export const addConnector = async ( const connectorsIndicesMapping = await client.asCurrentUser.indices.getMapping({ index: CONNECTORS_INDEX, }); - const connectorsPipelineMeta: DefaultConnectorsPipelineMeta = + const pipeline: DefaultConnectorsPipelineMeta = connectorsIndicesMapping[`${CONNECTORS_INDEX}-v${CONNECTORS_VERSION}`]?.mappings?._meta ?.pipeline; - const currentTimestamp = new Date().toISOString(); - const document: ConnectorDocument = { - api_key_id: null, - configuration: {}, - custom_scheduling: {}, - description: null, - error: null, - features: null, - filtering: [ - { - active: { - advanced_snippet: { - created_at: currentTimestamp, - updated_at: currentTimestamp, - value: {}, - }, - rules: [ - { - created_at: currentTimestamp, - field: '_', - id: 'DEFAULT', - order: 0, - policy: FilteringPolicy.INCLUDE, - rule: FilteringRuleRule.REGEX, - updated_at: currentTimestamp, - value: '.*', - }, - ], - validation: { - errors: [], - state: FilteringValidationState.VALID, - }, - }, - domain: 'DEFAULT', - draft: { - advanced_snippet: { - created_at: currentTimestamp, - updated_at: currentTimestamp, - value: {}, - }, - rules: [ - { - created_at: currentTimestamp, - field: '_', - id: 'DEFAULT', - order: 0, - policy: FilteringPolicy.INCLUDE, - rule: FilteringRuleRule.REGEX, - updated_at: currentTimestamp, - value: '.*', - }, - ], - validation: { - errors: [], - state: FilteringValidationState.VALID, - }, - }, - }, - ], - index_name: input.index_name, - is_native: input.is_native, + const document = createConnectorDocument({ + indexName: input.index_name, + isNative: input.is_native, language: input.language, - last_seen: null, - last_sync_error: null, - last_sync_status: null, - last_synced: null, - name: input.index_name.startsWith('search-') ? input.index_name.substring(7) : input.index_name, - pipeline: connectorsPipelineMeta + pipeline: pipeline ? { - extract_binary_content: connectorsPipelineMeta.default_extract_binary_content, - name: connectorsPipelineMeta.default_name, - reduce_whitespace: connectorsPipelineMeta.default_reduce_whitespace, - run_ml_inference: connectorsPipelineMeta.default_run_ml_inference, + extract_binary_content: pipeline.default_extract_binary_content, + name: pipeline.default_name, + reduce_whitespace: pipeline.default_reduce_whitespace, + run_ml_inference: pipeline.default_run_ml_inference, } : null, - scheduling: { enabled: false, interval: '0 0 0 * * ?' }, - service_type: input.service_type || null, - status: ConnectorStatus.CREATED, - sync_now: false, - }; + serviceType: input.service_type, + }); + return await createConnector(document, client, input.language, !!input.delete_existing_connector); }; diff --git a/x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.test.ts b/x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.test.ts new file mode 100644 index 0000000000000..729b72e8f643d --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.test.ts @@ -0,0 +1,108 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IScopedClusterClient } from '@kbn/core/server'; + +import { CONNECTORS_INDEX } from '../..'; +import { ConnectorStatus } from '../../../common/types/connectors'; + +import { recreateConnectorDocument } from './post_connector'; + +describe('recreateConnectorDocument lib function', () => { + const mockClient = { + asCurrentUser: { + index: jest.fn(), + }, + asInternalUser: {}, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should recreate connector document', async () => { + mockClient.asCurrentUser.index.mockResolvedValue({ _id: 'connectorId' }); + + await recreateConnectorDocument(mockClient as unknown as IScopedClusterClient, 'indexName'); + expect(mockClient.asCurrentUser.index).toHaveBeenCalledWith({ + document: { + api_key_id: null, + configuration: {}, + custom_scheduling: {}, + description: null, + error: null, + features: null, + filtering: [ + { + active: { + advanced_snippet: { + created_at: expect.any(String), + updated_at: expect.any(String), + value: {}, + }, + rules: [ + { + created_at: expect.any(String), + field: '_', + id: 'DEFAULT', + order: 0, + policy: 'include', + rule: 'regex', + updated_at: expect.any(String), + value: '.*', + }, + ], + validation: { + errors: [], + state: 'valid', + }, + }, + domain: 'DEFAULT', + draft: { + advanced_snippet: { + created_at: expect.any(String), + updated_at: expect.any(String), + value: {}, + }, + rules: [ + { + created_at: expect.any(String), + field: '_', + id: 'DEFAULT', + order: 0, + policy: 'include', + rule: 'regex', + updated_at: expect.any(String), + value: '.*', + }, + ], + validation: { + errors: [], + state: 'valid', + }, + }, + }, + ], + index_name: 'indexName', + is_native: false, + language: '', + last_seen: null, + last_sync_error: null, + last_sync_status: null, + last_synced: null, + name: 'indexName', + pipeline: null, + scheduling: { enabled: false, interval: '0 0 0 * * ?' }, + service_type: 'elastic-crawler', + status: ConnectorStatus.CONFIGURED, + sync_now: false, + }, + index: CONNECTORS_INDEX, + refresh: 'wait_for', + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.ts b/x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.ts new file mode 100644 index 0000000000000..17bf6945d0d82 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/crawler/post_connector.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IScopedClusterClient } from '@kbn/core-elasticsearch-server'; + +import { CONNECTORS_INDEX } from '../..'; + +import { ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE } from '../../../common/constants'; +import { ConnectorStatus } from '../../../common/types/connectors'; + +import { createConnectorDocument } from '../../utils/create_connector_document'; + +export const recreateConnectorDocument = async ( + client: IScopedClusterClient, + indexName: string +) => { + const document = createConnectorDocument({ + indexName, + isNative: false, + // The search index has already been created so we don't need the language, which we can't retrieve anymore anyway + language: '', + pipeline: null, + serviceType: ENTERPRISE_SEARCH_CONNECTOR_CRAWLER_SERVICE_TYPE, + }); + const result = await client.asCurrentUser.index({ + document: { ...document, status: ConnectorStatus.CONFIGURED }, + index: CONNECTORS_INDEX, + refresh: 'wait_for', + }); + return result._id; +}; diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts index 08cea961709fc..8d0c1e73df848 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/crawler/crawler.ts @@ -16,6 +16,7 @@ import { addConnector } from '../../../lib/connectors/add_connector'; import { deleteConnectorById } from '../../../lib/connectors/delete_connector'; import { fetchConnectorByIndexName } from '../../../lib/connectors/fetch_connectors'; import { fetchCrawlerByIndexName } from '../../../lib/crawler/fetch_crawlers'; +import { recreateConnectorDocument } from '../../../lib/crawler/post_connector'; import { updateHtmlExtraction } from '../../../lib/crawler/put_html_extraction'; import { deleteIndex } from '../../../lib/indices/delete_index'; import { RouteDependencies } from '../../../plugin'; @@ -429,6 +430,37 @@ export function registerCrawlerRoutes(routeDependencies: RouteDependencies) { }) ); + router.post( + { + path: '/internal/enterprise_search/indices/{indexName}/crawler/connector', + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, + }, + elasticsearchErrorHandler(log, async (context, request, response) => { + const { client } = (await context.core).elasticsearch; + const connector = await fetchConnectorByIndexName(client, request.params.indexName); + if (connector) { + return createError({ + errorCode: ErrorCode.CONNECTOR_DOCUMENT_ALREADY_EXISTS, + message: i18n.translate( + 'xpack.enterpriseSearch.server.routes.recreateConnector.connectorExistsError', + { + defaultMessage: 'A connector for this index already exists', + } + ), + response, + statusCode: 409, + }); + } + + const connectorId = await recreateConnectorDocument(client, request.params.indexName); + return response.ok({ body: { connector_id: connectorId } }); + }) + ); + registerCrawlerCrawlRulesRoutes(routeDependencies); registerCrawlerEntryPointRoutes(routeDependencies); registerCrawlerSitemapRoutes(routeDependencies); diff --git a/x-pack/plugins/enterprise_search/server/utils/create_connector_document.test.ts b/x-pack/plugins/enterprise_search/server/utils/create_connector_document.test.ts new file mode 100644 index 0000000000000..62851572cf798 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/create_connector_document.test.ts @@ -0,0 +1,195 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ConnectorStatus } from '../../common/types/connectors'; + +import { createConnectorDocument } from './create_connector_document'; + +describe('createConnectorDocument', () => { + it('should create a connector document', () => { + expect( + createConnectorDocument({ + indexName: 'indexName', + isNative: false, + language: 'fr', + pipeline: { + extract_binary_content: true, + name: 'ent-search-generic-ingestion', + reduce_whitespace: true, + run_ml_inference: false, + }, + }) + ).toEqual({ + api_key_id: null, + configuration: {}, + custom_scheduling: {}, + description: null, + error: null, + features: null, + filtering: [ + { + active: { + advanced_snippet: { + created_at: expect.any(String), + updated_at: expect.any(String), + value: {}, + }, + rules: [ + { + created_at: expect.any(String), + field: '_', + id: 'DEFAULT', + order: 0, + policy: 'include', + rule: 'regex', + updated_at: expect.any(String), + value: '.*', + }, + ], + validation: { + errors: [], + state: 'valid', + }, + }, + domain: 'DEFAULT', + draft: { + advanced_snippet: { + created_at: expect.any(String), + updated_at: expect.any(String), + value: {}, + }, + rules: [ + { + created_at: expect.any(String), + field: '_', + id: 'DEFAULT', + order: 0, + policy: 'include', + rule: 'regex', + updated_at: expect.any(String), + value: '.*', + }, + ], + validation: { + errors: [], + state: 'valid', + }, + }, + }, + ], + index_name: 'indexName', + is_native: false, + language: 'fr', + last_seen: null, + last_sync_error: null, + last_sync_status: null, + last_synced: null, + name: 'indexName', + pipeline: { + extract_binary_content: true, + name: 'ent-search-generic-ingestion', + reduce_whitespace: true, + run_ml_inference: false, + }, + scheduling: { enabled: false, interval: '0 0 0 * * ?' }, + service_type: null, + status: ConnectorStatus.CREATED, + sync_now: false, + }); + }); + it('should remove search- from name', () => { + expect( + createConnectorDocument({ + indexName: 'search-indexName', + isNative: false, + language: 'fr', + pipeline: { + extract_binary_content: true, + name: 'ent-search-generic-ingestion', + reduce_whitespace: true, + run_ml_inference: false, + }, + }) + ).toEqual({ + api_key_id: null, + configuration: {}, + custom_scheduling: {}, + description: null, + error: null, + features: null, + filtering: [ + { + active: { + advanced_snippet: { + created_at: expect.any(String), + updated_at: expect.any(String), + value: {}, + }, + rules: [ + { + created_at: expect.any(String), + field: '_', + id: 'DEFAULT', + order: 0, + policy: 'include', + rule: 'regex', + updated_at: expect.any(String), + value: '.*', + }, + ], + validation: { + errors: [], + state: 'valid', + }, + }, + domain: 'DEFAULT', + draft: { + advanced_snippet: { + created_at: expect.any(String), + updated_at: expect.any(String), + value: {}, + }, + rules: [ + { + created_at: expect.any(String), + field: '_', + id: 'DEFAULT', + order: 0, + policy: 'include', + rule: 'regex', + updated_at: expect.any(String), + value: '.*', + }, + ], + validation: { + errors: [], + state: 'valid', + }, + }, + }, + ], + index_name: 'search-indexName', + is_native: false, + language: 'fr', + last_seen: null, + last_sync_error: null, + last_sync_status: null, + last_synced: null, + name: 'indexName', + pipeline: { + extract_binary_content: true, + name: 'ent-search-generic-ingestion', + reduce_whitespace: true, + run_ml_inference: false, + }, + scheduling: { enabled: false, interval: '0 0 0 * * ?' }, + service_type: null, + status: ConnectorStatus.CREATED, + sync_now: false, + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts b/x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts new file mode 100644 index 0000000000000..d4776e3941cee --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/utils/create_connector_document.ts @@ -0,0 +1,103 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + ConnectorDocument, + ConnectorStatus, + FilteringPolicy, + FilteringRuleRule, + FilteringValidationState, + IngestPipelineParams, +} from '../../common/types/connectors'; + +export function createConnectorDocument({ + indexName, + isNative, + pipeline, + serviceType, + language, +}: { + indexName: string; + isNative: boolean; + language: string | null; + pipeline?: IngestPipelineParams | null; + serviceType?: string | null; +}): ConnectorDocument { + const currentTimestamp = new Date().toISOString(); + return { + api_key_id: null, + configuration: {}, + custom_scheduling: {}, + description: null, + error: null, + features: null, + filtering: [ + { + active: { + advanced_snippet: { + created_at: currentTimestamp, + updated_at: currentTimestamp, + value: {}, + }, + rules: [ + { + created_at: currentTimestamp, + field: '_', + id: 'DEFAULT', + order: 0, + policy: FilteringPolicy.INCLUDE, + rule: FilteringRuleRule.REGEX, + updated_at: currentTimestamp, + value: '.*', + }, + ], + validation: { + errors: [], + state: FilteringValidationState.VALID, + }, + }, + domain: 'DEFAULT', + draft: { + advanced_snippet: { + created_at: currentTimestamp, + updated_at: currentTimestamp, + value: {}, + }, + rules: [ + { + created_at: currentTimestamp, + field: '_', + id: 'DEFAULT', + order: 0, + policy: FilteringPolicy.INCLUDE, + rule: FilteringRuleRule.REGEX, + updated_at: currentTimestamp, + value: '.*', + }, + ], + validation: { + errors: [], + state: FilteringValidationState.VALID, + }, + }, + }, + ], + index_name: indexName, + is_native: isNative, + language, + last_seen: null, + last_sync_error: null, + last_sync_status: null, + last_synced: null, + name: indexName.startsWith('search-') ? indexName.substring(7) : indexName, + pipeline, + scheduling: { enabled: false, interval: '0 0 0 * * ?' }, + service_type: serviceType || null, + status: ConnectorStatus.CREATED, + sync_now: false, + }; +} From 7449b0adf44a44df741c814afd246eeea9972b48 Mon Sep 17 00:00:00 2001 From: "Joey F. Poon" Date: Tue, 28 Feb 2023 17:29:43 -0600 Subject: [PATCH 067/131] [Security Solution] fix flaky endpoint ftr tests (#152119) --- .../server/services/epm/elasticsearch/retry.test.ts | 9 +++++++++ .../server/services/epm/elasticsearch/retry.ts | 13 +++++++++---- .../services/epm/elasticsearch/transform/install.ts | 10 +++++++--- .../apps/endpoint/index.ts | 3 +-- 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.test.ts index 51a516e68ad6d..5947401917245 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.test.ts @@ -85,4 +85,13 @@ describe('retryTransientErrors', () => { await expect(retryTransientEsErrors(esCallMock)).rejects.toThrow(error); expect(esCallMock).toHaveBeenCalledTimes(1); }); + + it('retries with additionalResponseStatuses', async () => { + const error = new EsErrors.ResponseError({ statusCode: 123, meta: {} as any, warnings: [] }); + const esCallMock = jest.fn().mockRejectedValueOnce(error).mockResolvedValue('success'); + expect(await retryTransientEsErrors(esCallMock, { additionalResponseStatuses: [123] })).toEqual( + 'success' + ); + expect(esCallMock).toHaveBeenCalledTimes(2); + }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.ts index c8ea36a4addec..773ed7273d885 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.ts @@ -17,11 +17,12 @@ const retryResponseStatuses = [ 410, // Gone ]; -const isRetryableError = (e: any) => +const isRetryableError = (e: any, additionalResponseStatuses: number[] = []) => e instanceof EsErrors.NoLivingConnectionsError || e instanceof EsErrors.ConnectionError || e instanceof EsErrors.TimeoutError || - (e instanceof EsErrors.ResponseError && retryResponseStatuses.includes(e?.statusCode!)); + (e instanceof EsErrors.ResponseError && + [...retryResponseStatuses, ...additionalResponseStatuses].includes(e?.statusCode!)); /** * Retries any transient network or configuration issues encountered from Elasticsearch with an exponential backoff. @@ -29,12 +30,16 @@ const isRetryableError = (e: any) => */ export const retryTransientEsErrors = async ( esCall: () => Promise, - { logger, attempt = 0 }: { logger?: Logger; attempt?: number } = {} + { + logger, + attempt = 0, + additionalResponseStatuses = [], + }: { logger?: Logger; attempt?: number; additionalResponseStatuses?: number[] } = {} ): Promise => { try { return await esCall(); } catch (e) { - if (attempt < MAX_ATTEMPTS && isRetryableError(e)) { + if (attempt < MAX_ATTEMPTS && isRetryableError(e, additionalResponseStatuses)) { const retryCount = attempt + 1; const retryDelaySec = Math.min(Math.pow(2, retryCount), 64); // 2s, 4s, 8s, 16s, 32s, 64s, 64s, 64s ... diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts index e8881bb247e12..dc775d6f52e01 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts @@ -703,9 +703,13 @@ async function handleTransformInstall({ // start transform by default if not set in yml file // else, respect the setting if (startTransform === undefined || startTransform === true) { - await esClient.transform.startTransform( - { transform_id: transform.installationName }, - { ignore: [409] } + await retryTransientEsErrors( + () => + esClient.transform.startTransform( + { transform_id: transform.installationName }, + { ignore: [409] } + ), + { logger, additionalResponseStatuses: [400] } ); logger.debug(`Started transform: ${transform.installationName}`); } diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts index 589a61295a541..6aab2457c5278 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts @@ -15,8 +15,7 @@ import { export default function (providerContext: FtrProviderContext) { const { loadTestFile, getService } = providerContext; - // FLAKY: https://github.com/elastic/kibana/issues/72874 - describe.skip('endpoint', function () { + describe('endpoint', function () { const ingestManager = getService('ingestManager'); const log = getService('log'); const endpointTestResources = getService('endpointTestResources'); From d86f2f8eb95f03b5fff44410a3371b169ec27e31 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Tue, 28 Feb 2023 19:40:49 -0500 Subject: [PATCH 068/131] [Synthetics] adjust permissions for private locations (#152037) ## Summary Resolves https://github.com/elastic/kibana/issues/150725 Adds `Integrations: All` permissions requirement for interacting with Private locations A user without permissions Screen Shot 2023-02-23 at 3 26 15 PM Screen Shot 2023-02-23 at 3 26 06 PM Screen Shot 2023-02-23 at 3 26 01 PM Screen Shot 2023-02-23 at 2 36 02 PM Screen Shot 2023-02-23 at 1 16 38 PM Screen Shot 2023-02-23 at 12 28 08 PM A user with permissions Screen Shot 2023-02-23 at 1 22 11 PM ### Testing 1. Create a user with the following permissions ``` Index: synthetics-*: read Kibana: Uptime/Synthetics: All. Integrations: All ``` 2. Log in as that user 3. Navigate to Private locations in Synthetics settings. Confirm the add agent button is disabled and the need permission notice appears 4. Log in as a super user, create a private location 5. Log out, log in as the regular Uptime user 6. Navigate to Private locations in Synthetics settings. Confirm the create location button is disabled and the need permission notice appears --------- Co-authored-by: florent-leborgne --- .../synthetics/private_locations.journey.ts | 16 ++ .../common/components/permissions.tsx | 35 ++-- .../private_locations/add_location_flyout.tsx | 11 +- .../private_locations/agent_policy_needed.tsx | 9 +- .../private_locations/delete_location.tsx | 9 +- .../private_locations/location_form.tsx | 4 +- .../private_locations/locations_table.tsx | 8 +- .../private_locations/manage_empty_state.tsx | 2 +- .../manage_private_locations.test.tsx | 169 ++++++++++++++++++ .../manage_private_locations.tsx | 14 +- .../private_locations/policy_name.tsx | 28 ++- .../synthetics/hooks/use_fleet_permissions.ts | 6 + .../manage_locations_flyout.tsx | 2 +- .../monitor_config/locations.tsx | 2 +- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 17 files changed, 265 insertions(+), 53 deletions(-) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/private_locations.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/private_locations.journey.ts index 8cb69f498b066..e9aec6dc3f1c4 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/private_locations.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/private_locations.journey.ts @@ -149,4 +149,20 @@ journey(`PrivateLocationsSettings`, async ({ page, params }) => { await page.click('button:has-text("Delete location")'); await page.click('text=Create your first private location'); }); + + step('login with non super user', async () => { + await page.click('[data-test-subj="userMenuAvatar"]'); + await page.click('text="Log out"'); + await syntheticsApp.loginToKibana('viewer', 'changeme'); + }); + + step('viewer user cannot add locations', async () => { + await syntheticsApp.navigateToSettings(false); + await page.click('text=Private Locations'); + await page.waitForSelector( + `text="You're missing some Kibana privileges to manage private locations"` + ); + const createLocationBtn = await page.getByRole('button', { name: 'Create location' }); + expect(await createLocationBtn.getAttribute('disabled')).toEqual(''); + }); }); 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 index e9094bbc9a3f0..97a9ac3e62ce3 100644 --- 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 @@ -6,13 +6,14 @@ */ import React, { ReactNode } from 'react'; -import { EuiCallOut, EuiToolTip } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiCallOut, EuiToolTip, EuiCode } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; export const FleetPermissionsCallout = () => { return ( - -

    {NEED_FLEET_READ_AGENT_POLICIES_PERMISSION}

    + +

    {NEED_PRIVATE_LOCATIONS_PERMISSION}

    ); }; @@ -62,26 +63,32 @@ function getRestrictionReasonLabel( : undefined; } -export const NEED_PERMISSIONS = i18n.translate( - 'xpack.synthetics.monitorManagement.needPermissions', +export const NEED_PERMISSIONS_PRIVATE_LOCATIONS = i18n.translate( + 'xpack.synthetics.monitorManagement.privateLocations.needPermissions', { - defaultMessage: 'Need permissions', + defaultMessage: "You're missing some Kibana privileges to manage private locations", } ); -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 ALL = i18n.translate('xpack.synthetics.monitorManagement.priviledges.all', { + defaultMessage: 'All', +}); + +export const NEED_PRIVATE_LOCATIONS_PERMISSION = ( + {`"${ALL}"`}, + }} + /> ); 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.', + 'You are not authorized to manage private locations. It requires the "All" Kibana privilege for both Fleet and Integrations.', } ); @@ -89,7 +96,7 @@ 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.', + 'You are not authorized to perform this action. It requires the "All" Kibana privilege for Integrations.', } ); 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 c87aa157eeffa..51e4cce0f2fb0 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 @@ -19,7 +19,7 @@ import { EuiButton, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useFleetPermissions } from '../../../hooks/use_fleet_permissions'; +import { useCanManagePrivateLocation } from '../../../hooks/use_fleet_permissions'; import { useFormWrapped } from '../../../../../hooks/use_form_wrapped'; import { PrivateLocation } from '../../../../../../common/runtime_types'; import { FleetPermissionsCallout } from '../../common/components/permissions'; @@ -54,7 +54,7 @@ export const AddLocationFlyout = ({ const { handleSubmit } = form; - const { canReadAgentPolicies } = useFleetPermissions(); + const canManagePrivateLocation = useCanManagePrivateLocation(); const closeFlyout = () => { setIsOpen(false); @@ -69,9 +69,12 @@ export const AddLocationFlyout = ({ - {!canReadAgentPolicies && } + {!canManagePrivateLocation && } - + diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/agent_policy_needed.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/agent_policy_needed.tsx index 42aa5e8208ece..b3ad93e26d041 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/agent_policy_needed.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/agent_policy_needed.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { useSyntheticsSettingsContext } from '../../../contexts'; import { LEARN_MORE, READ_DOCS } from './empty_locations'; -export const AgentPolicyNeeded = () => { +export const AgentPolicyNeeded = ({ disabled }: { disabled: boolean }) => { const { basePath } = useSyntheticsSettingsContext(); return ( @@ -20,7 +20,12 @@ export const AgentPolicyNeeded = () => { title={

    {AGENT_POLICY_NEEDED}

    } body={

    {ADD_AGENT_POLICY_DESCRIPTION}

    } actions={ - + {CREATE_AGENT_POLICY} } 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 6d2c95cac70ae..959520c911469 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,7 +9,7 @@ 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 { useFleetPermissions, useCanManagePrivateLocation } from '../../../hooks'; import { CANNOT_SAVE_INTEGRATION_LABEL } from '../../common/components/permissions'; export const DeleteLocation = ({ @@ -30,6 +30,7 @@ export const DeleteLocation = ({ const { canSave } = useSyntheticsSettingsContext(); const { canSaveIntegrations } = useFleetPermissions(); + const canManagePrivateLocation = useCanManagePrivateLocation(); const [isModalOpen, setIsModalOpen] = useState(false); @@ -62,7 +63,9 @@ export const DeleteLocation = ({ return ( <> {isModalOpen && deleteModal} - + { setIsModalOpen(true); }} - isDisabled={!canDelete || !canSave} + isDisabled={!canDelete || !canManagePrivateLocation || !canSave} /> diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx index 89fe466d241f1..38bdac2592fb7 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx @@ -26,9 +26,11 @@ import { selectAgentPolicies } from '../../../state/private_locations'; export const LocationForm = ({ privateLocations, + hasPermissions, }: { onDiscard?: () => void; privateLocations: PrivateLocation[]; + hasPermissions: boolean; }) => { const { data } = useSelector(selectAgentPolicies); const { control, register } = useFormContext(); @@ -41,7 +43,7 @@ export const LocationForm = ({ return ( <> - {data?.items.length === 0 && } + {data?.items.length === 0 && } { const tags = item.tags || []; @@ -133,10 +133,10 @@ export const PrivateLocationsTable = ({ fill data-test-subj={'addPrivateLocationButton'} isLoading={loading} - disabled={!canSaveIntegrations || !canSave} + disabled={!canManagePrivateLocations || !canSave} onClick={() => setIsAddingNew(true)} iconType="plusInCircle" - title={!canSaveIntegrations ? CANNOT_SAVE_INTEGRATION_LABEL : undefined} + title={!canManagePrivateLocations ? CANNOT_SAVE_INTEGRATION_LABEL : undefined} > {ADD_LABEL} , diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx index 9cc313a106c96..92768f48a83ef 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx @@ -20,7 +20,7 @@ export const ManageEmptyState: FC<{ const { data: agentPolicies } = useSelector(selectAgentPolicies); if (agentPolicies?.total === 0) { - return ; + return ; } if (privateLocations.length === 0) { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx new file mode 100644 index 0000000000000..b4e406353f2a1 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx @@ -0,0 +1,169 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '../../../utils/testing/rtl_helpers'; +import * as permissionsHooks from '../../../hooks'; +import * as locationHooks from './hooks/use_locations_api'; +import * as settingsHooks from '../../../contexts/synthetics_settings_context'; +import type { SyntheticsSettingsContextValues } from '../../../contexts'; +import { ManagePrivateLocations } from './manage_private_locations'; +import { PrivateLocation } from '../../../../../../common/runtime_types'; + +jest.mock('../../../hooks'); +jest.mock('./hooks/use_locations_api'); +jest.mock('../../../contexts/synthetics_settings_context'); + +describe('', () => { + beforeEach(() => { + jest.spyOn(permissionsHooks, 'useCanManagePrivateLocation').mockReturnValue(true); + jest.spyOn(locationHooks, 'useLocationsAPI').mockReturnValue({ + formData: {} as PrivateLocation, + loading: false, + onSubmit: jest.fn(), + privateLocations: [], + onDelete: jest.fn(), + deleteLoading: false, + }); + jest.spyOn(settingsHooks, 'useSyntheticsSettingsContext').mockReturnValue({ + canSave: true, + } as SyntheticsSettingsContextValues); + }); + + it.each([true, false])( + 'handles no agent found when the user does and does not have permissions', + (hasFleetPermissions) => { + jest + .spyOn(permissionsHooks, 'useCanManagePrivateLocation') + .mockReturnValue(hasFleetPermissions); + const { getByText, getByRole, queryByText } = render(, { + state: { + agentPolicies: { + data: { + items: [], + total: 0, + page: 1, + perPage: 20, + }, + loading: false, + error: null, + isManageFlyoutOpen: false, + isAddingNewPrivateLocation: false, + }, + }, + }); + expect(getByText('No agent policies found')).toBeInTheDocument(); + + if (hasFleetPermissions) { + const button = getByRole('link', { name: 'Create agent policy' }); + expect(button).not.toBeDisabled(); + expect( + queryByText(/You are not authorized to manage private locations./) + ).not.toBeInTheDocument(); + } else { + const button = getByRole('button', { name: 'Create agent policy' }); + expect(button).toBeDisabled(); + expect(getByText(/You are not authorized to manage private locations./)); + } + } + ); + + it.each([true, false])( + 'handles create first location when the user does and does not have permissions', + (hasFleetPermissions) => { + jest + .spyOn(permissionsHooks, 'useCanManagePrivateLocation') + .mockReturnValue(hasFleetPermissions); + const { getByText, getByRole, queryByText } = render(, { + state: { + agentPolicies: { + data: { + items: [{}], + total: 1, + page: 1, + perPage: 20, + }, + loading: false, + error: null, + isManageFlyoutOpen: false, + isAddingNewPrivateLocation: false, + }, + }, + }); + expect(getByText('Create your first private location')).toBeInTheDocument(); + const button = getByRole('button', { name: 'Create location' }); + + if (hasFleetPermissions) { + expect(button).not.toBeDisabled(); + expect( + queryByText(/You are not authorized to manage private locations./) + ).not.toBeInTheDocument(); + } else { + expect(button).toBeDisabled(); + expect(getByText(/You are not authorized to manage private locations./)); + } + } + ); + + it.each([true, false])( + 'handles location table when the user does and does not have permissions', + (hasFleetPermissions) => { + const privateLocationName = 'Test private location'; + jest + .spyOn(permissionsHooks, 'useCanManagePrivateLocation') + .mockReturnValue(hasFleetPermissions); + jest.spyOn(permissionsHooks, 'useFleetPermissions').mockReturnValue({ + canSaveIntegrations: hasFleetPermissions, + canReadAgentPolicies: hasFleetPermissions, + }); + jest.spyOn(locationHooks, 'useLocationsAPI').mockReturnValue({ + formData: {} as PrivateLocation, + loading: false, + onSubmit: jest.fn(), + privateLocations: [ + { + label: privateLocationName, + id: 'lkjlere', + agentPolicyId: 'lkjelrje', + isServiceManaged: false, + concurrentMonitors: 2, + }, + ], + onDelete: jest.fn(), + deleteLoading: false, + }); + const { getByText, getByRole, queryByText } = render(, { + state: { + agentPolicies: { + data: { + items: [{}], + total: 1, + page: 1, + perPage: 20, + }, + loading: false, + error: null, + isManageFlyoutOpen: false, + isAddingNewPrivateLocation: false, + }, + }, + }); + expect(getByText(privateLocationName)).toBeInTheDocument(); + const button = getByRole('button', { name: 'Create location' }); + + if (hasFleetPermissions) { + expect(button).not.toBeDisabled(); + expect( + queryByText(/You are not authorized to manage private locations./) + ).not.toBeInTheDocument(); + } else { + expect(button).toBeDisabled(); + expect(getByText(/You are not authorized to manage private locations./)); + } + } + ); +}); 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 d697d011e5841..dd140ffd3b3f5 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 @@ -6,9 +6,10 @@ */ import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { EuiSpacer } from '@elastic/eui'; import { LoadingState } from '../../monitors_page/overview/overview/monitor_detail_flyout'; import { PrivateLocationsTable } from './locations_table'; -import { useFleetPermissions } from '../../../hooks'; +import { useCanManagePrivateLocation } from '../../../hooks'; import { ManageEmptyState } from './manage_empty_state'; import { AddLocationFlyout } from './add_location_flyout'; import { useLocationsAPI } from './hooks/use_locations_api'; @@ -30,7 +31,7 @@ export const ManagePrivateLocations = () => { const { onSubmit, loading, privateLocations, onDelete, deleteLoading } = useLocationsAPI(); - const { canReadAgentPolicies } = useFleetPermissions(); + const canManagePrivateLocation = useCanManagePrivateLocation(); useEffect(() => { dispatch(getAgentPoliciesAction.get()); @@ -43,7 +44,12 @@ export const ManagePrivateLocations = () => { return ( <> - {!canReadAgentPolicies && } + {!canManagePrivateLocation && ( + <> + + + + )} {loading ? ( @@ -51,7 +57,7 @@ export const ManagePrivateLocations = () => { { return ( -

    - {canReadAgentPolicies && ( - - {policy ? ( - - {policy?.name} - - ) : ( - - {POLICY_IS_DELETED} - - )} - - )} -

    + {canReadAgentPolicies && ( + + {policy ? ( + + {policy?.name} + + ) : ( + + {POLICY_IS_DELETED} + + )} + + )}
    ); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_fleet_permissions.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_fleet_permissions.ts index bbd5aa4f681bf..2ed8af08891ab 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_fleet_permissions.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_fleet_permissions.ts @@ -31,6 +31,12 @@ export function useCanUpdatePrivateMonitor(monitor: EncryptedSyntheticsMonitor) return canUpdatePrivateMonitor(monitor, canSaveIntegrations); } +export function useCanManagePrivateLocation() { + const { canSaveIntegrations, canReadAgentPolicies } = useFleetPermissions(); + + return Boolean(canSaveIntegrations && canReadAgentPolicies); +} + export function canUpdatePrivateMonitor( monitor: EncryptedSyntheticsMonitor, canSaveIntegrations: boolean diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/manage_locations_flyout.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/manage_locations_flyout.tsx index 103a9a37480db..805097312d4e8 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/manage_locations_flyout.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/manage_locations_flyout.tsx @@ -164,7 +164,7 @@ export const NEED_PERMISSIONS = i18n.translate( ); export const NEED_FLEET_READ_AGENT_POLICIES_PERMISSION = i18n.translate( - 'xpack.synthetics.monitorManagement.needFleetReadAgentPoliciesPermission', + 'xpack.synthetics.monitorManagement.needFleetReadAgentPoliciesPermissionUptime', { 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/legacy_uptime/components/monitor_management/monitor_config/locations.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_config/locations.tsx index 11e2588e909b7..3bcaa51c48f77 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_config/locations.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_config/locations.tsx @@ -146,7 +146,7 @@ export const INVALID_LABEL = i18n.translate('xpack.synthetics.monitorManagement. }); export const CANNOT_SAVE_INTEGRATION_LABEL = i18n.translate( - 'xpack.synthetics.monitorManagement.cannotSaveIntegration', + 'xpack.synthetics.monitorManagement.cannotSaveIntegrationUptime', { defaultMessage: 'You are not authorized to update integrations. Integrations write permissions are required.', diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 54d13791fa0d3..bc8fc835911fb 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -33706,7 +33706,6 @@ "xpack.synthetics.monitorManagement.monitorSync.failure.statusLabel": "Statut", "xpack.synthetics.monitorManagement.monitorSync.failure.title": "Impossible de synchroniser les moniteurs avec le service Synthetics", "xpack.synthetics.monitorManagement.nameRequired": "Le nom de l’emplacement est requis", - "xpack.synthetics.monitorManagement.needFleetReadAgentPoliciesPermission": "Vous n'êtes pas autorisé à accéder à Fleet. Des autorisations Fleet sont nécessaires pour créer de nouveaux emplacements privés.", "xpack.synthetics.monitorManagement.needPermissions": "Permissions requises", "xpack.synthetics.monitorManagement.new.label": "Nouveauté", "xpack.synthetics.monitorManagement.noLabel": "Annuler", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 774b9a54f191a..4bd272febf95a 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -33677,7 +33677,6 @@ "xpack.synthetics.monitorManagement.monitorSync.failure.statusLabel": "ステータス", "xpack.synthetics.monitorManagement.monitorSync.failure.title": "モニターをSyntheticsサービスと同期できませんでした", "xpack.synthetics.monitorManagement.nameRequired": "場所名は必須です", - "xpack.synthetics.monitorManagement.needFleetReadAgentPoliciesPermission": "Fleet へのアクセスが許可されていません。新しい非公開の場所を作成するには、Fleet権限が必要です。", "xpack.synthetics.monitorManagement.needPermissions": "権限が必要です", "xpack.synthetics.monitorManagement.new.label": "新規", "xpack.synthetics.monitorManagement.noLabel": "キャンセル", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 27e7ec4722827..d1d3729f26079 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -33712,7 +33712,6 @@ "xpack.synthetics.monitorManagement.monitorSync.failure.statusLabel": "状态", "xpack.synthetics.monitorManagement.monitorSync.failure.title": "监测无法与 Synthetics 服务同步", "xpack.synthetics.monitorManagement.nameRequired": "“位置名称”必填", - "xpack.synthetics.monitorManagement.needFleetReadAgentPoliciesPermission": "您无权访问 Fleet。需要 Fleet 权限才能创建新的专用位置。", "xpack.synthetics.monitorManagement.needPermissions": "需要权限", "xpack.synthetics.monitorManagement.new.label": "新建", "xpack.synthetics.monitorManagement.noLabel": "取消", From d783aae004658c0c7fd182d5f717a12308e406bc Mon Sep 17 00:00:00 2001 From: Karl Godard Date: Tue, 28 Feb 2023 16:46:30 -0800 Subject: [PATCH 069/131] [Defend for containers] cloud_defend plugin UI boilerplate (#151533) ## Summary This PR aims to create a footprint in the "security_solution" manage page for the new cloud_defend integration (and kibana plugin). Most of the changes are taken from the cloud_security_posture plugin architecture. The following additions have been made: - "Cloud security posture" category in manage page now includes a link to a new "Defend for containers" policies page (I originally created a new category for cloud_defend, but having two full categories with a single link is kind of a waste of real estate). - Cloud defend page wrapper to handle empty states, and the flows for when the integration is not yet installed, or user doesn't have cloud enterprise subscription. - Basic policies page to serve as a baseline for future detail around each cloud_defend integration (e.g selector / response / alert counts). - Application router and sub plugin tie'ins to security_solution. *Apologies in advance for the large PR :)* ### Screenshots Manage link ![image](https://user-images.githubusercontent.com/16198204/219512810-37f03d1b-0170-49e8-b5be-64b5b6ae20df.png) Policies page ![image](https://user-images.githubusercontent.com/16198204/219512772-a68fbb6d-4a30-439b-a11d-9ac2c95c8bda.png) ### 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 - [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)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 5 +- x-pack/plugins/cloud_defend/README.md | 1 + .../plugins/cloud_defend/common/constants.ts | 9 +- .../cloud_defend/common/schemas/policy.ts | 62 +++ x-pack/plugins/cloud_defend/common/types.ts | 54 ++ .../cloud_defend/common/utils/helpers.ts | 35 ++ .../common/utils/subscription.test.ts | 44 ++ .../cloud_defend/common/utils/subscription.ts | 24 + x-pack/plugins/cloud_defend/kibana.jsonc | 23 +- .../cloud_defend/public/application/route.tsx | 50 ++ .../public/application/router.test.tsx | 94 ++++ .../public/application/router.tsx | 52 ++ .../application/security_solution_context.ts | 16 + .../public/application/setup_context.ts | 16 + .../cloud_defend/public/assets/icons/logo.svg | 13 + .../api/use_cloud_defend_integration.tsx | 26 + .../public/common/api/use_setup_status_api.ts | 21 + .../cloud_defend/public/common/constants.ts | 2 + .../public/common/hooks/use_kibana.ts | 14 + .../public/common/hooks/use_page_size.ts | 26 + .../common/hooks/use_subscription_status.ts | 22 + .../public/common/navigation/constants.ts | 26 + .../security_solution_links.test.ts | 39 ++ .../navigation/security_solution_links.ts | 51 ++ .../public/common/navigation/types.ts | 23 + .../use_cloud_defend_integration_links.ts | 50 ++ .../cloud_defend_page/index.test.tsx | 361 +++++++++++++ .../components/cloud_defend_page/index.tsx | 294 +++++++++++ .../cloud_defend_page_title/index.tsx | 19 + .../components/full_size_page/index.tsx | 28 + .../public/components/loading_state/index.tsx | 24 + .../components/policies_table/index.test.tsx | 126 +++++ .../components/policies_table/index.tsx | 157 ++++++ .../subscription_not_allowed/index.tsx | 52 ++ .../components/timestamp_table_cell/index.tsx | 24 + x-pack/plugins/cloud_defend/public/index.ts | 8 + .../cloud_defend/public/pages/index.ts | 8 + .../public/pages/policies/index.test.tsx | 93 ++++ .../public/pages/policies/index.tsx | 197 +++++++ .../public/pages/policies/test_subjects.ts | 17 + .../policies/use_cloud_defend_policies.ts | 46 ++ x-pack/plugins/cloud_defend/public/plugin.ts | 44 -- x-pack/plugins/cloud_defend/public/plugin.tsx | 86 +++ .../test/fixtures/cloud_defend_integration.ts | 61 +++ .../public/test/fixtures/navigation_item.ts | 24 + .../public/test/fixtures/react_query.ts | 48 ++ .../plugins/cloud_defend/public/test/mocks.ts | 8 +- .../public/test/test_provider.tsx | 4 +- x-pack/plugins/cloud_defend/public/types.ts | 37 +- x-pack/plugins/cloud_defend/server/index.ts | 18 + .../server/lib/check_index_status.ts | 35 ++ .../cloud_defend/server/lib/fleet_util.ts | 119 +++++ x-pack/plugins/cloud_defend/server/mocks.ts | 36 ++ x-pack/plugins/cloud_defend/server/plugin.ts | 68 +++ .../server/routes/policies/policies.test.ts | 261 ++++++++++ .../server/routes/policies/policies.ts | 115 ++++ .../server/routes/setup_routes.ts | 61 +++ .../server/routes/status/status.test.ts | 493 ++++++++++++++++++ .../server/routes/status/status.ts | 198 +++++++ x-pack/plugins/cloud_defend/server/types.ts | 67 +++ x-pack/plugins/cloud_defend/tsconfig.json | 23 +- .../security_solution/common/constants.ts | 5 + x-pack/plugins/security_solution/kibana.jsonc | 1 + .../public/app/deep_links/index.ts | 12 +- .../public/app/home/home_navigations.ts | 5 + .../public/cloud_defend/index.ts | 17 + .../public/cloud_defend/links.ts | 26 + .../public/cloud_defend/routes.tsx | 51 ++ .../public/cloud_security_posture/links.ts | 5 +- .../common/components/navigation/types.ts | 2 + .../public/lazy_sub_plugins.tsx | 2 + .../public/management/icons/cloud_defend.tsx | 43 ++ .../public/management/links.ts | 2 + .../security_solution/public/plugin.tsx | 2 + .../plugins/security_solution/public/types.ts | 5 + .../plugins/security_solution/tsconfig.json | 1 + 76 files changed, 4166 insertions(+), 71 deletions(-) create mode 100644 x-pack/plugins/cloud_defend/common/schemas/policy.ts create mode 100644 x-pack/plugins/cloud_defend/common/types.ts create mode 100644 x-pack/plugins/cloud_defend/common/utils/helpers.ts create mode 100644 x-pack/plugins/cloud_defend/common/utils/subscription.test.ts create mode 100644 x-pack/plugins/cloud_defend/common/utils/subscription.ts create mode 100644 x-pack/plugins/cloud_defend/public/application/route.tsx create mode 100644 x-pack/plugins/cloud_defend/public/application/router.test.tsx create mode 100644 x-pack/plugins/cloud_defend/public/application/router.tsx create mode 100644 x-pack/plugins/cloud_defend/public/application/security_solution_context.ts create mode 100644 x-pack/plugins/cloud_defend/public/application/setup_context.ts create mode 100644 x-pack/plugins/cloud_defend/public/assets/icons/logo.svg create mode 100644 x-pack/plugins/cloud_defend/public/common/api/use_cloud_defend_integration.tsx create mode 100644 x-pack/plugins/cloud_defend/public/common/api/use_setup_status_api.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/hooks/use_kibana.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/hooks/use_page_size.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/hooks/use_subscription_status.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/navigation/constants.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.test.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/navigation/types.ts create mode 100644 x-pack/plugins/cloud_defend/public/common/navigation/use_cloud_defend_integration_links.ts create mode 100644 x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.test.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/cloud_defend_page_title/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/full_size_page/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/loading_state/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/policies_table/index.test.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/policies_table/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/subscription_not_allowed/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/components/timestamp_table_cell/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/pages/index.ts create mode 100644 x-pack/plugins/cloud_defend/public/pages/policies/index.test.tsx create mode 100644 x-pack/plugins/cloud_defend/public/pages/policies/index.tsx create mode 100644 x-pack/plugins/cloud_defend/public/pages/policies/test_subjects.ts create mode 100644 x-pack/plugins/cloud_defend/public/pages/policies/use_cloud_defend_policies.ts delete mode 100755 x-pack/plugins/cloud_defend/public/plugin.ts create mode 100755 x-pack/plugins/cloud_defend/public/plugin.tsx create mode 100644 x-pack/plugins/cloud_defend/public/test/fixtures/cloud_defend_integration.ts create mode 100644 x-pack/plugins/cloud_defend/public/test/fixtures/navigation_item.ts create mode 100644 x-pack/plugins/cloud_defend/public/test/fixtures/react_query.ts create mode 100644 x-pack/plugins/cloud_defend/server/index.ts create mode 100644 x-pack/plugins/cloud_defend/server/lib/check_index_status.ts create mode 100644 x-pack/plugins/cloud_defend/server/lib/fleet_util.ts create mode 100644 x-pack/plugins/cloud_defend/server/mocks.ts create mode 100644 x-pack/plugins/cloud_defend/server/plugin.ts create mode 100644 x-pack/plugins/cloud_defend/server/routes/policies/policies.test.ts create mode 100644 x-pack/plugins/cloud_defend/server/routes/policies/policies.ts create mode 100644 x-pack/plugins/cloud_defend/server/routes/setup_routes.ts create mode 100644 x-pack/plugins/cloud_defend/server/routes/status/status.test.ts create mode 100644 x-pack/plugins/cloud_defend/server/routes/status/status.ts create mode 100644 x-pack/plugins/cloud_defend/server/types.ts create mode 100644 x-pack/plugins/security_solution/public/cloud_defend/index.ts create mode 100644 x-pack/plugins/security_solution/public/cloud_defend/links.ts create mode 100644 x-pack/plugins/security_solution/public/cloud_defend/routes.tsx create mode 100644 x-pack/plugins/security_solution/public/management/icons/cloud_defend.tsx diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 27a7f01ec78e9..c30906c56c2ac 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1158,12 +1158,15 @@ x-pack/test/threat_intelligence_cypress @elastic/protections-experience /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 Defend +/x-pack/plugins/cloud_defend/ @elastic/sec-cloudnative-integrations +/x-pack/plugins/security_solution/public/cloud_defend @elastic/sec-cloudnative-integrations + # 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 diff --git a/x-pack/plugins/cloud_defend/README.md b/x-pack/plugins/cloud_defend/README.md index c0175af9cc2a6..9df1a13d328d2 100755 --- a/x-pack/plugins/cloud_defend/README.md +++ b/x-pack/plugins/cloud_defend/README.md @@ -42,6 +42,7 @@ responses: ``` node scripts/type_check.js --project x-pack/plugins/cloud_defend/tsconfig.json +node scripts/eslint.js x-pack/plugins/cloud_defend yarn test:jest x-pack/plugins/cloud_defend ``` diff --git a/x-pack/plugins/cloud_defend/common/constants.ts b/x-pack/plugins/cloud_defend/common/constants.ts index 860f3d4adffea..8fc54773da295 100755 --- a/x-pack/plugins/cloud_defend/common/constants.ts +++ b/x-pack/plugins/cloud_defend/common/constants.ts @@ -4,9 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; export const PLUGIN_ID = 'cloudDefend'; -export const PLUGIN_NAME = 'cloudDefend'; +export const PLUGIN_NAME = 'Cloud Defend'; export const INTEGRATION_PACKAGE_NAME = 'cloud_defend'; export const INPUT_CONTROL = 'cloud_defend/control'; export const ALERTS_DATASET = 'cloud_defend.alerts'; +export const ALERTS_INDEX_PATTERN = 'cloud_defend.alerts*'; + +export const POLICIES_ROUTE_PATH = '/internal/cloud_defend/policies'; +export const STATUS_ROUTE_PATH = '/internal/cloud_defend/status'; + +export const CLOUD_DEFEND_FLEET_PACKAGE_KUERY = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${INTEGRATION_PACKAGE_NAME}`; diff --git a/x-pack/plugins/cloud_defend/common/schemas/policy.ts b/x-pack/plugins/cloud_defend/common/schemas/policy.ts new file mode 100644 index 0000000000000..c6fff63b6bb81 --- /dev/null +++ b/x-pack/plugins/cloud_defend/common/schemas/policy.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { type TypeOf, schema } from '@kbn/config-schema'; + +export const DEFAULT_POLICIES_PER_PAGE = 20; +export const POLICIES_PACKAGE_POLICY_PREFIX = 'package_policy.'; +export const policiesQueryParamsSchema = schema.object({ + /** + * The page of objects to return + */ + page: schema.number({ defaultValue: 1, min: 1 }), + /** + * The number of objects to include in each page + */ + per_page: schema.number({ defaultValue: DEFAULT_POLICIES_PER_PAGE, min: 0 }), + /** + * Once of PackagePolicy fields for sorting the found objects. + * Sortable fields: + * - package_policy.id + * - package_policy.name + * - package_policy.policy_id + * - package_policy.namespace + * - package_policy.updated_at + * - package_policy.updated_by + * - package_policy.created_at + * - package_policy.created_by, + * - package_policy.package.name + * - package_policy.package.title + * - package_policy.package.version + */ + sort_field: schema.oneOf( + [ + schema.literal('package_policy.id'), + schema.literal('package_policy.name'), + schema.literal('package_policy.policy_id'), + schema.literal('package_policy.namespace'), + schema.literal('package_policy.updated_at'), + schema.literal('package_policy.updated_by'), + schema.literal('package_policy.created_at'), + schema.literal('package_policy.created_by'), + schema.literal('package_policy.package.name'), + schema.literal('package_policy.package.title'), + ], + { defaultValue: 'package_policy.name' } + ), + /** + * The order to sort by + */ + sort_order: schema.oneOf([schema.literal('asc'), schema.literal('desc')], { + defaultValue: 'asc', + }), + /** + * Policy filter + */ + policy_name: schema.maybe(schema.string()), +}); + +export type PoliciesQueryParams = TypeOf; diff --git a/x-pack/plugins/cloud_defend/common/types.ts b/x-pack/plugins/cloud_defend/common/types.ts new file mode 100644 index 0000000000000..c3bdbb4418183 --- /dev/null +++ b/x-pack/plugins/cloud_defend/common/types.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PackagePolicy, AgentPolicy } from '@kbn/fleet-plugin/common'; + +export type IndexStatus = + | 'not-empty' // Index contains documents + | 'empty' // Index doesn't contain documents (or doesn't exist) + | 'unprivileged'; // User doesn't have access to query the index + +export type CloudDefendStatusCode = + | 'indexed' // alerts index exists and has results + | 'indexing' // index timeout was not surpassed since installation, assumes data is being indexed + | 'unprivileged' // user lacks privileges for the alerts index + | 'index-timeout' // index timeout was surpassed since installation + | 'not-deployed' // no healthy agents were deployed + | 'not-installed'; // number of installed integrations is 0; + +export interface IndexDetails { + index: string; + status: IndexStatus; +} + +interface BaseCloudDefendSetupStatus { + indicesDetails: IndexDetails[]; + latestPackageVersion: string; + installedPackagePolicies: number; + healthyAgents: number; +} + +interface CloudDefendSetupNotInstalledStatus extends BaseCloudDefendSetupStatus { + status: Extract; +} + +interface CloudDefendSetupInstalledStatus extends BaseCloudDefendSetupStatus { + status: Exclude; + // status can be `indexed` but return with undefined package information in this case + installedPackageVersion: string | undefined; +} + +export type CloudDefendSetupStatus = + | CloudDefendSetupInstalledStatus + | CloudDefendSetupNotInstalledStatus; + +export type AgentPolicyStatus = Pick & { agents: number }; + +export interface CloudDefendPolicy { + package_policy: PackagePolicy; + agent_policy: AgentPolicyStatus; +} diff --git a/x-pack/plugins/cloud_defend/common/utils/helpers.ts b/x-pack/plugins/cloud_defend/common/utils/helpers.ts new file mode 100644 index 0000000000000..14b506e8d2e70 --- /dev/null +++ b/x-pack/plugins/cloud_defend/common/utils/helpers.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Truthy } from 'lodash'; +import { INTEGRATION_PACKAGE_NAME } from '../constants'; + +/** + * @example + * declare const foo: Array + * foo.filter(isNonNullable) // foo is Array + */ +export const isNonNullable = (v: T): v is NonNullable => + v !== null && v !== undefined; + +export const truthy = (value: T): value is Truthy => !!value; + +export const extractErrorMessage = (e: unknown, defaultMessage = 'Unknown Error'): string => { + if (e instanceof Error) return e.message; + if (typeof e === 'string') return e; + + return defaultMessage; // TODO: i18n +}; + +export function assert(condition: any, msg?: string): asserts condition { + if (!condition) { + throw new Error(msg); + } +} + +export const isCloudDefendPackage = (packageName?: string) => + packageName === INTEGRATION_PACKAGE_NAME; diff --git a/x-pack/plugins/cloud_defend/common/utils/subscription.test.ts b/x-pack/plugins/cloud_defend/common/utils/subscription.test.ts new file mode 100644 index 0000000000000..e47b887ae520f --- /dev/null +++ b/x-pack/plugins/cloud_defend/common/utils/subscription.test.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 type { LicenseType } from '@kbn/licensing-plugin/common/types'; +import { isSubscriptionAllowed } from './subscription'; +import { licenseMock } from '@kbn/licensing-plugin/common/licensing.mock'; + +const ON_PREM_ALLOWED_LICENSES: readonly LicenseType[] = ['enterprise', 'trial']; +const ON_PREM_NOT_ALLOWED_LICENSES: readonly LicenseType[] = ['basic', 'gold', 'platinum']; +const ALL_LICENSE_TYPES: readonly LicenseType[] = [ + 'standard', + ...ON_PREM_NOT_ALLOWED_LICENSES, + ...ON_PREM_NOT_ALLOWED_LICENSES, +]; + +describe('isSubscriptionAllowed', () => { + it('should allow any cloud subscription', () => { + const isCloudEnabled = true; + ALL_LICENSE_TYPES.forEach((licenseType) => { + const license = licenseMock.createLicense({ license: { type: licenseType } }); + expect(isSubscriptionAllowed(isCloudEnabled, license)).toBeTruthy(); + }); + }); + + it('should allow enterprise and trial licenses for on-prem', () => { + const isCloudEnabled = false; + ON_PREM_ALLOWED_LICENSES.forEach((licenseType) => { + const license = licenseMock.createLicense({ license: { type: licenseType } }); + expect(isSubscriptionAllowed(isCloudEnabled, license)).toBeTruthy(); + }); + }); + + it('should not allow enterprise and trial licenses for on-prem', () => { + const isCloudEnabled = false; + ON_PREM_NOT_ALLOWED_LICENSES.forEach((licenseType) => { + const license = licenseMock.createLicense({ license: { type: licenseType } }); + expect(isSubscriptionAllowed(isCloudEnabled, license)).toBeFalsy(); + }); + }); +}); diff --git a/x-pack/plugins/cloud_defend/common/utils/subscription.ts b/x-pack/plugins/cloud_defend/common/utils/subscription.ts new file mode 100644 index 0000000000000..e54eb0c4d4581 --- /dev/null +++ b/x-pack/plugins/cloud_defend/common/utils/subscription.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ILicense, LicenseType } from '@kbn/licensing-plugin/common/types'; +import { PLUGIN_NAME } from '../constants'; + +const MINIMUM_NON_CLOUD_LICENSE_TYPE: LicenseType = 'enterprise'; + +export const isSubscriptionAllowed = (isCloudEnabled?: boolean, license?: ILicense): boolean => { + if (isCloudEnabled) { + return true; + } + + if (!license) { + return false; + } + + const licenseCheck = license.check(PLUGIN_NAME, MINIMUM_NON_CLOUD_LICENSE_TYPE); + return licenseCheck.state === 'valid'; +}; diff --git a/x-pack/plugins/cloud_defend/kibana.jsonc b/x-pack/plugins/cloud_defend/kibana.jsonc index f561c33a5f832..392724467fd70 100644 --- a/x-pack/plugins/cloud_defend/kibana.jsonc +++ b/x-pack/plugins/cloud_defend/kibana.jsonc @@ -2,14 +2,31 @@ "type": "plugin", "id": "@kbn/cloud-defend-plugin", "owner": "@elastic/sec-cloudnative-integrations", - "description": "Defend for Containers", + "description": "Defend for containers (D4C)", "plugin": { "id": "cloudDefend", - "server": false, + "server": true, "browser": true, + "configPath": [ + "xpack", + "cloudDefend" + ], "requiredPlugins": [ + "navigation", + "data", "fleet", - "kibanaReact" + "unifiedSearch", + "kibanaReact", + "cloud", + "security", + "licensing" + ], + "optionalPlugins": [ + "usageCollection" + ], + "requiredBundles": [ + "kibanaReact", + "usageCollection" ] } } diff --git a/x-pack/plugins/cloud_defend/public/application/route.tsx b/x-pack/plugins/cloud_defend/public/application/route.tsx new file mode 100644 index 0000000000000..27959ec0845e5 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/application/route.tsx @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { Route } from '@kbn/shared-ux-router'; +import { type RouteProps } from 'react-router-dom'; +import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; +import { cloudDefendPages } from '../common/navigation/constants'; +import { useSecuritySolutionContext } from './security_solution_context'; +import type { CloudDefendPageNavigationItem } from '../common/navigation/types'; + +type CloudDefendRouteProps = Omit & CloudDefendPageNavigationItem; + +// Security SpyRoute can be automatically rendered for pages with static paths, Security will manage everything using the `links` object. +// Pages with dynamic paths are not in the Security `links` object, they must render SpyRoute with the parameters values, if needed. +const STATIC_PATH_PAGE_IDS = Object.fromEntries( + Object.values(cloudDefendPages).map(({ id }) => [id, true]) +); + +export const CloudDefendRoute: React.FC = ({ + id, + children, + component: Component, + disabled = false, + ...cloudDefendRouteProps +}) => { + const SpyRoute = useSecuritySolutionContext()?.getSpyRouteComponent(); + + if (disabled) { + return null; + } + + const routeProps: RouteProps = { + ...cloudDefendRouteProps, + ...(Component && { + render: (renderProps) => ( + + {STATIC_PATH_PAGE_IDS[id] && SpyRoute && } + + + ), + }), + }; + + return {children}; +}; diff --git a/x-pack/plugins/cloud_defend/public/application/router.test.tsx b/x-pack/plugins/cloud_defend/public/application/router.test.tsx new file mode 100644 index 0000000000000..af7766a290fca --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/application/router.test.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import CloudDefendRouter from './router'; +import React from 'react'; +import { render } from '@testing-library/react'; +import { Router } from 'react-router-dom'; +import type { CloudDefendPage, CloudDefendPageNavigationItem } from '../common/navigation/types'; +import { CloudDefendSecuritySolutionContext } from '../types'; +import { createMemoryHistory, MemoryHistory } from 'history'; +import * as constants from '../common/navigation/constants'; +import { QueryClientProviderProps } from '@tanstack/react-query'; + +jest.mock('../pages/policies', () => ({ + Policies: () =>
    Policies
    , +})); + +jest.mock('@tanstack/react-query', () => ({ + QueryClientProvider: ({ children }: QueryClientProviderProps) => <>{children}, + QueryClient: jest.fn(), +})); + +describe('CloudDefendRouter', () => { + const originalCloudDefendPages = { ...constants.cloudDefendPages }; + const mockConstants = constants as { + cloudDefendPages: Record; + }; + + const securityContext: CloudDefendSecuritySolutionContext = { + getFiltersGlobalComponent: jest.fn(), + getSpyRouteComponent: () => () =>
    , + }; + + let history: MemoryHistory; + + const renderCloudDefendRouter = () => + render( + + + + ); + + beforeEach(() => { + mockConstants.cloudDefendPages = originalCloudDefendPages; + jest.clearAllMocks(); + history = createMemoryHistory(); + }); + + describe('happy path', () => { + it('should render Policies', () => { + history.push('/cloud_defend/policies'); + const result = renderCloudDefendRouter(); + + expect(result.queryByTestId('Policies')).toBeInTheDocument(); + }); + }); + + describe('unhappy path', () => { + it('should redirect base path to policies', () => { + history.push('/cloud_defend/some_wrong_path'); + const result = renderCloudDefendRouter(); + + expect(history.location.pathname).toEqual('/cloud_defend/policies'); + expect(result.queryByTestId('Policies')).toBeInTheDocument(); + }); + }); + + describe('CloudDefendRoute', () => { + it('should not render disabled path', () => { + mockConstants.cloudDefendPages = { + ...constants.cloudDefendPages, + policies: { + ...constants.cloudDefendPages.policies, + disabled: true, + }, + }; + + history.push('/cloud_defend/policies'); + const result = renderCloudDefendRouter(); + + expect(result.queryByTestId('Policies')).not.toBeInTheDocument(); + }); + + it('should render SpyRoute for static paths', () => { + history.push('/cloud_defend/policies'); + const result = renderCloudDefendRouter(); + + expect(result.queryByTestId('mockedSpyRoute')).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/cloud_defend/public/application/router.tsx b/x-pack/plugins/cloud_defend/public/application/router.tsx new file mode 100644 index 0000000000000..3fa261d35c765 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/application/router.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { Redirect, Switch } from 'react-router-dom'; +import { Route } from '@kbn/shared-ux-router'; +import { cloudDefendPages } from '../common/navigation/constants'; +import type { CloudDefendSecuritySolutionContext } from '../types'; +import { SecuritySolutionContext } from './security_solution_context'; +import { Policies } from '../pages/policies'; +import { CloudDefendRoute } from './route'; + +const queryClient = new QueryClient({ + defaultOptions: { queries: { refetchOnWindowFocus: false } }, +}); + +export interface CloudDefendRouterProps { + securitySolutionContext?: CloudDefendSecuritySolutionContext; +} + +export const CloudDefendRouter = ({ securitySolutionContext }: CloudDefendRouterProps) => { + const routerElement = ( + + + + + + + + + + ); + + if (securitySolutionContext) { + return ( + + {routerElement} + + ); + } + + return <>{routerElement}; +}; + +// Using a default export for usage with `React.lazy` +// eslint-disable-next-line import/no-default-export +export { CloudDefendRouter as default }; diff --git a/x-pack/plugins/cloud_defend/public/application/security_solution_context.ts b/x-pack/plugins/cloud_defend/public/application/security_solution_context.ts new file mode 100644 index 0000000000000..fcbd10057021c --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/application/security_solution_context.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, { useContext } from 'react'; +import type { CloudDefendSecuritySolutionContext } from '../types'; + +export const SecuritySolutionContext = React.createContext< + CloudDefendSecuritySolutionContext | undefined +>(undefined); + +export const useSecuritySolutionContext = () => { + return useContext(SecuritySolutionContext); +}; diff --git a/x-pack/plugins/cloud_defend/public/application/setup_context.ts b/x-pack/plugins/cloud_defend/public/application/setup_context.ts new file mode 100644 index 0000000000000..574404ace38ce --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/application/setup_context.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { createContext } from 'react'; + +interface SetupContextValue { + isCloudEnabled?: boolean; +} + +/** + * A utility to pass data from the plugin setup lifecycle stage to application components + */ +export const SetupContext = createContext({}); diff --git a/x-pack/plugins/cloud_defend/public/assets/icons/logo.svg b/x-pack/plugins/cloud_defend/public/assets/icons/logo.svg new file mode 100644 index 0000000000000..a0534292eb717 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/assets/icons/logo.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/x-pack/plugins/cloud_defend/public/common/api/use_cloud_defend_integration.tsx b/x-pack/plugins/cloud_defend/public/common/api/use_cloud_defend_integration.tsx new file mode 100644 index 0000000000000..c41ffdab0851c --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/api/use_cloud_defend_integration.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useQuery } from '@tanstack/react-query'; +import { + epmRouteService, + type GetInfoResponse, + type DefaultPackagesInstallationError, +} from '@kbn/fleet-plugin/common'; +import { INTEGRATION_PACKAGE_NAME } from '../../../common/constants'; +import { useKibana } from '../hooks/use_kibana'; + +/** + * This hook will find our integration and return its PackageInfo + * */ +export const useCloudDefendIntegration = () => { + const { http } = useKibana().services; + + return useQuery(['integrations'], () => + http.get(epmRouteService.getInfoPath(INTEGRATION_PACKAGE_NAME)) + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/common/api/use_setup_status_api.ts b/x-pack/plugins/cloud_defend/public/common/api/use_setup_status_api.ts new file mode 100644 index 0000000000000..2d07d138e8d92 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/api/use_setup_status_api.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useQuery } from '@tanstack/react-query'; +import { useKibana } from '../hooks/use_kibana'; +import { CloudDefendSetupStatus } from '../../../common/types'; +import { STATUS_ROUTE_PATH } from '../../../common/constants'; + +const getCloudDefendSetupStatusQueryKey = 'cloud_defend_status_key'; + +export const useCloudDefendSetupStatusApi = () => { + const { http } = useKibana().services; + return useQuery( + [getCloudDefendSetupStatusQueryKey], + () => http.get(STATUS_ROUTE_PATH) + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/common/constants.ts b/x-pack/plugins/cloud_defend/public/common/constants.ts index d0baec8804ff7..1e101a47c0122 100644 --- a/x-pack/plugins/cloud_defend/public/common/constants.ts +++ b/x-pack/plugins/cloud_defend/public/common/constants.ts @@ -4,6 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +export const DEFAULT_VISIBLE_ROWS_PER_PAGE = 10; // generic default # of table rows to show (currently we only have a list of policies) +export const LOCAL_STORAGE_PAGE_SIZE = 'cloudDefend:userPageSize'; export const VALID_SELECTOR_NAME_REGEX = /^[a-z0-9][a-z0-9_\-]+$/i; // alphanumberic (no - or _ allowed on first char) export const MAX_SELECTOR_NAME_LENGTH = 128; // chars export const MAX_CONDITION_VALUE_LENGTH_BYTES = 511; diff --git a/x-pack/plugins/cloud_defend/public/common/hooks/use_kibana.ts b/x-pack/plugins/cloud_defend/public/common/hooks/use_kibana.ts new file mode 100644 index 0000000000000..261afc07db00f --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/hooks/use_kibana.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { CoreStart } from '@kbn/core/public'; +import { useKibana as useKibanaBase } from '@kbn/kibana-react-plugin/public'; +import type { CloudDefendPluginStartDeps } from '../../types'; + +type CloudDefendKibanaContext = CoreStart & CloudDefendPluginStartDeps; + +export const useKibana = () => useKibanaBase(); diff --git a/x-pack/plugins/cloud_defend/public/common/hooks/use_page_size.ts b/x-pack/plugins/cloud_defend/public/common/hooks/use_page_size.ts new file mode 100644 index 0000000000000..314dfbe661d93 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/hooks/use_page_size.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import useLocalStorage from 'react-use/lib/useLocalStorage'; +import { DEFAULT_VISIBLE_ROWS_PER_PAGE } from '../constants'; + +/** + * @description handles persisting the users table row size selection + */ +export const usePageSize = (localStorageKey: string) => { + const [persistedPageSize, setPersistedPageSize] = useLocalStorage( + localStorageKey, + DEFAULT_VISIBLE_ROWS_PER_PAGE + ); + + let pageSize: number = DEFAULT_VISIBLE_ROWS_PER_PAGE; + + if (persistedPageSize) { + pageSize = persistedPageSize; + } + + return { pageSize, setPageSize: setPersistedPageSize }; +}; diff --git a/x-pack/plugins/cloud_defend/public/common/hooks/use_subscription_status.ts b/x-pack/plugins/cloud_defend/public/common/hooks/use_subscription_status.ts new file mode 100644 index 0000000000000..26dd4caa33c4d --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/hooks/use_subscription_status.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { useContext } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import { SetupContext } from '../../application/setup_context'; +import { isSubscriptionAllowed } from '../../../common/utils/subscription'; +import { useKibana } from './use_kibana'; + +const SUBSCRIPTION_QUERY_KEY = 'cloud_defend_subscription_query_key'; + +export const useSubscriptionStatus = () => { + const { licensing } = useKibana().services; + const { isCloudEnabled } = useContext(SetupContext); + return useQuery([SUBSCRIPTION_QUERY_KEY], async () => { + const license = await licensing.refresh(); + return isSubscriptionAllowed(isCloudEnabled, license); + }); +}; diff --git a/x-pack/plugins/cloud_defend/public/common/navigation/constants.ts b/x-pack/plugins/cloud_defend/public/common/navigation/constants.ts new file mode 100644 index 0000000000000..b166184dddb87 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/navigation/constants.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import type { CloudDefendPage, CloudDefendPageNavigationItem } from './types'; + +const NAV_ITEMS_NAMES = { + POLICIES: i18n.translate('xpack.cloudDefend.navigation.policiesNavItemLabel', { + defaultMessage: 'Defend for containers (D4C)', + }), +}; + +/** The base path for all cloud defend pages. */ +export const CLOUD_DEFEND_BASE_PATH = '/cloud_defend'; + +export const cloudDefendPages: Record = { + policies: { + name: NAV_ITEMS_NAMES.POLICIES, + path: `${CLOUD_DEFEND_BASE_PATH}/policies`, + id: 'cloud_defend-policies', + }, +}; diff --git a/x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.test.ts b/x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.test.ts new file mode 100644 index 0000000000000..f6cfe42d0583a --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.test.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { cloudDefendPages } from './constants'; +import { getSecuritySolutionLink, getSecuritySolutionNavTab } from './security_solution_links'; +import { Chance } from 'chance'; +import type { CloudDefendPage } from './types'; + +const chance = new Chance(); + +describe('getSecuritySolutionLink', () => { + it('gets the correct link properties', () => { + const cloudDefendPage = chance.pickone(['policies']); + + const link = getSecuritySolutionLink(cloudDefendPage); + + expect(link.id).toEqual(cloudDefendPages[cloudDefendPage].id); + expect(link.path).toEqual(cloudDefendPages[cloudDefendPage].path); + expect(link.title).toEqual(cloudDefendPages[cloudDefendPage].name); + }); +}); + +describe('getSecuritySolutionNavTab', () => { + it('gets the correct nav tab properties', () => { + const cloudDefendPage = chance.pickone(['policies']); + const basePath = chance.word(); + + const navTab = getSecuritySolutionNavTab(cloudDefendPage, basePath); + + expect(navTab.id).toEqual(cloudDefendPages[cloudDefendPage].id); + expect(navTab.name).toEqual(cloudDefendPages[cloudDefendPage].name); + expect(navTab.href).toEqual(`${basePath}${cloudDefendPages[cloudDefendPage].path}`); + expect(navTab.disabled).toEqual(!!cloudDefendPages[cloudDefendPage].disabled); + }); +}); diff --git a/x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts b/x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts new file mode 100644 index 0000000000000..58e816c135593 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { cloudDefendPages } from './constants'; +import type { CloudDefendPageId, CloudDefendPage } from './types'; + +interface CloudDefendLinkItem { + id: TId; + title: string; + path: string; +} + +interface CloudDefendNavTab { + id: TId; + name: string; + href: string; + disabled: boolean; +} + +/** + * Gets the cloud_defend link properties of a Cloud Defend page for navigation in the security solution. + * @param cloudDefendPage the name of the cloud defend page. + */ +export const getSecuritySolutionLink = ( + cloudDefendPage: CloudDefendPage +): CloudDefendLinkItem => { + return { + id: cloudDefendPages[cloudDefendPage].id as TId, + title: cloudDefendPages[cloudDefendPage].name, + path: cloudDefendPages[cloudDefendPage].path, + }; +}; + +/** + * Gets the link properties of a Cloud Defend page for navigation in the old security solution navigation. + * @param cloudDefendPage the name of the cloud defend page. + * @param basePath the base path for links. + */ +export const getSecuritySolutionNavTab = ( + cloudDefendPage: CloudDefendPage, + basePath: string +): CloudDefendNavTab => ({ + id: cloudDefendPages[cloudDefendPage].id as TId, + name: cloudDefendPages[cloudDefendPage].name, + href: `${basePath}${cloudDefendPages[cloudDefendPage].path}`, + disabled: !!cloudDefendPages[cloudDefendPage].disabled, +}); diff --git a/x-pack/plugins/cloud_defend/public/common/navigation/types.ts b/x-pack/plugins/cloud_defend/public/common/navigation/types.ts new file mode 100644 index 0000000000000..56da6ac4c3948 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/navigation/types.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export interface CloudDefendNavigationItem { + readonly name: string; + readonly path: string; + readonly disabled?: boolean; +} + +export interface CloudDefendPageNavigationItem extends CloudDefendNavigationItem { + id: CloudDefendPageId; +} + +export type CloudDefendPage = 'policies'; + +/** + * All the IDs for the cloud defend pages. + * This needs to match the cloud defend page entries in `SecurityPageName` in `x-pack/plugins/security_solution/common/constants.ts`. + */ +export type CloudDefendPageId = 'cloud_defend-policies'; diff --git a/x-pack/plugins/cloud_defend/public/common/navigation/use_cloud_defend_integration_links.ts b/x-pack/plugins/cloud_defend/public/common/navigation/use_cloud_defend_integration_links.ts new file mode 100644 index 0000000000000..b2d0cca31fcba --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/common/navigation/use_cloud_defend_integration_links.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { pagePathGetters, pkgKeyFromPackageInfo } from '@kbn/fleet-plugin/public'; +import { INTEGRATION_PACKAGE_NAME } from '../../../common/constants'; +import { useCloudDefendIntegration } from '../api/use_cloud_defend_integration'; +import { useKibana } from '../hooks/use_kibana'; + +export const useCloudDefendIntegrationLinks = (): { + addIntegrationLink: string | undefined; + docsLink: string; +} => { + const { http } = useKibana().services; + const cloudDefendIntegration = useCloudDefendIntegration(); + + if (!cloudDefendIntegration.isSuccess) + return { + addIntegrationLink: undefined, + docsLink: 'https://www.elastic.co/guide/index.html', + }; + + const addIntegrationLink = pagePathGetters + .add_integration_to_policy({ + integration: INTEGRATION_PACKAGE_NAME, + pkgkey: pkgKeyFromPackageInfo({ + name: cloudDefendIntegration.data.item.name, + version: cloudDefendIntegration.data.item.version, + }), + }) + .join(''); + + const docsLink = pagePathGetters + .integration_details_overview({ + integration: INTEGRATION_PACKAGE_NAME, + pkgkey: pkgKeyFromPackageInfo({ + name: cloudDefendIntegration.data.item.name, + version: cloudDefendIntegration.data.item.version, + }), + }) + .join(''); + + return { + addIntegrationLink: http.basePath.prepend(addIntegrationLink), + docsLink: http.basePath.prepend(docsLink), + }; +}; diff --git a/x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.test.tsx b/x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.test.tsx new file mode 100644 index 0000000000000..4c620a73dcfa9 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.test.tsx @@ -0,0 +1,361 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; +import Chance from 'chance'; +import { + CloudDefendPage, + DEFAULT_NO_DATA_TEST_SUBJECT, + ERROR_STATE_TEST_SUBJECT, + isCommonError, + LOADING_STATE_TEST_SUBJECT, + PACKAGE_NOT_INSTALLED_TEST_SUBJECT, + SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT, +} from '.'; +import { createReactQueryResponse } from '../../test/fixtures/react_query'; +import { TestProvider } from '../../test/test_provider'; +import { coreMock } from '@kbn/core/public/mocks'; +import { render, screen } from '@testing-library/react'; +import React, { ComponentProps } from 'react'; +import { UseQueryResult } from '@tanstack/react-query'; +import { NoDataPage } from '@kbn/kibana-react-plugin/public'; +import { useCloudDefendSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useCloudDefendIntegrationLinks } from '../../common/navigation/use_cloud_defend_integration_links'; + +const chance = new Chance(); + +jest.mock('../../common/api/use_setup_status_api'); +jest.mock('../../common/hooks/use_subscription_status'); +jest.mock('../../common/navigation/use_cloud_defend_integration_links'); + +describe('', () => { + beforeEach(() => { + jest.resetAllMocks(); + (useCloudDefendSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed' }, + }) + ); + + (useCloudDefendIntegrationLinks as jest.Mock).mockImplementation(() => ({ + addIntegrationLink: chance.url(), + docsLink: chance.url(), + })); + + (useSubscriptionStatus as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: true, + }) + ); + }); + + const renderCloudDefendPage = ( + props: ComponentProps = { children: null } + ) => { + const mockCore = coreMock.createStart(); + + render( + + + + ); + }; + + it('renders children if setup status is indexed', () => { + const children = chance.sentence(); + renderCloudDefendPage({ children }); + + expect(screen.getByText(children)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default loading state when the subscription query is loading', () => { + (useSubscriptionStatus as jest.Mock).mockImplementation( + () => + createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult + ); + + const children = chance.sentence(); + renderCloudDefendPage({ children }); + + expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default error state when the subscription query has an error', () => { + (useSubscriptionStatus as jest.Mock).mockImplementation( + () => + createReactQueryResponse({ + status: 'error', + error: new Error('error'), + }) as unknown as UseQueryResult + ); + + const children = chance.sentence(); + renderCloudDefendPage({ children }); + + expect(screen.getByTestId(ERROR_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders subscription not allowed prompt if subscription is not installed', () => { + (useSubscriptionStatus as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: false, + }) + ); + + const children = chance.sentence(); + renderCloudDefendPage({ children }); + + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.getByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders integrations installation prompt if integration is not installed', () => { + (useCloudDefendSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'not-installed' }, + }) + ); + + const children = chance.sentence(); + renderCloudDefendPage({ children }); + + expect(screen.getByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default loading state when the integration query is loading', () => { + (useCloudDefendSetupStatusApi as jest.Mock).mockImplementation( + () => + createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult + ); + + const children = chance.sentence(); + renderCloudDefendPage({ children }); + + expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default error state when the integration query has an error', () => { + (useCloudDefendSetupStatusApi as jest.Mock).mockImplementation( + () => + createReactQueryResponse({ + status: 'error', + error: new Error('error'), + }) as unknown as UseQueryResult + ); + + const children = chance.sentence(); + renderCloudDefendPage({ children }); + + expect(screen.getByTestId(ERROR_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default loading text when query isLoading', () => { + const query = createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudDefendPage({ children, query }); + + expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default loading text when query is idle', () => { + const query = createReactQueryResponse({ + status: 'idle', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudDefendPage({ children, query }); + + expect(screen.getByTestId(LOADING_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders default error texts when query isError', () => { + const error = chance.sentence(); + const message = chance.sentence(); + const statusCode = chance.integer(); + + const query = createReactQueryResponse({ + status: 'error', + error: { + body: { + error, + message, + statusCode, + }, + }, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudDefendPage({ children, query }); + + [error, message, statusCode].forEach((text) => + expect(screen.getByText(text, { exact: false })).toBeInTheDocument() + ); + expect(screen.getByTestId(ERROR_STATE_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('prefers custom error render', () => { + const error = chance.sentence(); + const message = chance.sentence(); + const statusCode = chance.integer(); + + const query = createReactQueryResponse({ + status: 'error', + error: { + body: { + error, + message, + statusCode, + }, + }, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudDefendPage({ + children, + query, + errorRender: (err) =>
    {isCommonError(err) && err.body.message}
    , + }); + + expect(screen.getByText(message)).toBeInTheDocument(); + [error, statusCode].forEach((text) => expect(screen.queryByText(text)).not.toBeInTheDocument()); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('prefers custom loading render', () => { + const loading = chance.sentence(); + + const query = createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudDefendPage({ + children, + query, + loadingRender: () =>
    {loading}
    , + }); + + expect(screen.getByText(loading)).toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('renders no data prompt when query data is undefined', () => { + const query = createReactQueryResponse({ + status: 'success', + data: undefined, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudDefendPage({ children, query }); + + expect(screen.getByTestId(DEFAULT_NO_DATA_TEST_SUBJECT)).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); + + it('prefers custom no data prompt', () => { + const pageTitle = chance.sentence(); + const solution = chance.sentence(); + const docsLink = chance.sentence(); + const noDataRenderer = () => ( + + ); + + const query = createReactQueryResponse({ + status: 'success', + data: undefined, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCloudDefendPage({ + children, + query, + noDataRenderer, + }); + + expect(screen.getByText(pageTitle)).toBeInTheDocument(); + expect(screen.getAllByText(solution, { exact: false })[0]).toBeInTheDocument(); + expect(screen.queryByTestId(LOADING_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByTestId(ERROR_STATE_TEST_SUBJECT)).not.toBeInTheDocument(); + expect(screen.queryByTestId(PACKAGE_NOT_INSTALLED_TEST_SUBJECT)).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.tsx b/x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.tsx new file mode 100644 index 0000000000000..bc10db7ace74b --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/cloud_defend_page/index.tsx @@ -0,0 +1,294 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { i18n } from '@kbn/i18n'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { + EuiButton, + EuiEmptyPrompt, + EuiImage, + EuiFlexGroup, + EuiFlexItem, + EuiLink, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { NoDataPage, NoDataPageProps } from '@kbn/kibana-react-plugin/public'; +import { css } from '@emotion/react'; +import { SubscriptionNotAllowed } from '../subscription_not_allowed'; +import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; +import { FullSizeCenteredPage } from '../full_size_page'; +import { useCloudDefendSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { LoadingState } from '../loading_state'; +import { useCloudDefendIntegrationLinks } from '../../common/navigation/use_cloud_defend_integration_links'; + +import noDataIllustration from '../../assets/icons/logo.svg'; + +export const LOADING_STATE_TEST_SUBJECT = 'cloud_defend_page_loading'; +export const ERROR_STATE_TEST_SUBJECT = 'cloud_defend_page_error'; +export const PACKAGE_NOT_INSTALLED_TEST_SUBJECT = 'cloud_defend_page_package_not_installed'; +export const DEFAULT_NO_DATA_TEST_SUBJECT = 'cloud_defend_page_no_data'; +export const SUBSCRIPTION_NOT_ALLOWED_TEST_SUBJECT = 'cloud_defend_page_subscription_not_allowed'; + +interface CommonError { + body: { + error: string; + message: string; + statusCode: number; + }; +} + +export const isCommonError = (error: unknown): error is CommonError => { + if ( + !(error as any)?.body || + !(error as any)?.body?.error || + !(error as any)?.body?.message || + !(error as any)?.body?.statusCode + ) { + return false; + } + + return true; +}; + +export interface CloudDefendNoDataPageProps { + pageTitle: NoDataPageProps['pageTitle']; + docsLink: NoDataPageProps['docsLink']; + actionHref: NoDataPageProps['actions']['elasticAgent']['href']; + actionTitle: NoDataPageProps['actions']['elasticAgent']['title']; + actionDescription: NoDataPageProps['actions']['elasticAgent']['description']; + testId: string; +} + +export const CloudDefendNoDataPage = ({ + pageTitle, + docsLink, + actionHref, + actionTitle, + actionDescription, + testId, +}: CloudDefendNoDataPageProps) => { + return ( + :nth-child(3) { + display: block; + margin: auto; + width: 450px; + } + `} + pageTitle={pageTitle} + solution={i18n.translate( + 'xpack.cloudDefend.cloudDefendPage.packageNotInstalled.solutionNameLabel', + { + defaultMessage: 'Defend for containers (D4C)', + } + )} + docsLink={docsLink} + logo="logoSecurity" + actions={{ + elasticAgent: { + href: actionHref, + isDisabled: !actionHref, + title: actionTitle, + description: actionDescription, + }, + }} + /> + ); +}; + +const packageNotInstalledRenderer = ({ + addIntegrationLink, + docsLink, +}: { + addIntegrationLink?: string; + docsLink?: string; +}) => { + return ( + + } + title={ +

    + +

    + } + layout="horizontal" + color="plain" + body={ +

    + + + + ), + }} + /> +

    + } + actions={ + + + + + + + + } + /> +
    + ); +}; + +const defaultLoadingRenderer = () => ( + + + +); + +const defaultErrorRenderer = (error: unknown) => ( + + + + + } + body={ + isCommonError(error) ? ( +

    + +

    + ) : undefined + } + /> +
    +); + +const defaultNoDataRenderer = (docsLink: string) => ( + + + +); + +const subscriptionNotAllowedRenderer = () => ( + + + +); + +interface CloudDefendPageProps { + children: React.ReactNode; + query?: UseQueryResult; + loadingRender?: () => React.ReactNode; + errorRender?: (error: TError) => React.ReactNode; + noDataRenderer?: (docsLink: string) => React.ReactNode; +} + +export const CloudDefendPage = ({ + children, + query, + loadingRender = defaultLoadingRenderer, + errorRender = defaultErrorRenderer, + noDataRenderer = defaultNoDataRenderer, +}: CloudDefendPageProps) => { + const subscriptionStatus = useSubscriptionStatus(); + const getSetupStatus = useCloudDefendSetupStatusApi(); + const { addIntegrationLink, docsLink } = useCloudDefendIntegrationLinks(); + + const render = () => { + if (subscriptionStatus.isError) { + return defaultErrorRenderer(subscriptionStatus.error); + } + + if (subscriptionStatus.isLoading) { + return defaultLoadingRenderer(); + } + + if (!subscriptionStatus.data) { + return subscriptionNotAllowedRenderer(); + } + + if (getSetupStatus.isError) { + return defaultErrorRenderer(getSetupStatus.error); + } + + if (getSetupStatus.isLoading) { + return defaultLoadingRenderer(); + } + + if (getSetupStatus.data.status === 'not-installed') { + return packageNotInstalledRenderer({ addIntegrationLink, docsLink }); + } + + if (!query) { + return children; + } + + if (query.isError) { + return errorRender(query.error); + } + + if (query.isLoading) { + return loadingRender(); + } + + if (!query.data) { + return noDataRenderer(docsLink); + } + + return children; + }; + + return <>{render()}; +}; diff --git a/x-pack/plugins/cloud_defend/public/components/cloud_defend_page_title/index.tsx b/x-pack/plugins/cloud_defend/public/components/cloud_defend_page_title/index.tsx new file mode 100644 index 0000000000000..43422ff2db1e6 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/cloud_defend_page_title/index.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; + +export const CloudDefendPageTitle = ({ title }: { title: string }) => ( + + + +

    {title}

    +
    +
    +
    +); diff --git a/x-pack/plugins/cloud_defend/public/components/full_size_page/index.tsx b/x-pack/plugins/cloud_defend/public/components/full_size_page/index.tsx new file mode 100644 index 0000000000000..4e68797c8c21f --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/full_size_page/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 { EuiFlexGroup, type CommonProps } from '@elastic/eui'; +import { css } from '@emotion/react'; +import React from 'react'; + +// Keep this component lean as it is part of the main app bundle +export const FullSizeCenteredPage = ({ + children, + ...rest +}: { children: React.ReactNode } & CommonProps) => ( + + {children} + +); diff --git a/x-pack/plugins/cloud_defend/public/components/loading_state/index.tsx b/x-pack/plugins/cloud_defend/public/components/loading_state/index.tsx new file mode 100644 index 0000000000000..608eabf0e30a8 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/loading_state/index.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiLoadingSpinner, EuiSpacer } from '@elastic/eui'; +import React from 'react'; +import { FullSizeCenteredPage } from '../full_size_page'; + +// Keep this component lean as it is part of the main app bundle +export const LoadingState: React.FunctionComponent<{ ['data-test-subj']?: string }> = ({ + children, + ...rest +}) => { + return ( + + + + {children} + + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/components/policies_table/index.test.tsx b/x-pack/plugins/cloud_defend/public/components/policies_table/index.test.tsx new file mode 100644 index 0000000000000..e473fd9f990b1 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/policies_table/index.test.tsx @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import Chance from 'chance'; +import { render, screen } from '@testing-library/react'; +import moment from 'moment'; +import { createCloudDefendIntegrationFixture } from '../../test/fixtures/cloud_defend_integration'; +import { PoliciesTable } from '.'; +import { TestProvider } from '../../test/test_provider'; + +describe('', () => { + const chance = new Chance(); + + const tableProps = { + pageIndex: 1, + pageSize: 10, + error: undefined, + loading: false, + setQuery: jest.fn(), + }; + + it('renders integration name', () => { + const item = createCloudDefendIntegrationFixture(); + const policies = [item]; + + render( + + + + ); + + expect(screen.getByText(item.package_policy.name)).toBeInTheDocument(); + }); + + it('renders agent policy name', () => { + const agentPolicy = { + id: chance.guid(), + name: chance.sentence(), + agents: chance.integer({ min: 1 }), + }; + + const policies = [createCloudDefendIntegrationFixture({ agent_policy: agentPolicy })]; + + render( + + + + ); + + expect(screen.getByText(agentPolicy.name)).toBeInTheDocument(); + }); + + it('renders number of agents', () => { + const item = createCloudDefendIntegrationFixture(); + const policies = [item]; + + render( + + + + ); + + // TODO too loose + expect(screen.getByText(item.agent_policy.agents as number)).toBeInTheDocument(); + }); + + it('renders created by', () => { + const item = createCloudDefendIntegrationFixture(); + const policies = [item]; + + render( + + + + ); + + expect(screen.getByText(item.package_policy.created_by)).toBeInTheDocument(); + }); + + it('renders created at', () => { + const item = createCloudDefendIntegrationFixture(); + const policies = [item]; + + render( + + + + ); + + expect(screen.getByText(moment(item.package_policy.created_at).fromNow())).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/cloud_defend/public/components/policies_table/index.tsx b/x-pack/plugins/cloud_defend/public/components/policies_table/index.tsx new file mode 100644 index 0000000000000..bb4134b083d9f --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/policies_table/index.tsx @@ -0,0 +1,157 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiBasicTable, + type EuiBasicTableColumn, + type EuiBasicTableProps, + type Pagination, + type CriteriaWithPagination, + EuiLink, +} from '@elastic/eui'; +import React from 'react'; +import { pagePathGetters } from '@kbn/fleet-plugin/public'; +import { i18n } from '@kbn/i18n'; +import { TimestampTableCell } from '../timestamp_table_cell'; +import type { CloudDefendPolicy } from '../../../common/types'; +import { useKibana } from '../../common/hooks/use_kibana'; +import * as TEST_SUBJ from '../../pages/policies/test_subjects'; + +interface PoliciesTableProps + extends Pick< + EuiBasicTableProps, + 'loading' | 'error' | 'noItemsMessage' | 'sorting' + >, + Pagination { + policies: CloudDefendPolicy[]; + setQuery(pagination: CriteriaWithPagination): void; + 'data-test-subj'?: string; +} + +const AgentPolicyButtonLink = ({ name, id: policyId }: { name: string; id: string }) => { + const { http } = useKibana().services; + const [fleetBase, path] = pagePathGetters.policy_details({ policyId }); + + return {name}; +}; + +const IntegrationButtonLink = ({ + packageName, + policyId, + packagePolicyId, +}: { + packageName: string; + packagePolicyId: string; + policyId: string; +}) => { + const editIntegrationLink = pagePathGetters + .edit_integration({ + packagePolicyId, + policyId, + }) + .join(''); + + return {packageName}; +}; + +const POLICIES_TABLE_COLUMNS: Array> = [ + { + field: 'package_policy.name', + name: i18n.translate('xpack.cloudDefend.policies.policiesTable.integrationNameColumnTitle', { + defaultMessage: 'Integration Name', + }), + render: (packageName, policy) => ( + + ), + truncateText: true, + sortable: true, + 'data-test-subj': TEST_SUBJ.POLICIES_TABLE_COLUMNS.INTEGRATION_NAME, + }, + { + field: 'agent_policy.name', + name: i18n.translate('xpack.cloudDefend.policies.policiesTable.agentPolicyColumnTitle', { + defaultMessage: 'Agent Policy', + }), + render: (name, policy) => , + truncateText: true, + 'data-test-subj': TEST_SUBJ.POLICIES_TABLE_COLUMNS.AGENT_POLICY, + }, + { + field: 'agent_policy.agents', + name: i18n.translate('xpack.cloudDefend.policies.policiesTable.numberOfAgentsColumnTitle', { + defaultMessage: 'Number of Agents', + }), + truncateText: true, + 'data-test-subj': TEST_SUBJ.POLICIES_TABLE_COLUMNS.NUMBER_OF_AGENTS, + }, + { + field: 'package_policy.created_by', + name: i18n.translate('xpack.cloudDefend.policies.policiesTable.createdByColumnTitle', { + defaultMessage: 'Created by', + }), + dataType: 'string', + truncateText: true, + sortable: true, + 'data-test-subj': TEST_SUBJ.POLICIES_TABLE_COLUMNS.CREATED_BY, + }, + { + field: 'package_policy.created_at', + name: i18n.translate('xpack.cloudDefend.policies.policiesTable.createdAtColumnTitle', { + defaultMessage: 'Created at', + }), + dataType: 'date', + truncateText: true, + render: (timestamp: CloudDefendPolicy['package_policy']['created_at']) => ( + + ), + sortable: true, + 'data-test-subj': TEST_SUBJ.POLICIES_TABLE_COLUMNS.CREATED_AT, + }, +]; + +export const PoliciesTable = ({ + policies, + pageIndex, + pageSize, + totalItemCount, + loading, + error, + setQuery, + noItemsMessage, + sorting, + ...rest +}: PoliciesTableProps) => { + const pagination: Pagination = { + pageIndex: Math.max(pageIndex - 1, 0), + pageSize, + totalItemCount, + }; + + const onChange = ({ page, sort }: CriteriaWithPagination) => { + setQuery({ page: { ...page, index: page.index + 1 }, sort }); + }; + + return ( + [item.agent_policy.id, item.package_policy.id].join('/')} + pagination={pagination} + onChange={onChange} + tableLayout="fixed" + loading={loading} + noItemsMessage={noItemsMessage} + error={error} + sorting={sorting} + /> + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/components/subscription_not_allowed/index.tsx b/x-pack/plugins/cloud_defend/public/components/subscription_not_allowed/index.tsx new file mode 100644 index 0000000000000..7ab4afa3fb06e --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/subscription_not_allowed/index.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiEmptyPrompt, EuiPageSection, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { useKibana } from '../../common/hooks/use_kibana'; + +export const SubscriptionNotAllowed = () => { + const { application } = useKibana().services; + return ( + + + + + } + body={ +

    + + + + ), + }} + /> +

    + } + /> +
    + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/components/timestamp_table_cell/index.tsx b/x-pack/plugins/cloud_defend/public/components/timestamp_table_cell/index.tsx new file mode 100644 index 0000000000000..b6b6934b92cde --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/components/timestamp_table_cell/index.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import moment, { type MomentInput } from 'moment'; +import { EuiToolTip, formatDate } from '@elastic/eui'; +import { useUiSetting } from '@kbn/kibana-react-plugin/public'; + +const DEFAULT_DATE_FORMAT = 'dateFormat'; + +export const TimestampTableCell = ({ timestamp }: { timestamp: MomentInput }) => { + const dateFormat = useUiSetting(DEFAULT_DATE_FORMAT); + const formatted = formatDate(timestamp, dateFormat); + + return ( + + {moment(timestamp).fromNow()} + + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/index.ts b/x-pack/plugins/cloud_defend/public/index.ts index fd8099aa2ed11..b74c04111c91b 100755 --- a/x-pack/plugins/cloud_defend/public/index.ts +++ b/x-pack/plugins/cloud_defend/public/index.ts @@ -6,6 +6,14 @@ */ import { CloudDefendPlugin } from './plugin'; +export type { CloudDefendSecuritySolutionContext } from './types'; +export { + getSecuritySolutionLink, + getSecuritySolutionNavTab, +} from './common/navigation/security_solution_links'; +export { CLOUD_DEFEND_BASE_PATH } from './common/navigation/constants'; +export type { CloudDefendPageId } from './common/navigation/types'; + // This exports static code and TypeScript types, // as well as, Kibana Platform `plugin()` initializer. export function plugin() { diff --git a/x-pack/plugins/cloud_defend/public/pages/index.ts b/x-pack/plugins/cloud_defend/public/pages/index.ts new file mode 100644 index 0000000000000..ec35f87e70811 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/pages/index.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 { Policies } from './policies'; diff --git a/x-pack/plugins/cloud_defend/public/pages/policies/index.test.tsx b/x-pack/plugins/cloud_defend/public/pages/policies/index.test.tsx new file mode 100644 index 0000000000000..61fcf6f0a844a --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/pages/policies/index.test.tsx @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 Chance from 'chance'; +import { render, screen } from '@testing-library/react'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { createCloudDefendIntegrationFixture } from '../../test/fixtures/cloud_defend_integration'; +import { createReactQueryResponse } from '../../test/fixtures/react_query'; +import { TestProvider } from '../../test/test_provider'; +import { Policies } from '.'; +import * as TEST_SUBJ from './test_subjects'; +import { useCloudDefendPolicies } from './use_cloud_defend_policies'; +import { useCloudDefendSetupStatusApi } from '../../common/api/use_setup_status_api'; +import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; +import { useCloudDefendIntegrationLinks } from '../../common/navigation/use_cloud_defend_integration_links'; + +jest.mock('./use_cloud_defend_policies'); +jest.mock('../../common/api/use_setup_status_api'); +jest.mock('../../common/hooks/use_subscription_status'); +jest.mock('../../common/navigation/use_cloud_defend_integration_links'); + +const chance = new Chance(); + +describe('', () => { + beforeEach(() => { + jest.resetAllMocks(); + (useCloudDefendSetupStatusApi as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: { status: 'indexed' }, + }) + ); + + (useSubscriptionStatus as jest.Mock).mockImplementation(() => + createReactQueryResponse({ + status: 'success', + data: true, + }) + ); + + (useCloudDefendIntegrationLinks as jest.Mock).mockImplementation(() => ({ + addIntegrationLink: chance.url(), + docsLink: chance.url(), + })); + }); + + const renderPolicies = (queryResponse: Partial = createReactQueryResponse()) => { + (useCloudDefendPolicies as jest.Mock).mockImplementation(() => queryResponse); + + return render( + + + + ); + }; + + it('renders the page header', () => { + renderPolicies(); + + expect(screen.getByTestId(TEST_SUBJ.POLICIES_PAGE_HEADER)).toBeInTheDocument(); + }); + + it('renders the "add integration" button', () => { + renderPolicies(); + + expect(screen.getByTestId(TEST_SUBJ.ADD_INTEGRATION_TEST_SUBJ)).toBeInTheDocument(); + }); + + it('renders error state while there is an error', () => { + const error = new Error('message'); + renderPolicies(createReactQueryResponse({ status: 'error', error })); + + expect(screen.getByText(error.message)).toBeInTheDocument(); + }); + + it('renders the benchmarks table', () => { + renderPolicies( + createReactQueryResponse({ + status: 'success', + data: { total: 1, items: [createCloudDefendIntegrationFixture()] }, + }) + ); + + expect(screen.getByTestId(TEST_SUBJ.POLICIES_TABLE_DATA_TEST_SUBJ)).toBeInTheDocument(); + Object.values(TEST_SUBJ.POLICIES_TABLE_COLUMNS).forEach((testId) => + expect(screen.getAllByTestId(testId)[0]).toBeInTheDocument() + ); + }); +}); diff --git a/x-pack/plugins/cloud_defend/public/pages/policies/index.tsx b/x-pack/plugins/cloud_defend/public/pages/policies/index.tsx new file mode 100644 index 0000000000000..c732be5421a17 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/pages/policies/index.tsx @@ -0,0 +1,197 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, { useState } from 'react'; +import { + EuiButton, + EuiFieldSearch, + EuiFieldSearchProps, + EuiFlexGroup, + EuiFlexItem, + EuiPageHeader, + EuiSpacer, + EuiText, + EuiTextColor, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import useDebounce from 'react-use/lib/useDebounce'; +import { i18n } from '@kbn/i18n'; +import { CloudDefendPageTitle } from '../../components/cloud_defend_page_title'; +import { CloudDefendPage } from '../../components/cloud_defend_page'; +import { PoliciesTable } from '../../components/policies_table'; +import { useCloudDefendPolicies, UseCloudDefendPoliciesProps } from './use_cloud_defend_policies'; +import { extractErrorMessage } from '../../../common/utils/helpers'; +import * as TEST_SUBJ from './test_subjects'; +import { LOCAL_STORAGE_PAGE_SIZE } from '../../common/constants'; +import { usePageSize } from '../../common/hooks/use_page_size'; +import { useCloudDefendIntegrationLinks } from '../../common/navigation/use_cloud_defend_integration_links'; + +const SEARCH_DEBOUNCE_MS = 300; + +const AddIntegrationButton = () => { + const { addIntegrationLink } = useCloudDefendIntegrationLinks(); + + return ( + + + + ); +}; + +const EmptyState = ({ name }: { name: string }) => ( +
    + + { + + + + {name && ( + + )} + + + } + + + + + + + +
    +); + +const TotalIntegrationsCount = ({ + pageCount, + totalCount, +}: Record<'pageCount' | 'totalCount', number>) => ( + + + + + +); + +const SearchField = ({ + onSearch, + isLoading, +}: Required>) => { + const [localValue, setLocalValue] = useState(''); + + useDebounce(() => onSearch(localValue), SEARCH_DEBOUNCE_MS, [localValue]); + + return ( + + + + + + ); +}; + +export const Policies = () => { + const { pageSize, setPageSize } = usePageSize(LOCAL_STORAGE_PAGE_SIZE); + const [query, setQuery] = useState({ + name: '', + page: 1, + perPage: pageSize, + sortField: 'package_policy.name', + sortOrder: 'asc', + }); + + const queryResult = useCloudDefendPolicies(query); + const totalItemCount = queryResult.data?.total || 0; + + return ( + + + } + rightSideItems={[]} + bottomBorder + /> + + setQuery((current) => ({ ...current, name }))} + /> + + + + { + setPageSize(page.size); + setQuery((current) => ({ + ...current, + page: page.index, + perPage: page.size, + sortField: + (sort?.field as UseCloudDefendPoliciesProps['sortField']) || current.sortField, + sortOrder: sort?.direction || current.sortOrder, + })); + }} + noItemsMessage={ + queryResult.isSuccess && !queryResult.data.total ? ( + + ) : undefined + } + /> + + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/pages/policies/test_subjects.ts b/x-pack/plugins/cloud_defend/public/pages/policies/test_subjects.ts new file mode 100644 index 0000000000000..9709360512727 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/pages/policies/test_subjects.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. + */ + +export const POLICIES_PAGE_HEADER = 'policies-page-header'; +export const POLICIES_TABLE_DATA_TEST_SUBJ = 'cloud_defend_policies_table'; +export const ADD_INTEGRATION_TEST_SUBJ = 'cloud_defend_add_integration'; +export const POLICIES_TABLE_COLUMNS = { + INTEGRATION_NAME: 'policies-table-column-integration-name', + AGENT_POLICY: 'policies-table-column-agent-policy', + NUMBER_OF_AGENTS: 'policies-table-column-number-of-agents', + CREATED_BY: 'policies-table-column-created-by', + CREATED_AT: 'policies-table-column-created-at', +}; diff --git a/x-pack/plugins/cloud_defend/public/pages/policies/use_cloud_defend_policies.ts b/x-pack/plugins/cloud_defend/public/pages/policies/use_cloud_defend_policies.ts new file mode 100644 index 0000000000000..e0766026e12b8 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/pages/policies/use_cloud_defend_policies.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useQuery } from '@tanstack/react-query'; +import type { ListResult } from '@kbn/fleet-plugin/common'; +import { POLICIES_ROUTE_PATH } from '../../../common/constants'; +import type { PoliciesQueryParams } from '../../../common/schemas/policy'; +import { useKibana } from '../../common/hooks/use_kibana'; +import type { CloudDefendPolicy } from '../../../common/types'; + +const QUERY_KEY = 'cloud_defend_policies'; + +export interface UseCloudDefendPoliciesProps { + name: string; + page: number; + perPage: number; + sortField: PoliciesQueryParams['sort_field']; + sortOrder: PoliciesQueryParams['sort_order']; +} + +export const useCloudDefendPolicies = ({ + name, + perPage, + page, + sortField, + sortOrder, +}: UseCloudDefendPoliciesProps) => { + const { http } = useKibana().services; + const query: PoliciesQueryParams = { + policy_name: name, + per_page: perPage, + page, + sort_field: sortField, + sort_order: sortOrder, + }; + + return useQuery( + [QUERY_KEY, query], + () => http.get>(POLICIES_ROUTE_PATH, { query }), + { keepPreviousData: true } + ); +}; diff --git a/x-pack/plugins/cloud_defend/public/plugin.ts b/x-pack/plugins/cloud_defend/public/plugin.ts deleted file mode 100755 index 5bbb1215e2270..0000000000000 --- a/x-pack/plugins/cloud_defend/public/plugin.ts +++ /dev/null @@ -1,44 +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 { lazy } from 'react'; -import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; -import { - CloudDefendPluginSetup, - CloudDefendPluginStart, - CloudDefendPluginStartDeps, -} from './types'; -import { INTEGRATION_PACKAGE_NAME } from '../common/constants'; - -const LazyEditPolicy = lazy(() => import('./components/fleet_extensions/policy_extension_edit')); -const LazyCreatePolicy = lazy( - () => import('./components/fleet_extensions/policy_extension_create') -); - -export class CloudDefendPlugin implements Plugin { - public setup(core: CoreSetup): CloudDefendPluginSetup { - // Return methods that should be available to other plugins - return {}; - } - - public start(core: CoreStart, plugins: CloudDefendPluginStartDeps): CloudDefendPluginStart { - plugins.fleet.registerExtension({ - package: INTEGRATION_PACKAGE_NAME, - view: 'package-policy-create', - Component: LazyCreatePolicy, - }); - - plugins.fleet.registerExtension({ - package: INTEGRATION_PACKAGE_NAME, - view: 'package-policy-edit', - Component: LazyEditPolicy, - }); - - return {}; - } - - public stop() {} -} diff --git a/x-pack/plugins/cloud_defend/public/plugin.tsx b/x-pack/plugins/cloud_defend/public/plugin.tsx new file mode 100755 index 0000000000000..b9272993e6b55 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/plugin.tsx @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; +import React, { lazy, Suspense } from 'react'; +import type { CloudDefendRouterProps } from './application/router'; +import { + CloudDefendPluginSetup, + CloudDefendPluginStart, + CloudDefendPluginStartDeps, + CloudDefendPluginSetupDeps, +} from './types'; +import { INTEGRATION_PACKAGE_NAME } from '../common/constants'; +import { LoadingState } from './components/loading_state'; +import { SetupContext } from './application/setup_context'; + +const LazyEditPolicy = lazy(() => import('./components/fleet_extensions/policy_extension_edit')); +const LazyCreatePolicy = lazy( + () => import('./components/fleet_extensions/policy_extension_create') +); + +const RouterLazy = lazy(() => import('./application/router')); +const Router = (props: CloudDefendRouterProps) => ( + }> + + +); + +export class CloudDefendPlugin + implements + Plugin< + CloudDefendPluginSetup, + CloudDefendPluginStart, + CloudDefendPluginSetupDeps, + CloudDefendPluginStartDeps + > +{ + private isCloudEnabled?: boolean; + + public setup( + core: CoreSetup, + plugins: CloudDefendPluginSetupDeps + ): CloudDefendPluginSetup { + this.isCloudEnabled = plugins.cloud.isCloudEnabled; + + // Return methods that should be available to other plugins + return {}; + } + + public start(core: CoreStart, plugins: CloudDefendPluginStartDeps): CloudDefendPluginStart { + plugins.fleet.registerExtension({ + package: INTEGRATION_PACKAGE_NAME, + view: 'package-policy-create', + Component: LazyCreatePolicy, + }); + + plugins.fleet.registerExtension({ + package: INTEGRATION_PACKAGE_NAME, + view: 'package-policy-edit', + Component: LazyEditPolicy, + }); + + const CloudDefendRouter = (props: CloudDefendRouterProps) => ( + + +
    + + + +
    +
    +
    + ); + + return { + getCloudDefendRouter: () => CloudDefendRouter, + }; + } + + public stop() {} +} diff --git a/x-pack/plugins/cloud_defend/public/test/fixtures/cloud_defend_integration.ts b/x-pack/plugins/cloud_defend/public/test/fixtures/cloud_defend_integration.ts new file mode 100644 index 0000000000000..830977947673c --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/test/fixtures/cloud_defend_integration.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* eslint-disable @typescript-eslint/naming-convention */ + +import Chance from 'chance'; +import type { CloudDefendPolicy } from '../../../common/types'; + +type CreateCloudDefendIntegrationFixtureInput = { + chance?: Chance.Chance; +} & Partial; + +export const createCloudDefendIntegrationFixture = ({ + chance = new Chance(), + package_policy = { + revision: chance?.integer(), + enabled: true, + id: chance.guid(), + name: chance.string(), + policy_id: chance.guid(), + namespace: chance.string(), + updated_at: chance.date().toISOString(), + updated_by: chance.word(), + created_at: chance.date().toISOString(), + created_by: chance.word(), + inputs: [ + { + type: 'cloud_defend/control', + policy_template: 'cloud_defend', + enabled: true, + streams: [ + { + id: chance?.guid(), + enabled: true, + data_stream: { + type: 'logs', + dataset: 'cloud_defend.alerts', + }, + }, + ], + }, + ], + package: { + name: chance.string(), + title: chance.string(), + version: chance.string(), + }, + }, + agent_policy = { + id: chance.guid(), + name: chance.sentence(), + agents: chance.integer({ min: 0 }), + }, +}: CreateCloudDefendIntegrationFixtureInput = {}): CloudDefendPolicy => ({ + package_policy, + agent_policy, +}); diff --git a/x-pack/plugins/cloud_defend/public/test/fixtures/navigation_item.ts b/x-pack/plugins/cloud_defend/public/test/fixtures/navigation_item.ts new file mode 100644 index 0000000000000..74fdbce35f95b --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/test/fixtures/navigation_item.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import Chance from 'chance'; +import type { CloudDefendPageNavigationItem } from '../../common/navigation/types'; + +type CreateNavigationItemFixtureInput = { + chance?: Chance.Chance; +} & Partial; +export const createPageNavigationItemFixture = ({ + chance = new Chance(), + name = chance.word(), + path = `/${chance.word()}`, + disabled = undefined, + id = 'cloud_defend-policies', +}: CreateNavigationItemFixtureInput = {}): CloudDefendPageNavigationItem => ({ + name, + path, + disabled, + id, +}); diff --git a/x-pack/plugins/cloud_defend/public/test/fixtures/react_query.ts b/x-pack/plugins/cloud_defend/public/test/fixtures/react_query.ts new file mode 100644 index 0000000000000..9605515618882 --- /dev/null +++ b/x-pack/plugins/cloud_defend/public/test/fixtures/react_query.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { UseQueryResult } from '@tanstack/react-query'; + +interface CreateReactQueryResponseInput { + status?: UseQueryResult['status'] | 'idle'; + data?: TData; + error?: TError; +} + +// TODO: Consider alternatives to using `Partial` over `UseQueryResult` for the return type: +// 1. Fully mock `UseQueryResult` +// 2. Mock the network layer instead of `useQuery` - see: https://tkdodo.eu/blog/testing-react-query +export const createReactQueryResponse = ({ + status = 'loading', + error = undefined, + data = undefined, +}: CreateReactQueryResponseInput = {}): Partial> => { + if (status === 'success') { + return { status, data, isSuccess: true, isLoading: false, isError: false }; + } + + if (status === 'error') { + return { status, error, isSuccess: false, isLoading: false, isError: true }; + } + + if (status === 'loading') { + return { status, data: undefined, isSuccess: false, isLoading: true, isError: false }; + } + + if (status === 'idle') { + return { + status: 'loading', + data: undefined, + isSuccess: false, + isLoading: true, + isError: false, + fetchStatus: 'idle', + }; + } + + return { status }; +}; diff --git a/x-pack/plugins/cloud_defend/public/test/mocks.ts b/x-pack/plugins/cloud_defend/public/test/mocks.ts index 7dcf8d99d9116..4921d3f6d0f98 100644 --- a/x-pack/plugins/cloud_defend/public/test/mocks.ts +++ b/x-pack/plugins/cloud_defend/public/test/mocks.ts @@ -71,8 +71,8 @@ export const getCloudDefendNewPolicyMock = (yaml = MOCK_YAML_CONFIGURATION): New ], package: { name: 'cloud_defend', - title: 'Kubernetes Security Posture Management', - version: '0.0.21', + title: 'Container drift prevention', + version: '1.0.0', }, }); @@ -114,7 +114,7 @@ export const getCloudDefendPolicyMock = (yaml = MOCK_YAML_CONFIGURATION): Packag ], package: { name: 'cloud_defend', - title: 'Kubernetes Security Posture Management', - version: '0.0.21', + title: 'Container drift prevention', + version: '1.0.0', }, }); diff --git a/x-pack/plugins/cloud_defend/public/test/test_provider.tsx b/x-pack/plugins/cloud_defend/public/test/test_provider.tsx index 472f0ea04ecd1..c5deff816241c 100755 --- a/x-pack/plugins/cloud_defend/public/test/test_provider.tsx +++ b/x-pack/plugins/cloud_defend/public/test/test_provider.tsx @@ -37,13 +37,13 @@ Object.defineProperty(window, 'matchMedia', { })), }); -interface CspAppDeps { +interface CloudDefendAppDeps { core: CoreStart; deps: CloudDefendPluginStartDeps; params: AppMountParameters; } -export const TestProvider: React.FC> = ({ +export const TestProvider: React.FC> = ({ core = coreMock.createStart(), deps = { data: dataPluginMock.createStartContract(), diff --git a/x-pack/plugins/cloud_defend/public/types.ts b/x-pack/plugins/cloud_defend/public/types.ts index 801f5ee67891e..3b242b9fc2add 100755 --- a/x-pack/plugins/cloud_defend/public/types.ts +++ b/x-pack/plugins/cloud_defend/public/types.ts @@ -4,22 +4,53 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { CloudSetup } from '@kbn/cloud-plugin/public'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import type { FleetSetup, FleetStart } from '@kbn/fleet-plugin/public'; import { NewPackagePolicy } from '@kbn/fleet-plugin/public'; +import type { ComponentType, ReactNode } from 'react'; +import type { + UsageCollectionSetup, + UsageCollectionStart, +} from '@kbn/usage-collection-plugin/public'; +import type { CloudDefendRouterProps } from './application/router'; +import type { CloudDefendPageId } from './common/navigation/types'; + +/** + * cloud_defend plugin types + */ // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface CloudDefendPluginSetup {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface CloudDefendPluginStart {} +export interface CloudDefendPluginStart { + /** Gets the cloud defend router component for embedding in the security solution. */ + getCloudDefendRouter(): ComponentType; +} export interface CloudDefendPluginSetupDeps { fleet: FleetSetup; + cloud: CloudSetup; + usageCollection?: UsageCollectionSetup; } export interface CloudDefendPluginStartDeps { fleet: FleetStart; + licensing: LicensingPluginStart; + usageCollection?: UsageCollectionStart; } +export interface CloudDefendSecuritySolutionContext { + /** Gets the `FiltersGlobal` component for embedding a filter bar in the security solution application. */ + getFiltersGlobalComponent: () => ComponentType<{ children: ReactNode }>; + /** Gets the `SpyRoute` component for navigation highlighting and breadcrumbs. */ + getSpyRouteComponent: () => ComponentType<{ + pageName: CloudDefendPageId; + state?: Record; + }>; +} + +/** + * cloud_defend/control types + */ export enum ControlResponseAction { alert = 'alert', block = 'block', diff --git a/x-pack/plugins/cloud_defend/server/index.ts b/x-pack/plugins/cloud_defend/server/index.ts new file mode 100644 index 0000000000000..2cb2e1c2b55e5 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PluginInitializerContext } from '@kbn/core/server'; +import { CloudDefendPlugin } from './plugin'; + +// This exports static code and TypeScript types, +// as well as, Kibana Platform `plugin()` initializer. + +export function plugin(initializerContext: PluginInitializerContext) { + return new CloudDefendPlugin(initializerContext); +} + +export type { CloudDefendPluginSetup, CloudDefendPluginStart } from './types'; diff --git a/x-pack/plugins/cloud_defend/server/lib/check_index_status.ts b/x-pack/plugins/cloud_defend/server/lib/check_index_status.ts new file mode 100644 index 0000000000000..984c68a76a6b6 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/lib/check_index_status.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient, type Logger } from '@kbn/core/server'; +import { IndexStatus } from '../../common/types'; + +export const checkIndexStatus = async ( + esClient: ElasticsearchClient, + index: string, + logger: Logger +): Promise => { + try { + const queryResult = await esClient.search({ + index, + query: { + match_all: {}, + }, + size: 1, + }); + + return queryResult.hits.hits.length ? 'not-empty' : 'empty'; + } catch (e) { + logger.debug(e); + if (e?.meta?.body?.error?.type === 'security_exception') { + return 'unprivileged'; + } + + // Assuming index doesn't exist + return 'empty'; + } +}; diff --git a/x-pack/plugins/cloud_defend/server/lib/fleet_util.ts b/x-pack/plugins/cloud_defend/server/lib/fleet_util.ts new file mode 100644 index 0000000000000..ae9866b4f03ca --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/lib/fleet_util.ts @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { map, uniq } from 'lodash'; +import type { SavedObjectsClientContract, Logger } from '@kbn/core/server'; +import type { + AgentPolicyServiceInterface, + AgentService, + PackagePolicyClient, +} from '@kbn/fleet-plugin/server'; +import type { + AgentPolicy, + GetAgentStatusResponse, + ListResult, + PackagePolicy, +} from '@kbn/fleet-plugin/common'; +import { errors } from '@elastic/elasticsearch'; +import { INPUT_CONTROL, CLOUD_DEFEND_FLEET_PACKAGE_KUERY } from '../../common/constants'; +import { POLICIES_PACKAGE_POLICY_PREFIX, PoliciesQueryParams } from '../../common/schemas/policy'; + +export const PACKAGE_POLICY_SAVED_OBJECT_TYPE = 'ingest-package-policies'; + +const isFleetMissingAgentHttpError = (error: unknown) => + error instanceof errors.ResponseError && error.statusCode === 404; + +const isPolicyTemplate = (input: any) => input === INPUT_CONTROL; + +const getPackageNameQuery = (packageName: string, benchmarkFilter?: string): string => { + const integrationNameQuery = `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:${packageName}`; + const kquery = benchmarkFilter + ? `${integrationNameQuery} AND ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: *${benchmarkFilter}*` + : integrationNameQuery; + + return kquery; +}; + +export type AgentStatusByAgentPolicyMap = Record; + +export const getAgentStatusesByAgentPolicies = async ( + agentService: AgentService, + agentPolicies: AgentPolicy[] | undefined, + logger: Logger +): Promise => { + if (!agentPolicies?.length) return {}; + + const internalAgentService = agentService.asInternalUser; + const result: AgentStatusByAgentPolicyMap = {}; + + try { + for (const agentPolicy of agentPolicies) { + result[agentPolicy.id] = await internalAgentService.getAgentStatusForAgentPolicy( + agentPolicy.id + ); + } + } catch (error) { + if (isFleetMissingAgentHttpError(error)) { + logger.debug('failed to get agent status for agent policy'); + } else { + throw error; + } + } + + return result; +}; + +export const getCloudDefendAgentPolicies = async ( + soClient: SavedObjectsClientContract, + packagePolicies: PackagePolicy[], + agentPolicyService: AgentPolicyServiceInterface +): Promise => + agentPolicyService.getByIds(soClient, uniq(map(packagePolicies, 'policy_id')), { + withPackagePolicies: true, + ignoreMissing: true, + }); + +export const getCloudDefendPackagePolicies = ( + soClient: SavedObjectsClientContract, + packagePolicyService: PackagePolicyClient, + packageName: string, + queryParams: Partial +): Promise> => { + const sortField = queryParams.sort_field?.replaceAll(POLICIES_PACKAGE_POLICY_PREFIX, ''); + + return packagePolicyService.list(soClient, { + kuery: getPackageNameQuery(packageName, queryParams.policy_name), + page: queryParams.page, + perPage: queryParams.per_page, + sortField, + sortOrder: queryParams.sort_order, + }); +}; + +export const getInstalledPolicyTemplates = async ( + packagePolicyClient: PackagePolicyClient, + soClient: SavedObjectsClientContract +) => { + try { + // getting all installed cloud_defend package policies + const queryResult = await packagePolicyClient.list(soClient, { + kuery: CLOUD_DEFEND_FLEET_PACKAGE_KUERY, + perPage: 1000, + }); + + // getting installed policy templates + const enabledPolicyTemplates = queryResult.items + .map((policy) => { + return policy.inputs.find((input) => input.enabled)?.policy_template; + }) + .filter(isPolicyTemplate); + + // removing duplicates + return [...new Set(enabledPolicyTemplates)]; + } catch (e) { + return []; + } +}; diff --git a/x-pack/plugins/cloud_defend/server/mocks.ts b/x-pack/plugins/cloud_defend/server/mocks.ts new file mode 100644 index 0000000000000..a3a1fb895e3c8 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/mocks.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; +import { coreMock } from '@kbn/core/server/mocks'; +import { + createFleetRequestHandlerContextMock, + createMockAgentService, + createMockAgentPolicyService, + createPackagePolicyServiceMock, + createMockPackageService, +} from '@kbn/fleet-plugin/server/mocks'; +import { mockAuthenticatedUser } from '@kbn/security-plugin/common/model/authenticated_user.mock'; + +export const createCloudDefendRequestHandlerContextMock = () => { + const coreMockRequestContext = coreMock.createRequestHandlerContext(); + + return { + core: coreMockRequestContext, + fleet: createFleetRequestHandlerContextMock(), + cloudDefend: { + user: mockAuthenticatedUser(), + logger: loggingSystemMock.createLogger(), + esClient: coreMockRequestContext.elasticsearch.client, + soClient: coreMockRequestContext.savedObjects.client, + agentPolicyService: createMockAgentPolicyService(), + agentService: createMockAgentService(), + packagePolicyService: createPackagePolicyServiceMock(), + packageService: createMockPackageService(), + }, + }; +}; diff --git a/x-pack/plugins/cloud_defend/server/plugin.ts b/x-pack/plugins/cloud_defend/server/plugin.ts new file mode 100644 index 0000000000000..05926e82cf796 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/plugin.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 { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from '@kbn/core/server'; +import type { NewPackagePolicy } from '@kbn/fleet-plugin/common'; +import { + CloudDefendPluginSetup, + CloudDefendPluginStart, + CloudDefendPluginStartDeps, + CloudDefendPluginSetupDeps, +} from './types'; +import { setupRoutes } from './routes/setup_routes'; +import { isCloudDefendPackage } from '../common/utils/helpers'; +import { isSubscriptionAllowed } from '../common/utils/subscription'; + +export class CloudDefendPlugin implements Plugin { + private readonly logger: Logger; + private isCloudEnabled?: boolean; + + constructor(initializerContext: PluginInitializerContext) { + this.logger = initializerContext.logger.get(); + } + + public setup( + core: CoreSetup, + plugins: CloudDefendPluginSetupDeps + ) { + this.logger.debug('cloudDefend: Setup'); + + setupRoutes({ + core, + logger: this.logger, + }); + + this.isCloudEnabled = plugins.cloud.isCloudEnabled; + + return {}; + } + + public start(core: CoreStart, plugins: CloudDefendPluginStartDeps): CloudDefendPluginStart { + this.logger.debug('cloudDefend: Started'); + + plugins.fleet.fleetSetupCompleted().then(async () => { + plugins.fleet.registerExternalCallback( + 'packagePolicyCreate', + async (packagePolicy: NewPackagePolicy): Promise => { + const license = await plugins.licensing.refresh(); + if (isCloudDefendPackage(packagePolicy.package?.name)) { + if (!isSubscriptionAllowed(this.isCloudEnabled, license)) { + throw new Error( + 'To use this feature you must upgrade your subscription or start a trial' + ); + } + } + + return packagePolicy; + } + ); + }); + + return {}; + } + + public stop() {} +} diff --git a/x-pack/plugins/cloud_defend/server/routes/policies/policies.test.ts b/x-pack/plugins/cloud_defend/server/routes/policies/policies.test.ts new file mode 100644 index 0000000000000..51dbabe1d936f --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/routes/policies/policies.test.ts @@ -0,0 +1,261 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { httpServerMock, httpServiceMock, savedObjectsClientMock } from '@kbn/core/server/mocks'; +import { + policiesQueryParamsSchema, + DEFAULT_POLICIES_PER_PAGE, +} from '../../../common/schemas/policy'; +import { + PACKAGE_POLICY_SAVED_OBJECT_TYPE, + getCloudDefendPackagePolicies, + getCloudDefendAgentPolicies, +} from '../../lib/fleet_util'; +import { defineGetPoliciesRoute } from './policies'; + +import { SavedObjectsClientContract } from '@kbn/core/server'; +import { + createMockAgentPolicyService, + createPackagePolicyServiceMock, +} from '@kbn/fleet-plugin/server/mocks'; +import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; +import { createCloudDefendRequestHandlerContextMock } from '../../mocks'; + +describe('policies API', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('validate the API route path', async () => { + const router = httpServiceMock.createRouter(); + + defineGetPoliciesRoute(router); + + const [config] = router.get.mock.calls[0]; + + expect(config.path).toEqual('/internal/cloud_defend/policies'); + }); + + it('should accept to a user with fleet.all privilege', async () => { + const router = httpServiceMock.createRouter(); + + defineGetPoliciesRoute(router); + + const [_, handler] = router.get.mock.calls[0]; + + const mockContext = createCloudDefendRequestHandlerContextMock(); + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + const [context, req, res] = [mockContext, mockRequest, mockResponse]; + + await handler(context, req, res); + + expect(res.forbidden).toHaveBeenCalledTimes(0); + }); + + it('should reject to a user without fleet.all privilege', async () => { + const router = httpServiceMock.createRouter(); + + defineGetPoliciesRoute(router); + + const [_, handler] = router.get.mock.calls[0]; + + const mockContext = createCloudDefendRequestHandlerContextMock(); + mockContext.fleet.authz.fleet.all = false; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + const [context, req, res] = [mockContext, mockRequest, mockResponse]; + + await handler(context, req, res); + + expect(res.forbidden).toHaveBeenCalledTimes(1); + }); + + describe('test input schema', () => { + it('expect to find default values', async () => { + const validatedQuery = policiesQueryParamsSchema.validate({}); + + expect(validatedQuery).toMatchObject({ + page: 1, + per_page: DEFAULT_POLICIES_PER_PAGE, + }); + }); + + it('expect to find policy_name', async () => { + const validatedQuery = policiesQueryParamsSchema.validate({ + policy_name: 'my_cis_policy', + }); + + expect(validatedQuery).toMatchObject({ + page: 1, + per_page: DEFAULT_POLICIES_PER_PAGE, + policy_name: 'my_cis_policy', + }); + }); + + it('should throw when page field is not a positive integer', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ page: -2 }); + }).toThrow(); + }); + + it('should throw when per_page field is not a positive integer', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ per_page: -2 }); + }).toThrow(); + }); + }); + + it('should throw when sort_field is not string', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ sort_field: true }); + }).toThrow(); + }); + + it('should not throw when sort_field is a string', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ sort_field: 'package_policy.name' }); + }).not.toThrow(); + }); + + it('should throw when sort_order is not `asc` or `desc`', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ sort_order: 'Other Direction' }); + }).toThrow(); + }); + + it('should not throw when `asc` is input for sort_order field', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ sort_order: 'asc' }); + }).not.toThrow(); + }); + + it('should not throw when `desc` is input for sort_order field', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ sort_order: 'desc' }); + }).not.toThrow(); + }); + + it('should not throw when fields is a known string literal', async () => { + expect(() => { + policiesQueryParamsSchema.validate({ sort_field: 'package_policy.name' }); + }).not.toThrow(); + }); + + describe('test policies utils', () => { + let mockSoClient: jest.Mocked; + + beforeEach(() => { + mockSoClient = savedObjectsClientMock.create(); + }); + + describe('test getPackagePolicies', () => { + it('should format request by package name', async () => { + const mockPackagePolicyService = createPackagePolicyServiceMock(); + + await getCloudDefendPackagePolicies(mockSoClient, mockPackagePolicyService, 'myPackage', { + page: 1, + per_page: 100, + sort_order: 'desc', + }); + + expect(mockPackagePolicyService.list.mock.calls[0][1]).toMatchObject( + expect.objectContaining({ + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:myPackage`, + page: 1, + perPage: 100, + }) + ); + }); + + it('should build sort request by `sort_field` and default `sort_order`', async () => { + const mockAgentPolicyService = createPackagePolicyServiceMock(); + + await getCloudDefendPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { + page: 1, + per_page: 100, + sort_field: 'package_policy.name', + sort_order: 'desc', + }); + + expect(mockAgentPolicyService.list.mock.calls[0][1]).toMatchObject( + expect.objectContaining({ + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:myPackage`, + page: 1, + perPage: 100, + sortField: 'name', + sortOrder: 'desc', + }) + ); + }); + + it('should build sort request by `sort_field` and asc `sort_order`', async () => { + const mockAgentPolicyService = createPackagePolicyServiceMock(); + + await getCloudDefendPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { + page: 1, + per_page: 100, + sort_field: 'package_policy.name', + sort_order: 'asc', + }); + + expect(mockAgentPolicyService.list.mock.calls[0][1]).toMatchObject( + expect.objectContaining({ + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:myPackage`, + page: 1, + perPage: 100, + sortField: 'name', + sortOrder: 'asc', + }) + ); + }); + }); + + it('should format request by policy_name', async () => { + const mockAgentPolicyService = createPackagePolicyServiceMock(); + + await getCloudDefendPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { + page: 1, + per_page: 100, + sort_order: 'desc', + policy_name: 'cloud_defend_1', + }); + + expect(mockAgentPolicyService.list.mock.calls[0][1]).toMatchObject( + expect.objectContaining({ + kuery: `${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.package.name:myPackage AND ${PACKAGE_POLICY_SAVED_OBJECT_TYPE}.name: *cloud_defend_1*`, + page: 1, + perPage: 100, + }) + ); + }); + + describe('test getAgentPolicies', () => { + it('should return one agent policy id when there is duplication', async () => { + const agentPolicyService = createMockAgentPolicyService(); + const packagePolicies = [createPackagePolicyMock(), createPackagePolicyMock()]; + + await getCloudDefendAgentPolicies(mockSoClient, packagePolicies, agentPolicyService); + + expect(agentPolicyService.getByIds.mock.calls[0][1]).toHaveLength(1); + }); + + it('should return full policy ids list when there is no id duplication', async () => { + const agentPolicyService = createMockAgentPolicyService(); + + const packagePolicy1 = createPackagePolicyMock(); + const packagePolicy2 = createPackagePolicyMock(); + packagePolicy2.policy_id = 'AnotherId'; + const packagePolicies = [packagePolicy1, packagePolicy2]; + + await getCloudDefendAgentPolicies(mockSoClient, packagePolicies, agentPolicyService); + + expect(agentPolicyService.getByIds.mock.calls[0][1]).toHaveLength(2); + }); + }); + }); +}); diff --git a/x-pack/plugins/cloud_defend/server/routes/policies/policies.ts b/x-pack/plugins/cloud_defend/server/routes/policies/policies.ts new file mode 100644 index 0000000000000..a0dd3827ff618 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/routes/policies/policies.ts @@ -0,0 +1,115 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { transformError } from '@kbn/securitysolution-es-utils'; +import type { AgentPolicy, PackagePolicy } from '@kbn/fleet-plugin/common'; +import { POLICIES_ROUTE_PATH, INTEGRATION_PACKAGE_NAME } from '../../../common/constants'; +import { policiesQueryParamsSchema } from '../../../common/schemas/policy'; +import type { CloudDefendPolicy } from '../../../common/types'; +import { isNonNullable } from '../../../common/utils/helpers'; +import { CloudDefendRouter } from '../../types'; +import { + getAgentStatusesByAgentPolicies, + type AgentStatusByAgentPolicyMap, + getCloudDefendAgentPolicies, + getCloudDefendPackagePolicies, +} from '../../lib/fleet_util'; + +export const PACKAGE_POLICY_SAVED_OBJECT_TYPE = 'ingest-package-policies'; + +const createPolicies = ( + agentPolicies: AgentPolicy[], + agentStatusByAgentPolicyId: AgentStatusByAgentPolicyMap, + cloudDefendPackagePolicies: PackagePolicy[] +): Promise => { + const cloudDefendPackagePoliciesMap = new Map( + cloudDefendPackagePolicies.map((packagePolicy) => [packagePolicy.id, packagePolicy]) + ); + + return Promise.all( + agentPolicies.flatMap((agentPolicy) => { + const cloudDefendPackagesOnAgent = + agentPolicy.package_policies + ?.map(({ id: pckPolicyId }) => { + return cloudDefendPackagePoliciesMap.get(pckPolicyId); + }) + .filter(isNonNullable) ?? []; + + const policies = cloudDefendPackagesOnAgent.map(async (cloudDefendPackage) => { + const agentPolicyStatus = { + id: agentPolicy.id, + name: agentPolicy.name, + agents: agentStatusByAgentPolicyId[agentPolicy.id]?.total, + }; + return { + package_policy: cloudDefendPackage, + agent_policy: agentPolicyStatus, + }; + }); + + return policies; + }) + ); +}; + +export const defineGetPoliciesRoute = (router: CloudDefendRouter): void => + router.get( + { + path: POLICIES_ROUTE_PATH, + validate: { query: policiesQueryParamsSchema }, + options: { + tags: ['access:cloud-defend-read'], + }, + }, + async (context, request, response) => { + if (!(await context.fleet).authz.fleet.all) { + return response.forbidden(); + } + + const cloudDefendContext = await context.cloudDefend; + + try { + const cloudDefendPackagePolicies = await getCloudDefendPackagePolicies( + cloudDefendContext.soClient, + cloudDefendContext.packagePolicyService, + INTEGRATION_PACKAGE_NAME, + request.query + ); + + const agentPolicies = await getCloudDefendAgentPolicies( + cloudDefendContext.soClient, + cloudDefendPackagePolicies.items, + cloudDefendContext.agentPolicyService + ); + + const agentStatusesByAgentPolicyId = await getAgentStatusesByAgentPolicies( + cloudDefendContext.agentService, + agentPolicies, + cloudDefendContext.logger + ); + + const policies = await createPolicies( + agentPolicies, + agentStatusesByAgentPolicyId, + cloudDefendPackagePolicies.items + ); + + return response.ok({ + body: { + ...cloudDefendPackagePolicies, + items: policies, + }, + }); + } catch (err) { + const error = transformError(err); + cloudDefendContext.logger.error(`Failed to fetch policies ${err}`); + return response.customError({ + body: { message: error.message }, + statusCode: error.statusCode, + }); + } + } + ); diff --git a/x-pack/plugins/cloud_defend/server/routes/setup_routes.ts b/x-pack/plugins/cloud_defend/server/routes/setup_routes.ts new file mode 100644 index 0000000000000..1a9ef57ba83c7 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/routes/setup_routes.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { CoreSetup, Logger } from '@kbn/core/server'; +import type { AuthenticatedUser } from '@kbn/security-plugin/common'; +import type { + CloudDefendRequestHandlerContext, + CloudDefendPluginStart, + CloudDefendPluginStartDeps, +} from '../types'; +import { PLUGIN_ID } from '../../common/constants'; +import { defineGetPoliciesRoute } from './policies/policies'; +import { defineGetCloudDefendStatusRoute } from './status/status'; + +/** + * 1. Registers routes + * 2. Registers routes handler context + */ +export function setupRoutes({ + core, + logger, +}: { + core: CoreSetup; + logger: Logger; +}) { + const router = core.http.createRouter(); + defineGetPoliciesRoute(router); + defineGetCloudDefendStatusRoute(router); + + core.http.registerRouteHandlerContext( + PLUGIN_ID, + async (context, request) => { + const [, { security, fleet }] = await core.getStartServices(); + const coreContext = await context.core; + await fleet.fleetSetupCompleted(); + + let user: AuthenticatedUser | null = null; + + return { + get user() { + // We want to call getCurrentUser only when needed and only once + if (!user) { + user = security.authc.getCurrentUser(request); + } + return user; + }, + logger, + esClient: coreContext.elasticsearch.client, + soClient: coreContext.savedObjects.client, + agentPolicyService: fleet.agentPolicyService, + agentService: fleet.agentService, + packagePolicyService: fleet.packagePolicyService, + packageService: fleet.packageService, + }; + } + ); +} diff --git a/x-pack/plugins/cloud_defend/server/routes/status/status.test.ts b/x-pack/plugins/cloud_defend/server/routes/status/status.test.ts new file mode 100644 index 0000000000000..124d8f4738cb2 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/routes/status/status.test.ts @@ -0,0 +1,493 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { defineGetCloudDefendStatusRoute, INDEX_TIMEOUT_IN_MINUTES } from './status'; +import { httpServerMock, httpServiceMock } from '@kbn/core/server/mocks'; +import type { ESSearchResponse } from '@kbn/es-types'; +import { + AgentClient, + AgentPolicyServiceInterface, + AgentService, + PackageClient, + PackagePolicyClient, + PackageService, +} from '@kbn/fleet-plugin/server'; +import { + AgentPolicy, + GetAgentStatusResponse, + Installation, + RegistryPackage, +} from '@kbn/fleet-plugin/common'; +import { createPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks'; +import { createCloudDefendRequestHandlerContextMock } from '../../mocks'; +import { errors } from '@elastic/elasticsearch'; + +const mockCloudDefendPackageInfo: Installation = { + verification_status: 'verified', + installed_kibana: [], + installed_kibana_space_id: 'default', + installed_es: [], + package_assets: [], + es_index_patterns: { alerts: 'logs-cloud_defend.alerts-*' }, + name: 'cloud_defend', + version: '1.0.0', + install_version: '1.0.0', + install_status: 'installed', + install_started_at: '2022-06-16T15:24:58.281Z', + install_source: 'registry', +}; + +const mockLatestCloudDefendPackageInfo: RegistryPackage = { + format_version: 'mock', + name: 'cloud_defend', + title: 'Defend for containers (D4C)', + version: '1.0.0', + release: 'experimental', + description: 'Container drift prevention', + type: 'integration', + download: '/epr/cloud_defend/cloud_defend-1.0.0.zip', + path: '/package/cloud_defend/1.0.0', + policy_templates: [], + owner: { github: 'elastic/sec-cloudnative-integrations' }, + categories: ['containers', 'kubernetes'], +}; + +describe('CloudDefendSetupStatus route', () => { + const router = httpServiceMock.createRouter(); + let mockContext: ReturnType; + let mockPackagePolicyService: jest.Mocked; + let mockAgentPolicyService: jest.Mocked; + let mockAgentService: jest.Mocked; + let mockAgentClient: jest.Mocked; + let mockPackageService: PackageService; + let mockPackageClient: jest.Mocked; + + beforeEach(() => { + jest.clearAllMocks(); + + mockContext = createCloudDefendRequestHandlerContextMock(); + mockPackagePolicyService = mockContext.cloudDefend.packagePolicyService; + mockAgentPolicyService = mockContext.cloudDefend.agentPolicyService; + mockAgentService = mockContext.cloudDefend.agentService; + mockPackageService = mockContext.cloudDefend.packageService; + + mockAgentClient = mockAgentService.asInternalUser as jest.Mocked; + mockPackageClient = mockPackageService.asInternalUser as jest.Mocked; + }); + + it('validate the API route path', async () => { + defineGetCloudDefendStatusRoute(router); + const [config, _] = router.get.mock.calls[0]; + + expect(config.path).toEqual('/internal/cloud_defend/status'); + }); + + const indices = [ + { + index: 'logs-cloud_defend.alerts-default*', + expected_status: 'not-installed', + }, + ]; + + indices.forEach((idxTestCase) => { + it( + 'Verify the API result when there are no permissions to index: ' + idxTestCase.index, + async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseImplementation( + (req) => { + if (req?.index === idxTestCase.index) { + throw new errors.ResponseError({ + body: { + error: { + type: 'security_exception', + }, + }, + statusCode: 503, + headers: {}, + warnings: [], + meta: {} as any, + }); + } + + return { + hits: { + hits: [{}], + }, + } as any; + } + ); + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 0, + page: 1, + perPage: 100, + }); + + // Act + defineGetCloudDefendStatusRoute(router); + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + await handler(mockContext, mockRequest, mockResponse); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]?.body; + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + expect(body).toMatchObject({ + status: idxTestCase.expected_status, + }); + } + ); + }); + + it('Verify the API result when there are alerts and no installed policies', async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({ + hits: { + hits: [{ Alerts: 'foo' }], + }, + } as unknown as ESSearchResponse); + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 0, + page: 1, + perPage: 100, + }); + + // Act + defineGetCloudDefendStatusRoute(router); + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + await handler(mockContext, mockRequest, mockResponse); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]?.body; + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + await expect(body).toMatchObject({ + status: 'indexed', + latestPackageVersion: '1.0.0', + installedPackagePolicies: 0, + healthyAgents: 0, + installedPackageVersion: undefined, + }); + }); + + it('Verify the API result when there are alerts, installed policies, no running agents', async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({ + hits: { + hits: [{ Alerts: 'foo' }], + }, + } as unknown as ESSearchResponse); + + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + mockPackageClient.getInstallation.mockResolvedValueOnce(mockCloudDefendPackageInfo); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 3, + page: 1, + perPage: 100, + }); + + // Act + defineGetCloudDefendStatusRoute(router); + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + await handler(mockContext, mockRequest, mockResponse); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]?.body; + + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + await expect(body).toMatchObject({ + status: 'indexed', + latestPackageVersion: '1.0.0', + installedPackagePolicies: 3, + healthyAgents: 0, + installedPackageVersion: '1.0.0', + }); + }); + + it('Verify the API result when there are alerts, installed policies, running agents', async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({ + hits: { + hits: [{ Alerts: 'foo' }], + }, + } as unknown as ESSearchResponse); + + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + mockPackageClient.getInstallation.mockResolvedValueOnce(mockCloudDefendPackageInfo); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 3, + page: 1, + perPage: 100, + }); + + mockAgentPolicyService.getByIds.mockResolvedValue([ + { package_policies: createPackagePolicyMock() }, + ] as unknown as AgentPolicy[]); + + mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({ + online: 1, + updating: 0, + } as unknown as GetAgentStatusResponse['results']); + + // Act + defineGetCloudDefendStatusRoute(router); + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + await handler(mockContext, mockRequest, mockResponse); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]!.body; + + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + expect(body).toMatchObject({ + status: 'indexed', + latestPackageVersion: '1.0.0', + installedPackagePolicies: 3, + healthyAgents: 1, + installedPackageVersion: '1.0.0', + }); + }); + + it('Verify the API result when there are no alerts and no installed policies', async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({ + hits: { + hits: [], + }, + } as unknown as ESSearchResponse); + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 0, + page: 1, + perPage: 100, + }); + defineGetCloudDefendStatusRoute(router); + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + + // Act + await handler(mockContext, mockRequest, mockResponse); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]!.body; + + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + expect(body).toMatchObject({ + status: 'not-installed', + latestPackageVersion: '1.0.0', + installedPackagePolicies: 0, + healthyAgents: 0, + }); + }); + + it('Verify the API result when there are no alerts, installed agent but no deployed agent', async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({ + hits: { + hits: [], + }, + } as unknown as ESSearchResponse); + + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + mockPackageClient.getInstallation.mockResolvedValueOnce(mockCloudDefendPackageInfo); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 1, + page: 1, + perPage: 100, + }); + + mockAgentPolicyService.getByIds.mockResolvedValue([ + { package_policies: createPackagePolicyMock() }, + ] as unknown as AgentPolicy[]); + + mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({ + online: 0, + updating: 0, + } as unknown as GetAgentStatusResponse['results']); + + // Act + defineGetCloudDefendStatusRoute(router); + + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + await handler(mockContext, mockRequest, mockResponse); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]!.body; + + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + expect(body).toMatchObject({ + status: 'not-deployed', + latestPackageVersion: '1.0.0', + installedPackagePolicies: 1, + healthyAgents: 0, + installedPackageVersion: '1.0.0', + }); + }); + + it('Verify the API result when there are no alerts, installed agent, deployed agent, before index timeout', async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({ + hits: { + hits: [], + }, + } as unknown as ESSearchResponse); + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + + const currentTime = new Date(); + mockCloudDefendPackageInfo.install_started_at = new Date( + currentTime.setMinutes(currentTime.getMinutes() - INDEX_TIMEOUT_IN_MINUTES + 1) + ).toUTCString(); + + mockPackageClient.getInstallation.mockResolvedValueOnce(mockCloudDefendPackageInfo); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 1, + page: 1, + perPage: 100, + }); + + mockAgentPolicyService.getByIds.mockResolvedValue([ + { package_policies: createPackagePolicyMock() }, + ] as unknown as AgentPolicy[]); + + mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({ + online: 1, + updating: 0, + } as unknown as GetAgentStatusResponse['results']); + + // Act + defineGetCloudDefendStatusRoute(router); + + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + const [context, req, res] = [mockContext, mockRequest, mockResponse]; + + await handler(context, req, res); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]!.body; + + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + expect(body).toMatchObject({ + status: 'indexing', + latestPackageVersion: '1.0.0', + installedPackagePolicies: 1, + healthyAgents: 1, + installedPackageVersion: '1.0.0', + }); + }); + + it('Verify the API result when there are no alerts, installed agent, deployed agent, after index timeout', async () => { + mockContext.core.elasticsearch.client.asCurrentUser.search.mockResponseOnce({ + hits: { + hits: [], + }, + } as unknown as ESSearchResponse); + mockPackageClient.fetchFindLatestPackage.mockResolvedValueOnce( + mockLatestCloudDefendPackageInfo + ); + + const currentTime = new Date(); + mockCloudDefendPackageInfo.install_started_at = new Date( + currentTime.setMinutes(currentTime.getMinutes() - INDEX_TIMEOUT_IN_MINUTES - 1) + ).toUTCString(); + + mockPackageClient.getInstallation.mockResolvedValueOnce(mockCloudDefendPackageInfo); + + mockPackagePolicyService.list.mockResolvedValueOnce({ + items: [], + total: 1, + page: 1, + perPage: 100, + }); + + mockAgentPolicyService.getByIds.mockResolvedValue([ + { package_policies: createPackagePolicyMock() }, + ] as unknown as AgentPolicy[]); + + mockAgentClient.getAgentStatusForAgentPolicy.mockResolvedValue({ + online: 1, + updating: 0, + } as unknown as GetAgentStatusResponse['results']); + + // Act + defineGetCloudDefendStatusRoute(router); + + const [_, handler] = router.get.mock.calls[0]; + + const mockResponse = httpServerMock.createResponseFactory(); + const mockRequest = httpServerMock.createKibanaRequest(); + + await handler(mockContext, mockRequest, mockResponse); + + // Assert + const [call] = mockResponse.ok.mock.calls; + const body = call[0]!.body; + + expect(mockResponse.ok).toHaveBeenCalledTimes(1); + + expect(body).toMatchObject({ + status: 'index-timeout', + latestPackageVersion: '1.0.0', + installedPackagePolicies: 1, + healthyAgents: 1, + installedPackageVersion: '1.0.0', + }); + }); +}); diff --git a/x-pack/plugins/cloud_defend/server/routes/status/status.ts b/x-pack/plugins/cloud_defend/server/routes/status/status.ts new file mode 100644 index 0000000000000..0283843254978 --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/routes/status/status.ts @@ -0,0 +1,198 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { transformError } from '@kbn/securitysolution-es-utils'; +import type { SavedObjectsClientContract, Logger } from '@kbn/core/server'; +import type { AgentPolicyServiceInterface, AgentService } from '@kbn/fleet-plugin/server'; +import moment from 'moment'; +import { PackagePolicy } from '@kbn/fleet-plugin/common'; +import { + ALERTS_INDEX_PATTERN, + INTEGRATION_PACKAGE_NAME, + STATUS_ROUTE_PATH, +} from '../../../common/constants'; +import type { CloudDefendApiRequestHandlerContext, CloudDefendRouter } from '../../types'; +import type { + CloudDefendSetupStatus, + CloudDefendStatusCode, + IndexStatus, +} from '../../../common/types'; +import { + getAgentStatusesByAgentPolicies, + getCloudDefendAgentPolicies, + getCloudDefendPackagePolicies, + getInstalledPolicyTemplates, +} from '../../lib/fleet_util'; +import { checkIndexStatus } from '../../lib/check_index_status'; + +export const INDEX_TIMEOUT_IN_MINUTES = 10; + +const calculateDiffFromNowInMinutes = (date: string | number): number => + moment().diff(moment(date), 'minutes'); + +const getHealthyAgents = async ( + soClient: SavedObjectsClientContract, + installedCloudDefendPackagePolicies: PackagePolicy[], + agentPolicyService: AgentPolicyServiceInterface, + agentService: AgentService, + logger: Logger +): Promise => { + // Get agent policies of package policies (from installed package policies) + const agentPolicies = await getCloudDefendAgentPolicies( + soClient, + installedCloudDefendPackagePolicies, + agentPolicyService + ); + + // Get agents statuses of the following agent policies + const agentStatusesByAgentPolicyId = await getAgentStatusesByAgentPolicies( + agentService, + agentPolicies, + logger + ); + + return Object.values(agentStatusesByAgentPolicyId).reduce( + (sum, status) => sum + status.online + status.updating, + 0 + ); +}; + +const calculateCloudDefendStatusCode = ( + indicesStatus: { + alerts: IndexStatus; + }, + installedCloudDefendPackagePolicies: number, + healthyAgents: number, + timeSinceInstallationInMinutes: number +): CloudDefendStatusCode => { + // We check privileges only for the relevant indices for our pages to appear + if (indicesStatus.alerts === 'unprivileged') return 'unprivileged'; + if (indicesStatus.alerts === 'not-empty') return 'indexed'; + if (installedCloudDefendPackagePolicies === 0) return 'not-installed'; + if (healthyAgents === 0) return 'not-deployed'; + if (timeSinceInstallationInMinutes <= INDEX_TIMEOUT_IN_MINUTES) return 'indexing'; + if (timeSinceInstallationInMinutes > INDEX_TIMEOUT_IN_MINUTES) return 'index-timeout'; + + throw new Error('Could not determine cloud defend status'); +}; + +const assertResponse = ( + resp: CloudDefendSetupStatus, + logger: CloudDefendApiRequestHandlerContext['logger'] +) => { + if ( + resp.status === 'unprivileged' && + !resp.indicesDetails.some((idxDetails) => idxDetails.status === 'unprivileged') + ) { + logger.warn('Returned status in `unprivileged` but response is missing the unprivileged index'); + } +}; + +const getCloudDefendStatus = async ({ + logger, + esClient, + soClient, + packageService, + packagePolicyService, + agentPolicyService, + agentService, +}: CloudDefendApiRequestHandlerContext): Promise => { + const [ + alertsIndexStatus, + installation, + latestCloudDefendPackage, + installedPackagePolicies, + installedPolicyTemplates, + ] = await Promise.all([ + checkIndexStatus(esClient.asCurrentUser, ALERTS_INDEX_PATTERN, logger), + packageService.asInternalUser.getInstallation(INTEGRATION_PACKAGE_NAME), + packageService.asInternalUser.fetchFindLatestPackage(INTEGRATION_PACKAGE_NAME), + getCloudDefendPackagePolicies(soClient, packagePolicyService, INTEGRATION_PACKAGE_NAME, { + per_page: 10000, + }), + getInstalledPolicyTemplates(packagePolicyService, soClient), + ]); + + const healthyAgents = await getHealthyAgents( + soClient, + installedPackagePolicies.items, + agentPolicyService, + agentService, + logger + ); + + const installedPackagePoliciesTotal = installedPackagePolicies.total; + const latestCloudDefendPackageVersion = latestCloudDefendPackage.version; + + const MIN_DATE = 0; + const indicesDetails = [ + { + index: ALERTS_INDEX_PATTERN, + status: alertsIndexStatus, + }, + ]; + + const status = calculateCloudDefendStatusCode( + { + alerts: alertsIndexStatus, + }, + installedPackagePoliciesTotal, + healthyAgents, + calculateDiffFromNowInMinutes(installation?.install_started_at || MIN_DATE) + ); + + if (status === 'not-installed') + return { + status, + indicesDetails, + latestPackageVersion: latestCloudDefendPackageVersion, + healthyAgents, + installedPackagePolicies: installedPackagePoliciesTotal, + }; + + const response = { + status, + indicesDetails, + latestPackageVersion: latestCloudDefendPackageVersion, + healthyAgents, + installedPolicyTemplates, + installedPackagePolicies: installedPackagePoliciesTotal, + installedPackageVersion: installation?.install_version, + }; + + assertResponse(response, logger); + return response; +}; + +export const defineGetCloudDefendStatusRoute = (router: CloudDefendRouter): void => + router.get( + { + path: STATUS_ROUTE_PATH, + validate: {}, + options: { + tags: ['access:cloud-defend-read'], + }, + }, + async (context, request, response) => { + const cloudDefendContext = await context.cloudDefend; + try { + const status = await getCloudDefendStatus(cloudDefendContext); + return response.ok({ + body: status, + }); + } catch (err) { + cloudDefendContext.logger.error(`Error getting cloud_defend status`); + cloudDefendContext.logger.error(err); + + const error = transformError(err); + return response.customError({ + body: { message: error.message }, + statusCode: error.statusCode, + }); + } + } + ); diff --git a/x-pack/plugins/cloud_defend/server/types.ts b/x-pack/plugins/cloud_defend/server/types.ts new file mode 100644 index 0000000000000..121a97ee926be --- /dev/null +++ b/x-pack/plugins/cloud_defend/server/types.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { CloudSetup } from '@kbn/cloud-plugin/server'; +import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; +import type { + IRouter, + CustomRequestHandlerContext, + Logger, + SavedObjectsClientContract, + IScopedClusterClient, +} from '@kbn/core/server'; +import type { LicensingPluginStart } from '@kbn/licensing-plugin/server'; +import type { + FleetStartContract, + FleetRequestHandlerContext, + AgentService, + PackageService, + AgentPolicyServiceInterface, + PackagePolicyClient, +} from '@kbn/fleet-plugin/server'; +import type { + PluginSetup as DataPluginSetup, + PluginStart as DataPluginStart, +} from '@kbn/data-plugin/server'; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface CloudDefendPluginSetup {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface CloudDefendPluginStart {} + +export interface CloudDefendPluginSetupDeps { + data: DataPluginSetup; + security: SecurityPluginSetup; + cloud: CloudSetup; +} +export interface CloudDefendPluginStartDeps { + data: DataPluginStart; + fleet: FleetStartContract; + security: SecurityPluginStart; + licensing: LicensingPluginStart; +} + +export interface CloudDefendApiRequestHandlerContext { + user: ReturnType; + logger: Logger; + esClient: IScopedClusterClient; + soClient: SavedObjectsClientContract; + agentPolicyService: AgentPolicyServiceInterface; + agentService: AgentService; + packagePolicyService: PackagePolicyClient; + packageService: PackageService; +} + +export type CloudDefendRequestHandlerContext = CustomRequestHandlerContext<{ + cloudDefend: CloudDefendApiRequestHandlerContext; + fleet: FleetRequestHandlerContext['fleet']; +}>; + +/** + * Convenience type for routers in cloud_defend that includes the CloudDefendRequestHandlerContext type + * @internal + */ +export type CloudDefendRouter = IRouter; diff --git a/x-pack/plugins/cloud_defend/tsconfig.json b/x-pack/plugins/cloud_defend/tsconfig.json index f96b98d8c44dd..d12ee82da6fce 100755 --- a/x-pack/plugins/cloud_defend/tsconfig.json +++ b/x-pack/plugins/cloud_defend/tsconfig.json @@ -6,23 +6,30 @@ "include": [ "common/**/*", "public/**/*", + "server/**/*", "../../../typings/**/*", - "server/**/*.json", - "public/**/*.json" + "public/**/*.json", + "server/**/*.json" ], "kbn_references": [ "@kbn/core", + "@kbn/data-plugin", + "@kbn/security-plugin", "@kbn/fleet-plugin", - "@kbn/fleet-plugin", - "@kbn/core", "@kbn/i18n-react", + "@kbn/config-schema", + "@kbn/licensing-plugin", "@kbn/data-plugin", "@kbn/kibana-react-plugin", "@kbn/monaco", "@kbn/i18n", - "@kbn/shared-ux-router" + "@kbn/usage-collection-plugin", + "@kbn/cloud-plugin", + "@kbn/shared-ux-router", + "@kbn/shared-ux-link-redirect-app", + "@kbn/core-logging-server-mocks", + "@kbn/securitysolution-es-utils", + "@kbn/es-types" ], - "exclude": [ - "target/**/*" - ] + "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 55b802ae06d8d..5c903966bd0cc 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -91,6 +91,11 @@ export enum SecurityPageName { cloudSecurityPostureDashboard = 'cloud_security_posture-dashboard', cloudSecurityPostureFindings = 'cloud_security_posture-findings', cloudSecurityPostureRules = 'cloud_security_posture-rules', + /* + * Warning: Computed values are not permitted in an enum with string valued members + * All cloud defend page names must match `CloudDefendPageId` in x-pack/plugins/cloud_defend/public/common/navigation/types.ts + */ + cloudDefendPolicies = 'cloud_defend-policies', dashboardsLanding = 'dashboards', dataQuality = 'data_quality', detections = 'detections', diff --git a/x-pack/plugins/security_solution/kibana.jsonc b/x-pack/plugins/security_solution/kibana.jsonc index 6f6c371f5f27f..85418bdeb31b7 100644 --- a/x-pack/plugins/security_solution/kibana.jsonc +++ b/x-pack/plugins/security_solution/kibana.jsonc @@ -15,6 +15,7 @@ "alerting", "cases", "cloud", + "cloudDefend", "cloudSecurityPosture", "dashboard", "data", diff --git a/x-pack/plugins/security_solution/public/app/deep_links/index.ts b/x-pack/plugins/security_solution/public/app/deep_links/index.ts index 9853c52502fb2..87d43742a9433 100644 --- a/x-pack/plugins/security_solution/public/app/deep_links/index.ts +++ b/x-pack/plugins/security_solution/public/app/deep_links/index.ts @@ -7,7 +7,8 @@ import { i18n } from '@kbn/i18n'; -import { getSecuritySolutionLink } from '@kbn/cloud-security-posture-plugin/public'; +import { getSecuritySolutionLink as getCloudDefendSecuritySolutionLink } from '@kbn/cloud-defend-plugin/public'; +import { getSecuritySolutionLink as getCloudPostureSecuritySolutionLink } from '@kbn/cloud-security-posture-plugin/public'; import { getSecuritySolutionDeepLink } from '@kbn/threat-intelligence-plugin/public'; import type { LicenseType } from '@kbn/licensing-plugin/common/types'; import { getCasesDeepLinks } from '@kbn/cases-plugin/public'; @@ -167,7 +168,7 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ ], }, { - ...getSecuritySolutionLink('dashboard'), + ...getCloudPostureSecuritySolutionLink('dashboard'), features: [FEATURE.general], }, { @@ -251,7 +252,7 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ ], }, { - ...getSecuritySolutionLink('findings'), + ...getCloudPostureSecuritySolutionLink('findings'), features: [FEATURE.general], navLinkStatus: AppNavLinkStatus.visible, order: 9002, @@ -529,7 +530,10 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ path: RESPONSE_ACTIONS_HISTORY_PATH, }, { - ...getSecuritySolutionLink('benchmarks'), + ...getCloudPostureSecuritySolutionLink('benchmarks'), + }, + { + ...getCloudDefendSecuritySolutionLink('policies'), }, ], }, diff --git a/x-pack/plugins/security_solution/public/app/home/home_navigations.ts b/x-pack/plugins/security_solution/public/app/home/home_navigations.ts index bbff6ffa0a6f9..d9a988004ac1a 100644 --- a/x-pack/plugins/security_solution/public/app/home/home_navigations.ts +++ b/x-pack/plugins/security_solution/public/app/home/home_navigations.ts @@ -7,6 +7,7 @@ import { getSecuritySolutionNavTab as getSecuritySolutionCSPNavTab } from '@kbn/cloud-security-posture-plugin/public'; import { getSecuritySolutionNavTab as getSecuritySolutionTINavTab } from '@kbn/threat-intelligence-plugin/public'; +import { getSecuritySolutionNavTab as getSecuritySolutionCloudDefendNavTab } from '@kbn/cloud-defend-plugin/public'; import * as i18n from '../translations'; import type { SecurityNav, SecurityNavGroup } from '../../common/components/navigation/types'; import { SecurityNavGroupKey } from '../../common/components/navigation/types'; @@ -186,6 +187,10 @@ export const navTabs: SecurityNav = { ...getSecuritySolutionCSPNavTab('benchmarks', APP_PATH), urlKey: 'administration', }, + [SecurityPageName.cloudDefendPolicies]: { + ...getSecuritySolutionCloudDefendNavTab('policies', APP_PATH), + urlKey: 'administration', + }, [SecurityPageName.entityAnalytics]: { id: SecurityPageName.entityAnalytics, name: i18n.ENTITY_ANALYTICS, diff --git a/x-pack/plugins/security_solution/public/cloud_defend/index.ts b/x-pack/plugins/security_solution/public/cloud_defend/index.ts new file mode 100644 index 0000000000000..4ec2329d36bd5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_defend/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { SecuritySubPlugin } from '../app/types'; +import { routes } from './routes'; + +export class CloudDefend { + public setup() {} + + public start(): SecuritySubPlugin { + return { routes }; + } +} diff --git a/x-pack/plugins/security_solution/public/cloud_defend/links.ts b/x-pack/plugins/security_solution/public/cloud_defend/links.ts new file mode 100644 index 0000000000000..652ebe6181151 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_defend/links.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { getSecuritySolutionLink } from '@kbn/cloud-defend-plugin/public'; +import { i18n } from '@kbn/i18n'; +import type { SecurityPageName } from '../../common/constants'; +import { SERVER_APP_ID } from '../../common/constants'; +import type { LinkItem } from '../common/links/types'; +import { IconCloudDefend } from '../management/icons/cloud_defend'; + +const commonLinkProperties: Partial = { + hideTimeline: true, + capabilities: [`${SERVER_APP_ID}.show`], +}; + +export const manageLinks: LinkItem = { + ...getSecuritySolutionLink('policies'), + description: i18n.translate('xpack.securitySolution.appLinks.cloudDefendPoliciesDescription', { + defaultMessage: 'View drift prevention policies.', + }), + landingIcon: IconCloudDefend, + ...commonLinkProperties, +}; diff --git a/x-pack/plugins/security_solution/public/cloud_defend/routes.tsx b/x-pack/plugins/security_solution/public/cloud_defend/routes.tsx new file mode 100644 index 0000000000000..18bd7641addf3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/cloud_defend/routes.tsx @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { + CloudDefendPageId, + CloudDefendSecuritySolutionContext, +} from '@kbn/cloud-defend-plugin/public'; +import { CLOUD_DEFEND_BASE_PATH } from '@kbn/cloud-defend-plugin/public'; +import type { SecurityPageName, SecuritySubPluginRoutes } from '../app/types'; +import { useKibana } from '../common/lib/kibana'; +import { SecuritySolutionPageWrapper } from '../common/components/page_wrapper'; +import { SpyRoute } from '../common/utils/route/spy_routes'; +import { FiltersGlobal } from '../common/components/filters_global'; +import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper'; + +// This exists only for the type signature cast +const CloudDefendSpyRoute = ({ pageName, ...rest }: { pageName?: CloudDefendPageId }) => ( + +); + +const cloudDefendSecuritySolutionContext: CloudDefendSecuritySolutionContext = { + getFiltersGlobalComponent: () => FiltersGlobal, + getSpyRouteComponent: () => CloudDefendSpyRoute, +}; + +const CloudDefend = () => { + const { cloudDefend } = useKibana().services; + const CloudDefendRouter = cloudDefend.getCloudDefendRouter(); + + return ( + + + + + + ); +}; + +CloudDefend.displayName = 'CloudDefend'; + +export const routes: SecuritySubPluginRoutes = [ + { + path: CLOUD_DEFEND_BASE_PATH, + component: CloudDefend, + }, +]; diff --git a/x-pack/plugins/security_solution/public/cloud_security_posture/links.ts b/x-pack/plugins/security_solution/public/cloud_security_posture/links.ts index def3b0ed9f5eb..e4c0dfd1f20db 100644 --- a/x-pack/plugins/security_solution/public/cloud_security_posture/links.ts +++ b/x-pack/plugins/security_solution/public/cloud_security_posture/links.ts @@ -51,6 +51,9 @@ export const manageCategories: LinkCategories = [ label: i18n.translate('xpack.securitySolution.appLinks.category.cloudSecurityPosture', { defaultMessage: 'CLOUD SECURITY POSTURE', }), - linkIds: [SecurityPageName.cloudSecurityPostureBenchmarks], + linkIds: [ + SecurityPageName.cloudSecurityPostureBenchmarks, + SecurityPageName.cloudDefendPolicies, + ], }, ]; diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts index b0190d40ced78..29f69700afdb7 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/types.ts @@ -42,6 +42,7 @@ export type UrlStateType = | 'explore' | 'dashboards' | 'indicators' + | 'cloud_defend' | 'cloud_posture' | 'findings' | 'entity_analytics' @@ -84,6 +85,7 @@ export const securityNavKeys = [ SecurityPageName.cloudSecurityPostureDashboard, SecurityPageName.cloudSecurityPostureFindings, SecurityPageName.cloudSecurityPostureBenchmarks, + SecurityPageName.cloudDefendPolicies, SecurityPageName.entityAnalytics, SecurityPageName.dataQuality, ] as const; diff --git a/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx b/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx index 1d93699ff1b47..66aefc6db3e08 100644 --- a/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx +++ b/x-pack/plugins/security_solution/public/lazy_sub_plugins.tsx @@ -20,6 +20,7 @@ import { Rules } from './rules'; import { Timelines } from './timelines'; import { Management } from './management'; import { LandingPages } from './landing_pages'; +import { CloudDefend } from './cloud_defend'; import { CloudSecurityPosture } from './cloud_security_posture'; import { ThreatIntelligence } from './threat_intelligence'; @@ -37,6 +38,7 @@ const subPluginClasses = { Timelines, Management, LandingPages, + CloudDefend, CloudSecurityPosture, ThreatIntelligence, }; diff --git a/x-pack/plugins/security_solution/public/management/icons/cloud_defend.tsx b/x-pack/plugins/security_solution/public/management/icons/cloud_defend.tsx new file mode 100644 index 0000000000000..1eb5a656b3628 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/icons/cloud_defend.tsx @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { SVGProps } from 'react'; +import React from 'react'; +export const IconCloudDefend: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + + +); diff --git a/x-pack/plugins/security_solution/public/management/links.ts b/x-pack/plugins/security_solution/public/management/links.ts index 1db32eae3d5f2..57f2c53a7be19 100644 --- a/x-pack/plugins/security_solution/public/management/links.ts +++ b/x-pack/plugins/security_solution/public/management/links.ts @@ -49,6 +49,7 @@ import { manageCategories as cloudSecurityPostureCategories, manageLinks as cloudSecurityPostureLinks, } from '../cloud_security_posture/links'; +import { manageLinks as cloudDefendLinks } from '../cloud_defend/links'; import { IconActionHistory } from './icons/action_history'; import { IconBlocklist } from './icons/blocklist'; import { IconEndpoints } from './icons/endpoints'; @@ -226,6 +227,7 @@ export const links: LinkItem = { hideTimeline: true, }, cloudSecurityPostureLinks, + cloudDefendLinks, ], }; diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index abc9c41101e25..78680086d45c0 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -395,6 +395,7 @@ export class Plugin implements IPlugin; management: ReturnType; landingPages: ReturnType; + cloudDefend: ReturnType; cloudSecurityPosture: ReturnType; threatIntelligence: ReturnType; } diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index 373c561888a23..1cc1a355d3537 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -36,6 +36,7 @@ "@kbn/actions-plugin", "@kbn/alerting-plugin", "@kbn/cases-plugin", + "@kbn/cloud-defend-plugin", "@kbn/cloud-experiments-plugin", "@kbn/cloud-security-posture-plugin", "@kbn/encrypted-saved-objects-plugin", From b833b108215c858177535fd3feee406cc628bca8 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Tue, 28 Feb 2023 18:47:28 -0700 Subject: [PATCH 070/131] [Security Solution] Fixes Related Integrations showing as not installed or enabled when they actually are (#152055) ## Summary Resolves: https://github.com/elastic/kibana/issues/142081 https://github.com/elastic/kibana/issues/149970 https://github.com/elastic/kibana/issues/150968 By adding an initial query for installed integrations and augments the existing `InstalledIntegrationArray` constructed using `PackagePolicy`'s. Also removes `version` from the `packageKey` when calculating installed integrations as there can be mis-matches between different policy versions and the integration itself, and I believe the intended behavior here is to not have multiple `relatedIntegrations` returned for different versions. We may want to expand the response here to include all the different policy versions that exist (and perhaps # of agents assigned the policy). Lastly, updates `getIntegrationsInfoFromPolicy()` to also pull the base `package` details in addition to the policy_template details, as this is what ensure base packages show as `Installed: enabled` if they have an integration policy assigned (vs just showing as `Installed` like when there isn't an integration policy). Note: This PR also adds the `getPackages()` method to the `PackageClient` as it didn't currently exist, and was only available via the fleet API via the `/api/fleet/epm/packages` route. ### Before:

    ### After

    --------- Co-authored-by: Georgii Gorbachev --- .../services/epm/package_service.mock.ts | 1 + .../server/services/epm/package_service.ts | 26 +++++- .../related_integrations.cy.ts | 2 +- .../installed_integration_set.ts | 89 ++++++++++++++----- .../api/get_installed_integrations/route.ts | 47 ++-------- 5 files changed, 102 insertions(+), 63 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts b/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts index 806f295ec2c4e..69e1217b0493c 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.mock.ts @@ -12,6 +12,7 @@ const createClientMock = (): jest.Mocked => ({ ensureInstalledPackage: jest.fn(), fetchFindLatestPackage: jest.fn(), getPackage: jest.fn(), + getPackages: jest.fn(), reinstallEsAssets: jest.fn(), }); diff --git a/x-pack/plugins/fleet/server/services/epm/package_service.ts b/x-pack/plugins/fleet/server/services/epm/package_service.ts index dfc02c4f68c57..b0dd6e9dc38b4 100644 --- a/x-pack/plugins/fleet/server/services/epm/package_service.ts +++ b/x-pack/plugins/fleet/server/services/epm/package_service.ts @@ -14,7 +14,10 @@ import type { Logger, } from '@kbn/core/server'; +import type { PackageList } from '../../../common'; + import type { + CategoryId, EsAssetReference, InstallablePackage, Installation, @@ -28,7 +31,7 @@ import { FleetUnauthorizedError } from '../../errors'; import { installTransforms, isTransform } from './elasticsearch/transform/install'; import type { FetchFindLatestPackageOptions } from './registry'; import { fetchFindLatestPackageOrThrow, getPackage } from './registry'; -import { ensureInstalledPackage, getInstallation } from './packages'; +import { ensureInstalledPackage, getInstallation, getPackages } from './packages'; export type InstalledAssetType = EsAssetReference; @@ -56,6 +59,12 @@ export interface PackageClient { packageVersion: string ): Promise<{ packageInfo: ArchivePackage; paths: string[] }>; + getPackages(params?: { + excludeInstallStatus?: false; + category?: CategoryId; + prerelease?: false; + }): Promise; + reinstallEsAssets( packageInfo: InstallablePackage, assetPaths: string[] @@ -137,6 +146,21 @@ class PackageClientImpl implements PackageClient { return getPackage(packageName, packageVersion, options); } + public async getPackages(params?: { + excludeInstallStatus?: false; + category?: CategoryId; + prerelease?: false; + }) { + const { excludeInstallStatus, category, prerelease } = params || {}; + await this.#runPreflight(); + return getPackages({ + savedObjectsClient: this.internalSoClient, + excludeInstallStatus, + category, + prerelease, + }); + } + public async reinstallEsAssets( packageInfo: InstallablePackage, assetPaths: string[] diff --git a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts index f411b5e229590..663317f334751 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/detection_rules/related_integrations.cy.ts @@ -117,7 +117,7 @@ describe('Related integrations', () => { const rule = { name: 'Related integrations rule', integrations: [ - { name: 'Amazon CloudFront', installed: true, enabled: true }, + { name: 'AWS Cloudfront', installed: true, enabled: true }, { name: 'AWS CloudTrail', installed: true, enabled: false }, { name: 'Aws Unknown', installed: false, enabled: false }, { name: 'System', installed: true, enabled: true }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/installed_integration_set.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/installed_integration_set.ts index af35f7881bd00..dcf9d006c4315 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/installed_integration_set.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/installed_integration_set.ts @@ -5,8 +5,8 @@ * 2.0. */ +import type { PackageListItem, PackagePolicy } from '@kbn/fleet-plugin/common'; import { capitalize, flatten } from 'lodash'; -import type { PackagePolicy, ArchivePackage } from '@kbn/fleet-plugin/common'; import type { InstalledIntegration, InstalledIntegrationArray, @@ -17,8 +17,8 @@ import type { } from '../../../../../../common/detection_engine/fleet_integrations'; export interface IInstalledIntegrationSet { + addPackage(fleetPackage: PackageListItem): void; addPackagePolicy(policy: PackagePolicy): void; - addRegistryPackage(registryPackage: ArchivePackage): void; getPackages(): InstalledPackageArray; getIntegrations(): InstalledIntegrationArray; @@ -33,10 +33,57 @@ interface PackageInfo extends InstalledPackageBasicInfo { export const createInstalledIntegrationSet = (): IInstalledIntegrationSet => { const packageMap: PackageMap = new Map([]); + const addPackage = (fleetPackage: PackageListItem): void => { + if (fleetPackage.type !== 'integration') { + return; + } + if (fleetPackage.status !== 'installed') { + return; + } + + const packageKey = `${fleetPackage.name}`; + const existingPackageInfo = packageMap.get(packageKey); + + if (existingPackageInfo != null) { + return; + } + + // Actual `installed_version` is buried in SO, root `version` is latest package version available + const installedPackageVersion = fleetPackage.savedObject.attributes.install_version; + + // Policy templates correspond to package's integrations. + const packagePolicyTemplates = fleetPackage.policy_templates ?? []; + + const packageInfo: PackageInfo = { + package_name: fleetPackage.name, + package_title: fleetPackage.title, + package_version: installedPackageVersion, + + integrations: new Map( + packagePolicyTemplates.map((pt) => { + const integrationTitle: string = + packagePolicyTemplates.length === 1 && pt.name === fleetPackage.name + ? fleetPackage.title + : pt.title; + + const integrationInfo: InstalledIntegrationBasicInfo = { + integration_name: pt.name, + integration_title: integrationTitle, + is_enabled: false, // There might not be an integration policy, so default false and later update in addPackagePolicy() + }; + + return [integrationInfo.integration_name, integrationInfo]; + }) + ), + }; + + packageMap.set(packageKey, packageInfo); + }; + const addPackagePolicy = (policy: PackagePolicy): void => { const packageInfo = getPackageInfoFromPolicy(policy); const integrationsInfo = getIntegrationsInfoFromPolicy(policy, packageInfo); - const packageKey = `${packageInfo.package_name}:${packageInfo.package_version}`; + const packageKey = `${packageInfo.package_name}`; const existingPackageInfo = packageMap.get(packageKey); if (existingPackageInfo == null) { @@ -56,21 +103,6 @@ export const createInstalledIntegrationSet = (): IInstalledIntegrationSet => { } }; - const addRegistryPackage = (registryPackage: ArchivePackage): void => { - const policyTemplates = registryPackage.policy_templates ?? []; - const packageKey = `${registryPackage.name}:${registryPackage.version}`; - const existingPackageInfo = packageMap.get(packageKey); - - if (existingPackageInfo != null) { - for (const integration of existingPackageInfo.integrations.values()) { - const policyTemplate = policyTemplates.find((t) => t.name === integration.integration_name); - if (policyTemplate != null) { - integration.integration_title = policyTemplate.title; - } - } - } - }; - const getPackages = (): InstalledPackageArray => { const packages = Array.from(packageMap.values()); return packages.map((packageInfo): InstalledPackage => { @@ -106,8 +138,8 @@ export const createInstalledIntegrationSet = (): IInstalledIntegrationSet => { }; return { + addPackage, addPackagePolicy, - addRegistryPackage, getPackages, getIntegrations, }; @@ -125,15 +157,30 @@ const getIntegrationsInfoFromPolicy = ( policy: PackagePolicy, packageInfo: InstalledPackageBasicInfo ): InstalledIntegrationBasicInfo[] => { - return policy.inputs.map((input) => { + // Construct integration info from the available policy_templates + const integrationInfos = policy.inputs.map((input) => { const integrationName = normalizeString(input.policy_template ?? input.type); // e.g. 'cloudtrail' const integrationTitle = `${packageInfo.package_title} ${capitalize(integrationName)}`; // e.g. 'AWS Cloudtrail' return { integration_name: integrationName, - integration_title: integrationTitle, // title gets re-initialized later in addRegistryPackage() + integration_title: integrationTitle, is_enabled: input.enabled, }; }); + + // Base package may not have policy template, so pull directly from `policy.package` if so + return [ + ...integrationInfos, + ...(policy.package + ? [ + { + integration_name: policy.package.name, + integration_title: policy.package.title, + is_enabled: true, // Always true if `policy.package` exists since this corresponds to the base package + }, + ] + : []), + ]; }; const normalizeString = (raw: string | null | undefined): string => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/route.ts index 7b904c282e1e4..559abe391f5a1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/fleet_integrations/api/get_installed_integrations/route.ts @@ -7,7 +7,6 @@ import type { Logger } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; -import { initPromisePool } from '../../../../../utils/promise_pool'; import { buildSiemResponse } from '../../../routes/utils'; import type { SecuritySolutionPluginRouter } from '../../../../../types'; @@ -15,8 +14,6 @@ import type { GetInstalledIntegrationsResponse } from '../../../../../../common/ import { GET_INSTALLED_INTEGRATIONS_URL } from '../../../../../../common/detection_engine/fleet_integrations'; import { createInstalledIntegrationSet } from './installed_integration_set'; -const MAX_CONCURRENT_REQUESTS_TO_PACKAGE_REGISTRY = 5; - /** * Returns an array of installed Fleet integrations and their packages. */ @@ -40,48 +37,18 @@ export const getInstalledIntegrationsRoute = ( const fleet = ctx.securitySolution.getInternalFleetServices(); const set = createInstalledIntegrationSet(); - const packagePolicies = await fleet.packagePolicy.list(fleet.internalReadonlySoClient, {}); + // Pulls all packages into memory just like the main fleet landing page + // No pagination support currently, so cannot batch this call + const allThePackages = await fleet.packages.getPackages(); + allThePackages.forEach((fleetPackage) => { + set.addPackage(fleetPackage); + }); + const packagePolicies = await fleet.packagePolicy.list(fleet.internalReadonlySoClient, {}); packagePolicies.items.forEach((policy) => { set.addPackagePolicy(policy); }); - const registryPackages = await initPromisePool({ - concurrency: MAX_CONCURRENT_REQUESTS_TO_PACKAGE_REGISTRY, - items: set.getPackages(), - executor: async (packageInfo) => { - const registryPackage = await fleet.packages.getPackage( - packageInfo.package_name, - packageInfo.package_version - ); - return registryPackage; - }, - }); - - if (registryPackages.errors.length > 0) { - const errors = registryPackages.errors.map(({ error, item }) => { - return { - error, - packageId: `${item.package_name}@${item.package_version}`, - }; - }); - - const packages = errors.map((e) => e.packageId).join(', '); - logger.error( - `Unable to retrieve installed integrations. Error fetching packages from registry: ${packages}.` - ); - - errors.forEach(({ error, packageId }) => { - const logMessage = `Error fetching package info from registry for ${packageId}`; - const logReason = error instanceof Error ? error.message : String(error); - logger.debug(`${logMessage}. ${logReason}`); - }); - } - - registryPackages.results.forEach(({ result }) => { - set.addRegistryPackage(result.packageInfo); - }); - const installedIntegrations = set.getIntegrations(); const body: GetInstalledIntegrationsResponse = { From afb251c624552024076ae75890de9c7d5f4458f0 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 28 Feb 2023 18:47:48 -0700 Subject: [PATCH 071/131] [embeddable] centralize should fetch embeddable observable logic (#151799) Fixes https://github.com/elastic/kibana/issues/151223 and https://github.com/elastic/kibana/issues/151128 PR does the following 1) creates `shouldFetch$` method that centralizes logic for checking when an embeddable should fetch. 2) updates Lens and Maps embeddable to use `shouldFetch$` 3) Adds unit tests for Maps embeddable to capture behavior of unique edge cases --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../diff_state/dashboard_diffing_functions.ts | 7 +- src/plugins/embeddable/public/index.ts | 2 + .../public/lib/filterable_embeddable/index.ts | 1 + .../filterable_embeddable/should_fetch.tsx | 44 +++ .../public/lib/filterable_embeddable/types.ts | 10 +- .../lens/public/embeddable/embeddable.tsx | 18 +- .../public/embeddable/map_embeddable.test.tsx | 290 ++++++++++++++++++ .../maps/public/embeddable/map_embeddable.tsx | 63 ++-- .../plugins/maps/public/embeddable/types.ts | 3 +- 9 files changed, 381 insertions(+), 57 deletions(-) create mode 100644 src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx create mode 100644 x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/integrations/diff_state/dashboard_diffing_functions.ts b/src/plugins/dashboard/public/dashboard_container/embeddable/integrations/diff_state/dashboard_diffing_functions.ts index c4886c55d976c..74f852df484e4 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/integrations/diff_state/dashboard_diffing_functions.ts +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/integrations/diff_state/dashboard_diffing_functions.ts @@ -15,6 +15,7 @@ import { isFilterPinned, onlyDisabledFiltersChanged, } from '@kbn/es-query'; +import { shouldRefreshFilterCompareOptions } from '@kbn/embeddable-plugin/public'; import { DashboardContainer } from '../../dashboard_container'; import { DashboardContainerByValueInput } from '../../../../../common'; @@ -117,12 +118,6 @@ export const unsavedChangesDiffingFunctions: DashboardDiffFunctions = { viewMode: () => false, // When compared view mode is always considered unequal so that it gets backed up. }; -const shouldRefreshFilterCompareOptions = { - ...COMPARE_ALL_OPTIONS, - // do not compare $state to avoid refreshing when filter is pinned/unpinned (which does not impact results) - state: false, -}; - export const shouldRefreshDiffingFunctions: DashboardDiffFunctions = { ...unsavedChangesDiffingFunctions, filters: ({ currentValue, lastValue }) => diff --git a/src/plugins/embeddable/public/index.ts b/src/plugins/embeddable/public/index.ts index ff41aa5503e33..18e5484b8fa4d 100644 --- a/src/plugins/embeddable/public/index.ts +++ b/src/plugins/embeddable/public/index.ts @@ -87,6 +87,8 @@ export { EmbeddableRenderer, useEmbeddableFactory, isFilterableEmbeddable, + shouldFetch$, + shouldRefreshFilterCompareOptions, } from './lib'; export { AttributeService, ATTRIBUTE_SERVICE_KEY } from './lib/attribute_service'; diff --git a/src/plugins/embeddable/public/lib/filterable_embeddable/index.ts b/src/plugins/embeddable/public/lib/filterable_embeddable/index.ts index ffa9470a34af4..0a01b6cab39df 100644 --- a/src/plugins/embeddable/public/lib/filterable_embeddable/index.ts +++ b/src/plugins/embeddable/public/lib/filterable_embeddable/index.ts @@ -8,3 +8,4 @@ export type { FilterableEmbeddable } from './types'; export { isFilterableEmbeddable } from './types'; +export { shouldFetch$, shouldRefreshFilterCompareOptions } from './should_fetch'; diff --git a/src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx b/src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx new file mode 100644 index 0000000000000..cf9cba103e011 --- /dev/null +++ b/src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx @@ -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 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 fastIsEqual from 'fast-deep-equal'; +import { Observable } from 'rxjs'; +import { map, distinctUntilChanged, skip, startWith } from 'rxjs/operators'; +import { COMPARE_ALL_OPTIONS, onlyDisabledFiltersChanged } from '@kbn/es-query'; +import type { FilterableEmbeddableInput } from './types'; + +export const shouldRefreshFilterCompareOptions = { + ...COMPARE_ALL_OPTIONS, + // do not compare $state to avoid refreshing when filter is pinned/unpinned (which does not impact results) + state: false, +}; + +export function shouldFetch$< + TFilterableEmbeddableInput extends FilterableEmbeddableInput = FilterableEmbeddableInput +>( + updated$: Observable, + getInput: () => TFilterableEmbeddableInput +): Observable { + return updated$.pipe(map(() => getInput())).pipe( + // wrapping distinctUntilChanged with startWith and skip to prime distinctUntilChanged with an initial input value. + startWith(getInput()), + distinctUntilChanged((a: TFilterableEmbeddableInput, b: TFilterableEmbeddableInput) => { + if ( + !fastIsEqual( + [a.searchSessionId, a.query, a.timeRange, a.timeslice], + [b.searchSessionId, b.query, b.timeRange, b.timeslice] + ) + ) { + return false; + } + + return onlyDisabledFiltersChanged(a.filters, b.filters, shouldRefreshFilterCompareOptions); + }), + skip(1) + ); +} diff --git a/src/plugins/embeddable/public/lib/filterable_embeddable/types.ts b/src/plugins/embeddable/public/lib/filterable_embeddable/types.ts index 8fe2b85e02ada..2b6182b1b95db 100644 --- a/src/plugins/embeddable/public/lib/filterable_embeddable/types.ts +++ b/src/plugins/embeddable/public/lib/filterable_embeddable/types.ts @@ -6,7 +6,15 @@ * Side Public License, v 1. */ -import { type AggregateQuery, type Filter, type Query } from '@kbn/es-query'; +import type { AggregateQuery, Filter, Query, TimeRange } from '@kbn/es-query'; +import { EmbeddableInput } from '../embeddables'; + +export type FilterableEmbeddableInput = EmbeddableInput & { + filters?: Filter[]; + query?: Query; + timeRange?: TimeRange; + timeslice?: [number, number]; +}; /** * All embeddables that implement this interface should support being filtered diff --git a/x-pack/plugins/lens/public/embeddable/embeddable.tsx b/x-pack/plugins/lens/public/embeddable/embeddable.tsx index 39bc64adef207..edb3d82b09e13 100644 --- a/x-pack/plugins/lens/public/embeddable/embeddable.tsx +++ b/x-pack/plugins/lens/public/embeddable/embeddable.tsx @@ -55,6 +55,7 @@ import { cellValueTrigger, CELL_VALUE_TRIGGER, type CellValueContext, + shouldFetch$, } from '@kbn/embeddable-plugin/public'; import type { Action, UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { DataViewsContract, DataView } from '@kbn/data-views-plugin/public'; @@ -501,20 +502,11 @@ export class Embeddable // Update search context and reload on changes related to search this.inputReloadSubscriptions.push( - this.getUpdated$() - .pipe(map(() => this.getInput())) - .pipe( - distinctUntilChanged((a, b) => - fastIsEqual( - [a.filters, a.query, a.timeRange, a.searchSessionId], - [b.filters, b.query, b.timeRange, b.searchSessionId] - ) - ), - skip(1) - ) - .subscribe(async (input) => { + shouldFetch$(this.getUpdated$(), () => this.getInput()).subscribe( + (input) => { this.onContainerStateChanged(input); - }) + } + ) ); } diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx new file mode 100644 index 0000000000000..bcb5aea3cca85 --- /dev/null +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.test.tsx @@ -0,0 +1,290 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { v4 as uuidv4 } from 'uuid'; +import { getControlledBy, MapEmbeddable } from './map_embeddable'; +import { buildExistsFilter, disableFilter, pinFilter, toggleFilterNegated } from '@kbn/es-query'; +import type { DataViewFieldBase, DataViewBase } from '@kbn/es-query'; +import { MapEmbeddableConfig, MapEmbeddableInput } from './types'; +import { MapSavedObjectAttributes } from '../../common/map_saved_object_type'; + +jest.mock('../kibana_services', () => { + return { + getHttp() { + return { + basePath: { + prepend: (url: string) => url, + }, + }; + }, + getMapsCapabilities() { + return { save: true }; + }, + getSearchService() { + return { + session: { + getSearchOptions() { + return undefined; + }, + }, + }; + }, + getShowMapsInspectorAdapter() { + return false; + }, + getTimeFilter() { + return { + getTime() { + return { from: 'now-7d', to: 'now' }; + }, + }; + }, + }; +}); + +jest.mock('../connected_components/map_container', () => { + return { + MapContainer: () => { + return
    mockLayerTOC
    ; + }, + }; +}); + +jest.mock('../routes/map_page', () => { + class MockSavedMap { + // eslint-disable-next-line @typescript-eslint/no-var-requires + private _store = require('../reducers/store').createMapStore(); + private _attributes: MapSavedObjectAttributes = { + title: 'myMap', + }; + + whenReady = async function () {}; + + getStore() { + return this._store; + } + getAttributes() { + return this._attributes; + } + getAutoFitToBounds() { + return true; + } + getSharingSavedObjectProps() { + return null; + } + } + return { SavedMap: MockSavedMap }; +}); + +function untilInitialized(mapEmbeddable: MapEmbeddable): Promise { + return new Promise((resolve) => { + // @ts-expect-error setInitializationFinished is protected but we are overriding it to know when embeddable is initialized + mapEmbeddable.setInitializationFinished = () => { + resolve(); + }; + }); +} + +function onNextTick(): Promise { + // wait one tick to give observables time to fire + return new Promise((resolve) => setTimeout(resolve, 0)); +} + +describe('shouldFetch$', () => { + test('should not fetch when search context does not change', async () => { + const mapEmbeddable = new MapEmbeddable( + {} as unknown as MapEmbeddableConfig, + { + id: 'map1', + } as unknown as MapEmbeddableInput + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + title: 'updated map title', + }); + + await onNextTick(); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + describe('on filters change', () => { + test('should fetch on filter change', async () => { + const existsFilter = buildExistsFilter( + { + name: 'myFieldName', + } as DataViewFieldBase, + { + id: 'myDataViewId', + } as DataViewBase + ); + const mapEmbeddable = new MapEmbeddable( + {} as unknown as MapEmbeddableConfig, + { + id: 'map1', + filters: [existsFilter], + } as unknown as MapEmbeddableInput + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + filters: [toggleFilterNegated(existsFilter)], + }); + + await onNextTick(); + + expect(fetchSpy).toHaveBeenCalled(); + }); + + test('should not fetch on disabled filter change', async () => { + const disabledFilter = disableFilter( + buildExistsFilter( + { + name: 'myFieldName', + } as DataViewFieldBase, + { + id: 'myDataViewId', + } as DataViewBase + ) + ); + const mapEmbeddable = new MapEmbeddable( + {} as unknown as MapEmbeddableConfig, + { + id: 'map1', + filters: [disabledFilter], + } as unknown as MapEmbeddableInput + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + filters: [toggleFilterNegated(disabledFilter)], + }); + + await onNextTick(); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + test('should not fetch when unpinned filter is pinned', async () => { + const unpinnedFilter = buildExistsFilter( + { + name: 'myFieldName', + } as DataViewFieldBase, + { + id: 'myDataViewId', + } as DataViewBase + ); + const mapEmbeddable = new MapEmbeddable( + {} as unknown as MapEmbeddableConfig, + { + id: 'map1', + filters: [unpinnedFilter], + } as unknown as MapEmbeddableInput + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + filters: [pinFilter(unpinnedFilter)], + }); + + await onNextTick(); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + + test('should not fetch on filter controlled by map embeddable change', async () => { + const embeddableId = 'map1'; + const filter = buildExistsFilter( + { + name: 'myFieldName', + } as DataViewFieldBase, + { + id: 'myDataViewId', + } as DataViewBase + ); + const controlledByFilter = { + ...filter, + meta: { + ...filter.meta, + controlledBy: getControlledBy(embeddableId), + }, + }; + const mapEmbeddable = new MapEmbeddable( + {} as unknown as MapEmbeddableConfig, + { + id: embeddableId, + filters: [controlledByFilter], + } as unknown as MapEmbeddableInput + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + filters: [toggleFilterNegated(controlledByFilter)], + }); + + await onNextTick(); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + }); + + describe('on searchSessionId change', () => { + test('should fetch when filterByMapExtent is false', async () => { + const mapEmbeddable = new MapEmbeddable( + {} as unknown as MapEmbeddableConfig, + { + id: 'map1', + filterByMapExtent: false, + } as unknown as MapEmbeddableInput + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + searchSessionId: uuidv4(), + }); + + await onNextTick(); + + expect(fetchSpy).toHaveBeenCalled(); + }); + + test('should not fetch when filterByMapExtent is true', async () => { + const mapEmbeddable = new MapEmbeddable( + {} as unknown as MapEmbeddableConfig, + { + id: 'map1', + filterByMapExtent: true, + } as unknown as MapEmbeddableInput + ); + await untilInitialized(mapEmbeddable); + + const fetchSpy = jest.spyOn(mapEmbeddable, '_dispatchSetQuery'); + + mapEmbeddable.updateInput({ + searchSessionId: uuidv4(), + }); + + await onNextTick(); + + expect(fetchSpy).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index 51b806cec5dce..41579d4f5375d 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -14,7 +14,7 @@ import { render, unmountComponentAtNode } from 'react-dom'; import { Subscription } from 'rxjs'; import { Unsubscribe } from 'redux'; import { EuiEmptyPrompt } from '@elastic/eui'; -import { type Filter, compareFilters, type TimeRange, type Query } from '@kbn/es-query'; +import { type Filter } from '@kbn/es-query'; import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { Embeddable, @@ -24,6 +24,7 @@ import { VALUE_CLICK_TRIGGER, omitGenericEmbeddableInput, FilterableEmbeddable, + shouldFetch$, } from '@kbn/embeddable-plugin/public'; import { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; import { APPLY_FILTER_TRIGGER } from '@kbn/data-plugin/public'; @@ -104,6 +105,10 @@ function getIsRestore(searchSessionId?: string) { return searchSessionOptions ? searchSessionOptions.isRestore : false; } +export function getControlledBy(id: string) { + return `mapEmbeddablePanel${id}`; +} + export class MapEmbeddable extends Embeddable implements ReferenceOrValueEmbeddable, FilterableEmbeddable @@ -114,15 +119,10 @@ export class MapEmbeddable private _isActive: boolean; private _savedMap: SavedMap; private _renderTooltipContent?: RenderToolTipContent; - private _subscription: Subscription; + private _subscriptions: Subscription[] = []; private _prevIsRestore: boolean = false; private _prevMapExtent?: MapExtent; - private _prevTimeRange?: TimeRange; - private _prevTimeslice?: [number, number]; - private _prevQuery?: Query; - private _prevFilters: Filter[] = []; private _prevSyncColors?: boolean; - private _prevSearchSessionId?: string; private _domNode?: HTMLElement; private _unsubscribeFromStore?: Unsubscribe; private _isInitialized = false; @@ -145,8 +145,8 @@ export class MapEmbeddable this._isActive = true; this._savedMap = new SavedMap({ mapEmbeddableInput: initialInput }); this._initializeSaveMap(); - this._subscription = this.getUpdated$().subscribe(() => this.onUpdate()); - this._controlledBy = `mapEmbeddablePanel${this.id}`; + this._subscriptions.push(this.getUpdated$().subscribe(() => this.onUpdate())); + this._controlledBy = getControlledBy(this.id); } public reportsEmbeddableLoad() { @@ -193,9 +193,20 @@ export class MapEmbeddable // Passing callback into redux store instead of regular pattern of getting redux state changes for performance reasons store.dispatch(setOnMapMove(this._propogateMapMovement)); - this._dispatchSetQuery({ - forceRefresh: false, - }); + this._dispatchSetQuery({ forceRefresh: false }); + this._subscriptions.push( + shouldFetch$(this.getUpdated$(), () => { + return { + ...this.getInput(), + filters: this._getInputFilters(), + searchSessionId: this._getSearchSessionId(), + }; + }).subscribe(() => { + this._dispatchSetQuery({ + forceRefresh: false, + }); + }) + ); const mapStateJSON = this._savedMap.getAttributes().mapStateJSON; if (mapStateJSON) { @@ -309,18 +320,6 @@ export class MapEmbeddable } onUpdate() { - if ( - !_.isEqual(this.input.timeRange, this._prevTimeRange) || - !_.isEqual(this.input.timeslice, this._prevTimeslice) || - !_.isEqual(this.input.query, this._prevQuery) || - !compareFilters(this._getFilters(), this._prevFilters) || - this._getSearchSessionId() !== this._prevSearchSessionId - ) { - this._dispatchSetQuery({ - forceRefresh: false, - }); - } - if (this.input.syncColors !== this._prevSyncColors) { this._dispatchSetChartsPaletteServiceGetColor(this.input.syncColors); } @@ -382,7 +381,7 @@ export class MapEmbeddable } }; - _getFilters() { + _getInputFilters() { return this.input.filters ? this.input.filters.filter( (filter) => !filter.meta.disabled && filter.meta.controlledBy !== this._controlledBy @@ -401,15 +400,9 @@ export class MapEmbeddable } _dispatchSetQuery({ forceRefresh }: { forceRefresh: boolean }) { - const filters = this._getFilters(); - this._prevTimeRange = this.input.timeRange; - this._prevTimeslice = this.input.timeslice; - this._prevQuery = this.input.query; - this._prevFilters = filters; - this._prevSearchSessionId = this._getSearchSessionId(); this._savedMap.getStore().dispatch( setQuery({ - filters, + filters: this._getInputFilters(), query: this.input.query, timeFilters: this.input.timeRange, timeslice: this.input.timeslice @@ -675,9 +668,9 @@ export class MapEmbeddable unmountComponentAtNode(this._domNode); } - if (this._subscription) { - this._subscription.unsubscribe(); - } + this._subscriptions.forEach((subscription) => { + subscription.unsubscribe(); + }); } reload() { diff --git a/x-pack/plugins/maps/public/embeddable/types.ts b/x-pack/plugins/maps/public/embeddable/types.ts index d024eee88ae6d..1d29a23ec44c5 100644 --- a/x-pack/plugins/maps/public/embeddable/types.ts +++ b/x-pack/plugins/maps/public/embeddable/types.ts @@ -5,7 +5,6 @@ * 2.0. */ -import type { Filter } from '@kbn/es-query'; import type { DataView } from '@kbn/data-plugin/common'; import { Embeddable, @@ -13,7 +12,7 @@ import { EmbeddableOutput, SavedObjectEmbeddableInput, } from '@kbn/embeddable-plugin/public'; -import type { Query, TimeRange } from '@kbn/es-query'; +import type { Filter, Query, TimeRange } from '@kbn/es-query'; import { MapCenterAndZoom, MapExtent, MapSettings } from '../../common/descriptor_types'; import { MapSavedObjectAttributes } from '../../common/map_saved_object_type'; From 5c0d3050baac3268f039ebcd66e151fcb734d845 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 1 Mar 2023 00:53:35 -0500 Subject: [PATCH 072/131] [api-docs] 2023-03-01 Daily api_docs build (#152416) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/263 --- 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.devdocs.json | 241 ++- api_docs/cloud_defend.mdx | 23 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.devdocs.json | 1738 +++++++++++++++-- api_docs/content_management.mdx | 19 +- 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.devdocs.json | 16 +- 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 | 8 +- api_docs/deprecations_by_plugin.mdx | 7 +- 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.devdocs.json | 94 + api_docs/embeddable.mdx | 4 +- 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 | 83 +- 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_as_data_utils.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 +- .../kbn_core_lifecycle_browser.devdocs.json | 8 - 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 +- ...ore_saved_objects_api_browser.devdocs.json | 48 - .../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.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_expandable_flyout.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_types.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.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.devdocs.json | 4 +- 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 | 14 +- 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.devdocs.json | 189 ++ api_docs/saved_objects.mdx | 4 +- 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.devdocs.json | 8 +- 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 +- 489 files changed, 2738 insertions(+), 716 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 0b8e633709e11..eb18c12c4c087 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-28 +date: 2023-03-01 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 923c752e5b8ee..457c9a044a4f5 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-28 +date: 2023-03-01 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 7570552b45d10..a27f9db685c13 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-28 +date: 2023-03-01 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 896d6335b1e48..f05c201efa2b2 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-28 +date: 2023-03-01 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 064ab9c52e28f..da0ef9b627636 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-28 +date: 2023-03-01 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 0d3965826809e..7fedab8ec9cf3 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-28 +date: 2023-03-01 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 e742fdf8dfc18..ec54a22e05b23 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-28 +date: 2023-03-01 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 32b1952cafdd8..22ee299448164 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-28 +date: 2023-03-01 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 1ed8c149e896c..ca31ede36cb35 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-28 +date: 2023-03-01 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 9d36327064aec..6dc629e35d2dc 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-28 +date: 2023-03-01 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 659b85d1d7b28..87cefa21ff0d3 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-28 +date: 2023-03-01 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 9f42c75ffb3e9..5dd10df91ff20 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-28 +date: 2023-03-01 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 3809b2b6a701f..84f7145933da0 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.devdocs.json b/api_docs/cloud_defend.devdocs.json index f155214541b73..40015d4edbbb1 100644 --- a/api_docs/cloud_defend.devdocs.json +++ b/api_docs/cloud_defend.devdocs.json @@ -2,10 +2,188 @@ "id": "cloudDefend", "client": { "classes": [], - "functions": [], - "interfaces": [], + "functions": [ + { + "parentPluginId": "cloudDefend", + "id": "def-public.getSecuritySolutionLink", + "type": "Function", + "tags": [], + "label": "getSecuritySolutionLink", + "description": [ + "\nGets the cloud_defend link properties of a Cloud Defend page for navigation in the security solution." + ], + "signature": [ + "(cloudDefendPage: \"policies\") => CloudDefendLinkItem" + ], + "path": "x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudDefend", + "id": "def-public.getSecuritySolutionLink.$1", + "type": "string", + "tags": [], + "label": "cloudDefendPage", + "description": [ + "the name of the cloud defend page." + ], + "signature": [ + "\"policies\"" + ], + "path": "x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "cloudDefend", + "id": "def-public.getSecuritySolutionNavTab", + "type": "Function", + "tags": [], + "label": "getSecuritySolutionNavTab", + "description": [ + "\nGets the link properties of a Cloud Defend page for navigation in the old security solution navigation." + ], + "signature": [ + "(cloudDefendPage: \"policies\", basePath: string) => CloudDefendNavTab" + ], + "path": "x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudDefend", + "id": "def-public.getSecuritySolutionNavTab.$1", + "type": "string", + "tags": [], + "label": "cloudDefendPage", + "description": [ + "the name of the cloud defend page." + ], + "signature": [ + "\"policies\"" + ], + "path": "x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "cloudDefend", + "id": "def-public.getSecuritySolutionNavTab.$2", + "type": "string", + "tags": [], + "label": "basePath", + "description": [ + "the base path for links." + ], + "signature": [ + "string" + ], + "path": "x-pack/plugins/cloud_defend/public/common/navigation/security_solution_links.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "cloudDefend", + "id": "def-public.CloudDefendSecuritySolutionContext", + "type": "Interface", + "tags": [], + "label": "CloudDefendSecuritySolutionContext", + "description": [], + "path": "x-pack/plugins/cloud_defend/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "cloudDefend", + "id": "def-public.CloudDefendSecuritySolutionContext.getFiltersGlobalComponent", + "type": "Function", + "tags": [], + "label": "getFiltersGlobalComponent", + "description": [ + "Gets the `FiltersGlobal` component for embedding a filter bar in the security solution application." + ], + "signature": [ + "() => React.ComponentType<{ children: React.ReactNode; }>" + ], + "path": "x-pack/plugins/cloud_defend/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "cloudDefend", + "id": "def-public.CloudDefendSecuritySolutionContext.getSpyRouteComponent", + "type": "Function", + "tags": [], + "label": "getSpyRouteComponent", + "description": [ + "Gets the `SpyRoute` component for navigation highlighting and breadcrumbs." + ], + "signature": [ + "() => React.ComponentType<{ pageName: \"cloud_defend-policies\"; state?: Record | undefined; }>" + ], + "path": "x-pack/plugins/cloud_defend/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], "enums": [], - "misc": [], + "misc": [ + { + "parentPluginId": "cloudDefend", + "id": "def-public.CLOUD_DEFEND_BASE_PATH", + "type": "string", + "tags": [], + "label": "CLOUD_DEFEND_BASE_PATH", + "description": [ + "The base path for all cloud defend pages." + ], + "signature": [ + "\"/cloud_defend\"" + ], + "path": "x-pack/plugins/cloud_defend/public/common/navigation/constants.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "cloudDefend", + "id": "def-public.CloudDefendPageId", + "type": "Type", + "tags": [], + "label": "CloudDefendPageId", + "description": [ + "\nAll the IDs for the cloud defend pages.\nThis needs to match the cloud defend page entries in `SecurityPageName` in `x-pack/plugins/security_solution/common/constants.ts`." + ], + "signature": [ + "\"cloud_defend-policies\"" + ], + "path": "x-pack/plugins/cloud_defend/public/common/navigation/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "objects": [], "setup": { "parentPluginId": "cloudDefend", @@ -13,7 +191,9 @@ "type": "Interface", "tags": [], "label": "CloudDefendPluginSetup", - "description": [], + "description": [ + "\ncloud_defend plugin types" + ], "path": "x-pack/plugins/cloud_defend/public/types.ts", "deprecated": false, "trackAdoption": false, @@ -31,7 +211,28 @@ "path": "x-pack/plugins/cloud_defend/public/types.ts", "deprecated": false, "trackAdoption": false, - "children": [], + "children": [ + { + "parentPluginId": "cloudDefend", + "id": "def-public.CloudDefendPluginStart.getCloudDefendRouter", + "type": "Function", + "tags": [], + "label": "getCloudDefendRouter", + "description": [ + "Gets the cloud defend router component for embedding in the security solution." + ], + "signature": [ + "() => React.ComponentType<", + "CloudDefendRouterProps", + ">" + ], + "path": "x-pack/plugins/cloud_defend/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + } + ], "lifecycle": "start", "initialIsOpen": true } @@ -42,7 +243,35 @@ "interfaces": [], "enums": [], "misc": [], - "objects": [] + "objects": [], + "setup": { + "parentPluginId": "cloudDefend", + "id": "def-server.CloudDefendPluginSetup", + "type": "Interface", + "tags": [], + "label": "CloudDefendPluginSetup", + "description": [], + "path": "x-pack/plugins/cloud_defend/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "cloudDefend", + "id": "def-server.CloudDefendPluginStart", + "type": "Interface", + "tags": [], + "label": "CloudDefendPluginStart", + "description": [], + "path": "x-pack/plugins/cloud_defend/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [], + "lifecycle": "start", + "initialIsOpen": true + } }, "common": { "classes": [], diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index da868144c7618..ffff93a8d3d3c 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,12 +8,12 @@ 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; -Defend for Containers +Defend for containers (D4C) Contact [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) for questions regarding this plugin. @@ -21,7 +21,7 @@ Contact [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 2 | 0 | 2 | 0 | +| 15 | 0 | 4 | 1 | ## Client @@ -31,3 +31,20 @@ Contact [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/ ### Start +### Functions + + +### Interfaces + + +### Consts, variables and types + + +## Server + +### Setup + + +### Start + + diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index 4bb90591915e0..58f563e56b4c0 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-28 +date: 2023-03-01 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 284069b14370d..9f76e7a05a1bd 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-28 +date: 2023-03-01 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 e8e668d7e0993..35ea8b7e28ddc 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-28 +date: 2023-03-01 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 896f476aaffb2..0b70a55a41998 100644 --- a/api_docs/content_management.devdocs.json +++ b/api_docs/content_management.devdocs.json @@ -1,11 +1,1050 @@ { "id": "contentManagement", "client": { - "classes": [], - "functions": [], - "interfaces": [], + "classes": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient", + "type": "Class", + "tags": [], + "label": "ContentClient", + "description": [], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.queryClient", + "type": "Object", + "tags": [], + "label": "queryClient", + "description": [], + "signature": [ + "QueryClient" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.queryOptionBuilder", + "type": "Object", + "tags": [], + "label": "queryOptionBuilder", + "description": [], + "signature": [ + "{ get: = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.GetIn", + "text": "GetIn" + }, + ", O = unknown>(input: I) => { queryKey: readonly [string, string]; queryFn: () => Promise; }; search: = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.SearchIn", + "text": "SearchIn" + }, + ", O = unknown>(input: I) => { queryKey: readonly [string, \"search\", unknown]; queryFn: () => Promise; }; }" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.Unnamed.$1", + "type": "Function", + "tags": [], + "label": "crudClientProvider", + "description": [], + "signature": [ + "(contentType: string) => ", + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.CrudClient", + "text": "CrudClient" + } + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [], + "signature": [ + " = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.GetIn", + "text": "GetIn" + }, + ", O = unknown>(input: I) => Promise" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.get.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.get$", + "type": "Function", + "tags": [], + "label": "get$", + "description": [], + "signature": [ + " = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.GetIn", + "text": "GetIn" + }, + ", O = unknown>(input: I) => ", + "Observable", + "<", + "QueryObserverResult", + ">" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.get$.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + ", O = unknown>(input: I) => Promise" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.create.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.update", + "type": "Function", + "tags": [], + "label": "update", + "description": [], + "signature": [ + ", O = unknown>(input: I) => Promise" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.update.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.delete", + "type": "Function", + "tags": [], + "label": "delete", + "description": [], + "signature": [ + ", O = unknown>(input: I) => Promise" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.delete.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.search", + "type": "Function", + "tags": [], + "label": "search", + "description": [], + "signature": [ + ", O = unknown>(input: I) => Promise" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.search.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.search$", + "type": "Function", + "tags": [], + "label": "search$", + "description": [], + "signature": [ + ", O = unknown>(input: I) => ", + "Observable", + "<", + "QueryObserverResult", + ">" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClient.search$.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClientProvider", + "type": "Function", + "tags": [], + "label": "ContentClientProvider", + "description": [], + "signature": [ + "({ contentClient, children, }: React.PropsWithChildren<{ contentClient: ", + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.ContentClient", + "text": "ContentClient" + }, + "; }>) => JSX.Element" + ], + "path": "src/plugins/content_management/public/content_client/content_client_context.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.ContentClientProvider.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n contentClient,\n children,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<{ contentClient: ", + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.ContentClient", + "text": "ContentClient" + }, + "; }>" + ], + "path": "src/plugins/content_management/public/content_client/content_client_context.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useContentClient", + "type": "Function", + "tags": [], + "label": "useContentClient", + "description": [], + "signature": [ + "() => ", + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.ContentClient", + "text": "ContentClient" + } + ], + "path": "src/plugins/content_management/public/content_client/content_client_context.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useCreateContentMutation", + "type": "Function", + "tags": [], + "label": "useCreateContentMutation", + "description": [], + "signature": [ + " = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.CreateIn", + "text": "CreateIn" + }, + ", O = unknown>() => ", + "UseMutationResult", + "" + ], + "path": "src/plugins/content_management/public/content_client/content_client_mutation_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useDeleteContentMutation", + "type": "Function", + "tags": [], + "label": "useDeleteContentMutation", + "description": [], + "signature": [ + " = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.DeleteIn", + "text": "DeleteIn" + }, + ", O = unknown>() => ", + "UseMutationResult", + "" + ], + "path": "src/plugins/content_management/public/content_client/content_client_mutation_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useGetContentQuery", + "type": "Function", + "tags": [], + "label": "useGetContentQuery", + "description": [ + "\n" + ], + "signature": [ + " = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.GetIn", + "text": "GetIn" + }, + ", O = unknown>(input: I, queryOptions?: ", + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.QueryOptions", + "text": "QueryOptions" + }, + " | undefined) => ", + "UseQueryResult", + "" + ], + "path": "src/plugins/content_management/public/content_client/content_client_query_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.useGetContentQuery.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [ + "- get content identifier like \"id\" and \"contentType\"" + ], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client_query_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useGetContentQuery.$2", + "type": "Object", + "tags": [], + "label": "queryOptions", + "description": [ + "- query options" + ], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.QueryOptions", + "text": "QueryOptions" + }, + " | undefined" + ], + "path": "src/plugins/content_management/public/content_client/content_client_query_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useSearchContentQuery", + "type": "Function", + "tags": [], + "label": "useSearchContentQuery", + "description": [ + "\n" + ], + "signature": [ + " = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.SearchIn", + "text": "SearchIn" + }, + ", O = unknown>(input: I, queryOptions?: ", + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.QueryOptions", + "text": "QueryOptions" + }, + " | undefined) => ", + "UseQueryResult", + "" + ], + "path": "src/plugins/content_management/public/content_client/content_client_query_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.useSearchContentQuery.$1", + "type": "Uncategorized", + "tags": [], + "label": "input", + "description": [ + "- get content identifier like \"id\" and \"contentType\"" + ], + "signature": [ + "I" + ], + "path": "src/plugins/content_management/public/content_client/content_client_query_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useSearchContentQuery.$2", + "type": "Object", + "tags": [], + "label": "queryOptions", + "description": [ + "- query options" + ], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.QueryOptions", + "text": "QueryOptions" + }, + " | undefined" + ], + "path": "src/plugins/content_management/public/content_client/content_client_query_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.useUpdateContentMutation", + "type": "Function", + "tags": [], + "label": "useUpdateContentMutation", + "description": [], + "signature": [ + " = ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.UpdateIn", + "text": "UpdateIn" + }, + ", O = unknown>() => ", + "UseMutationResult", + "" + ], + "path": "src/plugins/content_management/public/content_client/content_client_mutation_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient", + "type": "Interface", + "tags": [], + "label": "CrudClient", + "description": [], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [], + "signature": [ + "(input: ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.GetIn", + "text": "GetIn" + }, + ") => Promise" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.get.$1", + "type": "Object", + "tags": [], + "label": "input", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.GetIn", + "text": "GetIn" + }, + "" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [], + "signature": [ + "(input: ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.CreateIn", + "text": "CreateIn" + }, + ") => Promise" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.create.$1", + "type": "Object", + "tags": [], + "label": "input", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.CreateIn", + "text": "CreateIn" + }, + "" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.update", + "type": "Function", + "tags": [], + "label": "update", + "description": [], + "signature": [ + "(input: ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.UpdateIn", + "text": "UpdateIn" + }, + ") => Promise" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.update.$1", + "type": "Object", + "tags": [], + "label": "input", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.UpdateIn", + "text": "UpdateIn" + }, + "" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.delete", + "type": "Function", + "tags": [], + "label": "delete", + "description": [], + "signature": [ + "(input: ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.DeleteIn", + "text": "DeleteIn" + }, + ") => Promise" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.delete.$1", + "type": "Object", + "tags": [], + "label": "input", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.DeleteIn", + "text": "DeleteIn" + }, + "" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.search", + "type": "Function", + "tags": [], + "label": "search", + "description": [], + "signature": [ + "(input: ", + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.SearchIn", + "text": "SearchIn" + }, + ") => Promise" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.CrudClient.search.$1", + "type": "Object", + "tags": [], + "label": "input", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "common", + "docId": "kibContentManagementPluginApi", + "section": "def-common.SearchIn", + "text": "SearchIn" + }, + "" + ], + "path": "src/plugins/content_management/public/crud_client/crud_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], "enums": [], - "misc": [], + "misc": [ + { + "parentPluginId": "contentManagement", + "id": "def-public.QueryOptions", + "type": "Type", + "tags": [], + "label": "QueryOptions", + "description": [ + "\nExposed `useQuery` options" + ], + "signature": [ + "{ enabled?: boolean | undefined; }" + ], + "path": "src/plugins/content_management/public/content_client/content_client_query_hooks.tsx", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "objects": [], "start": { "parentPluginId": "contentManagement", @@ -26,7 +1065,13 @@ "label": "client", "description": [], "signature": [ - "ContentClient" + { + "pluginId": "contentManagement", + "scope": "public", + "docId": "kibContentManagementPluginApi", + "section": "def-public.ContentClient", + "text": "ContentClient" + } ], "path": "src/plugins/content_management/public/types.ts", "deprecated": false, @@ -91,7 +1136,541 @@ "server": { "classes": [], "functions": [], - "interfaces": [], + "interfaces": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage", + "type": "Interface", + "tags": [], + "label": "ContentStorage", + "description": [], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.get", + "type": "Function", + "tags": [], + "label": "get", + "description": [ + "Get a single item" + ], + "signature": [ + "(ctx: ", + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + }, + ", id: string, options: unknown) => Promise" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.get.$1", + "type": "Object", + "tags": [], + "label": "ctx", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + } + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.get.$2", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.get.$3", + "type": "Unknown", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "unknown" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.bulkGet", + "type": "Function", + "tags": [], + "label": "bulkGet", + "description": [ + "Get multiple items" + ], + "signature": [ + "(ctx: ", + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + }, + ", ids: string[], options: unknown) => Promise" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.bulkGet.$1", + "type": "Object", + "tags": [], + "label": "ctx", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + } + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.bulkGet.$2", + "type": "Array", + "tags": [], + "label": "ids", + "description": [], + "signature": [ + "string[]" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.bulkGet.$3", + "type": "Unknown", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "unknown" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.create", + "type": "Function", + "tags": [], + "label": "create", + "description": [ + "Create an item" + ], + "signature": [ + "(ctx: ", + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + }, + ", data: object, options: unknown) => Promise" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.create.$1", + "type": "Object", + "tags": [], + "label": "ctx", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + } + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.create.$2", + "type": "Uncategorized", + "tags": [], + "label": "data", + "description": [], + "signature": [ + "object" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.create.$3", + "type": "Unknown", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "unknown" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.update", + "type": "Function", + "tags": [], + "label": "update", + "description": [ + "Update an item" + ], + "signature": [ + "(ctx: ", + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + }, + ", id: string, data: object, options: unknown) => Promise" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.update.$1", + "type": "Object", + "tags": [], + "label": "ctx", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + } + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.update.$2", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.update.$3", + "type": "Uncategorized", + "tags": [], + "label": "data", + "description": [], + "signature": [ + "object" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.update.$4", + "type": "Unknown", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "unknown" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.delete", + "type": "Function", + "tags": [], + "label": "delete", + "description": [ + "Delete an item" + ], + "signature": [ + "(ctx: ", + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + }, + ", id: string, options: unknown) => Promise" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.delete.$1", + "type": "Object", + "tags": [], + "label": "ctx", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + } + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.delete.$2", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.delete.$3", + "type": "Unknown", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "unknown" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.search", + "type": "Function", + "tags": [], + "label": "search", + "description": [ + "Search items" + ], + "signature": [ + "(ctx: ", + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + }, + ", query: object, options: unknown) => Promise" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.search.$1", + "type": "Object", + "tags": [], + "label": "ctx", + "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.StorageContext", + "text": "StorageContext" + } + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.search.$2", + "type": "Uncategorized", + "tags": [], + "label": "query", + "description": [], + "signature": [ + "object" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.ContentStorage.search.$3", + "type": "Unknown", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "unknown" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "contentManagement", + "id": "def-server.StorageContext", + "type": "Interface", + "tags": [], + "label": "StorageContext", + "description": [ + "Context that is sent to all storage instance methods" + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "contentManagement", + "id": "def-server.StorageContext.requestHandlerContext", + "type": "Object", + "tags": [], + "label": "requestHandlerContext", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-request-handler-context-server", + "scope": "common", + "docId": "kibKbnCoreHttpRequestHandlerContextServerPluginApi", + "section": "def-common.RequestHandlerContext", + "text": "RequestHandlerContext" + } + ], + "path": "src/plugins/content_management/server/core/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], "enums": [], "misc": [], "objects": [], @@ -102,6 +1681,17 @@ "tags": [], "label": "ContentManagementServerSetup", "description": [], + "signature": [ + { + "pluginId": "contentManagement", + "scope": "server", + "docId": "kibContentManagementPluginApi", + "section": "def-server.ContentManagementServerSetup", + "text": "ContentManagementServerSetup" + }, + " extends ", + "CoreApi" + ], "path": "src/plugins/content_management/server/types.ts", "deprecated": false, "trackAdoption": false, @@ -598,7 +2188,7 @@ "label": "API_ENDPOINT", "description": [], "signature": [ - "\"/api/content_management\"" + "\"/api/content_management/rpc\"" ], "path": "src/plugins/content_management/common/constants.ts", "deprecated": false, @@ -651,140 +2241,6 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false - }, - { - "parentPluginId": "contentManagement", - "id": "def-common.schemas", - "type": "Object", - "tags": [], - "label": "schemas", - "description": [], - "path": "src/plugins/content_management/common/rpc/rpc.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "contentManagement", - "id": "def-common.schemas.get", - "type": "Object", - "tags": [], - "label": "get", - "description": [], - "signature": [ - { - "pluginId": "contentManagement", - "scope": "common", - "docId": "kibContentManagementPluginApi", - "section": "def-common.ProcedureSchemas", - "text": "ProcedureSchemas" - } - ], - "path": "src/plugins/content_management/common/rpc/rpc.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "contentManagement", - "id": "def-common.schemas.bulkGet", - "type": "Object", - "tags": [], - "label": "bulkGet", - "description": [], - "signature": [ - { - "pluginId": "contentManagement", - "scope": "common", - "docId": "kibContentManagementPluginApi", - "section": "def-common.ProcedureSchemas", - "text": "ProcedureSchemas" - } - ], - "path": "src/plugins/content_management/common/rpc/rpc.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "contentManagement", - "id": "def-common.schemas.create", - "type": "Object", - "tags": [], - "label": "create", - "description": [], - "signature": [ - { - "pluginId": "contentManagement", - "scope": "common", - "docId": "kibContentManagementPluginApi", - "section": "def-common.ProcedureSchemas", - "text": "ProcedureSchemas" - } - ], - "path": "src/plugins/content_management/common/rpc/rpc.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "contentManagement", - "id": "def-common.schemas.update", - "type": "Object", - "tags": [], - "label": "update", - "description": [], - "signature": [ - { - "pluginId": "contentManagement", - "scope": "common", - "docId": "kibContentManagementPluginApi", - "section": "def-common.ProcedureSchemas", - "text": "ProcedureSchemas" - } - ], - "path": "src/plugins/content_management/common/rpc/rpc.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "contentManagement", - "id": "def-common.schemas.delete", - "type": "Object", - "tags": [], - "label": "delete", - "description": [], - "signature": [ - { - "pluginId": "contentManagement", - "scope": "common", - "docId": "kibContentManagementPluginApi", - "section": "def-common.ProcedureSchemas", - "text": "ProcedureSchemas" - } - ], - "path": "src/plugins/content_management/common/rpc/rpc.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "contentManagement", - "id": "def-common.schemas.search", - "type": "Object", - "tags": [], - "label": "search", - "description": [], - "signature": [ - { - "pluginId": "contentManagement", - "scope": "common", - "docId": "kibContentManagementPluginApi", - "section": "def-common.ProcedureSchemas", - "text": "ProcedureSchemas" - } - ], - "path": "src/plugins/content_management/common/rpc/rpc.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false } ] } diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index 7b367b913e7e1..cf0ca55516578 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.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 | |-------------------|-----------|------------------------|-----------------| -| 46 | 0 | 46 | 3 | +| 110 | 0 | 96 | 3 | ## Client @@ -31,6 +31,18 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh ### Start +### Functions + + +### Classes + + +### Interfaces + + +### Consts, variables and types + + ## Server ### Setup @@ -39,6 +51,9 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh ### Start +### Interfaces + + ## Common ### Objects diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 92cff1862b49c..6f4c31dc6eb24 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-28 +date: 2023-03-01 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 00fd8abf5d551..217d118b83fd9 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-28 +date: 2023-03-01 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 6f7f587f59345..e4fbf40660418 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-28 +date: 2023-03-01 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 2c0a9a906d5d2..236ea0cd5f1ab 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index b2be9a6510899..7759142291791 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -13087,35 +13087,35 @@ }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" }, { "plugin": "expressionPartitionVis", - "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts" + "path": "src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts" } ] }, diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 1e4c203e60816..a8ff6c781ceec 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-28 +date: 2023-03-01 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 5480e56f276a5..18f87793f4dad 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-28 +date: 2023-03-01 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 c2771042aa461..20d3b7417d133 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-28 +date: 2023-03-01 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 75735009f549a..8401c7e3aa4c0 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-28 +date: 2023-03-01 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 f1e63364df52b..d8f6a38d7d905 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-28 +date: 2023-03-01 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 991044de8198b..6e13f172d3f04 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-28 +date: 2023-03-01 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 9d6efbcd459f6..2aaecd805c8ae 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-28 +date: 2023-03-01 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 4f8549bfe3799..e4096996b690e 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-28 +date: 2023-03-01 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 a4f0482e3da88..b17477ae78a6f 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -23,11 +23,11 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | home, data, esUiShared, spaces, savedObjectsManagement, fleet, observability, ml, apm, enterpriseSearch, indexLifecycleManagement, synthetics, upgradeAssistant, ux, kibanaOverview | - | | | encryptedSavedObjects, actions, data, ml, logstash, securitySolution, cloudChat | - | | | actions, ml, savedObjectsTagging, enterpriseSearch | - | -| | @kbn/core-plugins-browser-internal, @kbn/core-root-browser-internal, dataViews, home, data, savedObjects, unifiedSearch, presentationUtil, visualizations, dashboard, lens, discover, cases, fileUpload, maps, ml, infra, fleet, canvas, dashboardEnhanced, graph, monitoring, synthetics, transform, watcher, dataVisualizer, cloudSecurityPosture, securitySolution | - | +| | @kbn/core-plugins-browser-internal, @kbn/core-root-browser-internal, dataViews, home, data, savedObjects, unifiedSearch, presentationUtil, visualizations, dashboard, lens, discover, fileUpload, maps, ml, infra, fleet, canvas, dashboardEnhanced, graph, monitoring, synthetics, transform, watcher, dataVisualizer, cloudSecurityPosture, securitySolution | - | | | @kbn/core-saved-objects-browser, @kbn/core-saved-objects-browser-internal, @kbn/core, dataViews, home, savedObjects, savedSearch, visualizations, dashboard, lens, ml, canvas, graph, securitySolution, synthetics, watcher, visTypeTimeseries, @kbn/core-saved-objects-browser-mocks | - | -| | @kbn/core-saved-objects-browser-mocks, dataViews, savedObjects, presentationUtil, savedSearch, visualizations, dashboard, lens, cases, maps, ml, infra, cloudSecurityPosture, dashboardEnhanced, graph, securitySolution, synthetics, @kbn/core-saved-objects-browser-internal | - | +| | @kbn/core-saved-objects-browser-mocks, dataViews, savedObjects, presentationUtil, savedSearch, visualizations, dashboard, lens, maps, ml, infra, cloudSecurityPosture, dashboardEnhanced, graph, securitySolution, synthetics, @kbn/core-saved-objects-browser-internal | - | | | @kbn/core-saved-objects-browser-mocks, dataViews, savedObjects, visualizations, dashboard, ml, infra, cloudSecurityPosture, dashboardEnhanced, monitoring, synthetics, @kbn/core-saved-objects-browser-internal | - | -| | @kbn/core-saved-objects-browser-internal, @kbn/core, dataViews, savedObjects, embeddable, presentationUtil, visualizations, dashboard, lens, aiops, ml, cases, maps, dataVisualizer, infra, fleet, cloudSecurityPosture, dashboardEnhanced, graph, synthetics, securitySolution, @kbn/core-saved-objects-browser-mocks | - | +| | @kbn/core-saved-objects-browser-internal, @kbn/core, dataViews, savedObjects, embeddable, presentationUtil, visualizations, dashboard, lens, aiops, ml, maps, dataVisualizer, infra, fleet, cloudSecurityPosture, dashboardEnhanced, graph, synthetics, securitySolution, @kbn/core-saved-objects-browser-mocks | - | | | @kbn/core-lifecycle-browser-mocks, @kbn/core, ml, dashboard, dataViews, savedSearch, @kbn/core-plugins-browser-internal | - | | | @kbn/core, savedObjects, embeddable, visualizations, dashboard, fleet, infra, canvas, graph, ml, @kbn/core-saved-objects-common, @kbn/core-saved-objects-server, actions, alerting, savedSearch, enterpriseSearch, securitySolution, taskManager, @kbn/core-saved-objects-server-internal, @kbn/core-saved-objects-api-server | - | | | stackAlerts, alerting, securitySolution, inputControlVis | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 6a179d1e6e930..80094a42fb4ef 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -382,9 +382,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | ---------------|-----------|-----------| | | [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [find.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/operations/find.ts#:~:text=SavedObject), [find.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/operations/find.ts#:~:text=SavedObject), [find.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/operations/find.ts#:~:text=SavedObject), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObject), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObject), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObject)+ 8 more | - | | | [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObject), [find.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/operations/find.ts#:~:text=SavedObject), [find.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/operations/find.ts#:~:text=SavedObject), [find.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/operations/find.ts#:~:text=SavedObject), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObject), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObject), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObject)+ 44 more | - | -| | [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=savedObjects), [plugin.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx#:~:text=savedObjects) | - | -| | [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=find) | - | -| | [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject), [saved_objects_finder.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx#:~:text=SimpleSavedObject)+ 1 more | - | | | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/common/ui/types.ts#:~:text=ResolvedSimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/common/ui/types.ts#:~:text=ResolvedSimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/common/ui/types.ts#:~:text=ResolvedSimpleSavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/common/ui/types.ts#:~:text=ResolvedSimpleSavedObject) | - | | | [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/attachment_framework/so_references.ts#:~:text=SavedObjectReference), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/attachment_framework/so_references.ts#:~:text=SavedObjectReference), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/attachment_framework/so_references.ts#:~:text=SavedObjectReference), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/attachment_framework/so_references.ts#:~:text=SavedObjectReference), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObjectReference), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObjectReference), [so_references.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/so_references.ts#:~:text=SavedObjectReference), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObjectReference), [test_utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/services/user_actions/test_utils.ts#:~:text=SavedObjectReference) | - | | | [cases.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/saved_object_types/cases.ts#:~:text=convertToMultiNamespaceTypeVersion), [configure.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/saved_object_types/configure.ts#:~:text=convertToMultiNamespaceTypeVersion), [comments.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/saved_object_types/comments.ts#:~:text=convertToMultiNamespaceTypeVersion), [user_actions.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/saved_object_types/user_actions.ts#:~:text=convertToMultiNamespaceTypeVersion), [connector_mappings.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/cases/server/saved_object_types/connector_mappings.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | @@ -628,7 +625,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats), [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats), [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats), [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats), [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats), [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats), [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats), [get_layers.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_layers.test.ts#:~:text=fieldFormats) | - | +| | [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats), [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats), [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats), [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats), [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats), [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats), [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats), [get_color.test.ts](https://github.com/elastic/kibana/tree/main/src/plugins/chart_expressions/expression_partition_vis/public/utils/layers/get_color.test.ts#:~:text=fieldFormats) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 729cc3299b1a5..83b680c45c6d5 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index c6ba017a7eea2..a5be54c3a993b 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-28 +date: 2023-03-01 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 928f2d7a7c7b2..68d7e71d19fcd 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-28 +date: 2023-03-01 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 e54cece7c8f15..207042f8c205a 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-28 +date: 2023-03-01 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 686c30001f9f2..997bebea4a967 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/embeddable.devdocs.json b/api_docs/embeddable.devdocs.json index 4ac29344dbe29..9c774d762c515 100644 --- a/api_docs/embeddable.devdocs.json +++ b/api_docs/embeddable.devdocs.json @@ -6250,6 +6250,59 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "embeddable", + "id": "def-public.shouldFetch$", + "type": "Function", + "tags": [], + "label": "shouldFetch$", + "description": [], + "signature": [ + "(updated$: ", + "Observable", + ", getInput: () => TFilterableEmbeddableInput) => ", + "Observable", + "" + ], + "path": "src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "embeddable", + "id": "def-public.shouldFetch$.$1", + "type": "Object", + "tags": [], + "label": "updated$", + "description": [], + "signature": [ + "Observable", + "" + ], + "path": "src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "embeddable", + "id": "def-public.shouldFetch$.$2", + "type": "Function", + "tags": [], + "label": "getInput", + "description": [], + "signature": [ + "() => TFilterableEmbeddableInput" + ], + "path": "src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "embeddable", "id": "def-public.useEmbeddableFactory", @@ -10711,6 +10764,47 @@ } ], "initialIsOpen": false + }, + { + "parentPluginId": "embeddable", + "id": "def-public.shouldRefreshFilterCompareOptions", + "type": "Object", + "tags": [], + "label": "shouldRefreshFilterCompareOptions", + "description": [], + "path": "src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "embeddable", + "id": "def-public.shouldRefreshFilterCompareOptions.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "embeddable", + "id": "def-public.shouldRefreshFilterCompareOptions.state", + "type": "boolean", + "tags": [], + "label": "state", + "description": [ + "// do not compare $state to avoid refreshing when filter is pinned/unpinned (which does not impact results)" + ], + "path": "src/plugins/embeddable/public/lib/filterable_embeddable/should_fetch.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false } ], "setup": { diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index e073454315134..7dbe14444d9f0 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.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 | |-------------------|-----------|------------------------|-----------------| -| 532 | 8 | 430 | 4 | +| 538 | 9 | 435 | 4 | ## Client diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 6932c93c6692c..83ae1d0c3da02 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-28 +date: 2023-03-01 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 eb2d18465b28d..bc81ba849ed3d 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-28 +date: 2023-03-01 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 b2441359f4430..bb071de249983 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-28 +date: 2023-03-01 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 2001eb24562a0..98c959696e829 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-28 +date: 2023-03-01 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 b8fda3d5517fc..9f01ece99d2d5 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-28 +date: 2023-03-01 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 dbada9b2dfca3..80a488bc472c6 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-28 +date: 2023-03-01 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 6622e021130e7..8c666366fc8d6 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-28 +date: 2023-03-01 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 8b15b75e8abbd..9fdec0dc8cb79 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-28 +date: 2023-03-01 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 908f94186daf1..ec04a0683a4f1 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-28 +date: 2023-03-01 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 3765e915e81df..d7b940077fb77 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-28 +date: 2023-03-01 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 654925d8dc2ce..a619d11728ba2 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-28 +date: 2023-03-01 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 668becba901ef..30bec93fff3c6 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-28 +date: 2023-03-01 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 b0dc76f0b6f76..eeec105f003cc 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-28 +date: 2023-03-01 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 fd80d1a9b4784..0908cbf569b2b 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-28 +date: 2023-03-01 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 cc220ea04321b..a826b9492c3ea 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-28 +date: 2023-03-01 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 fee9dda3d70c3..56f581eff2739 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-28 +date: 2023-03-01 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 bf5da43e550bc..c3ec86cf5b9a8 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-28 +date: 2023-03-01 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 b982d403d0459..215621e2f70de 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-28 +date: 2023-03-01 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 6a3d62bd53b91..9ca0c092ed412 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-28 +date: 2023-03-01 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 5fa1a549697f1..3cd9a6d0a8187 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-28 +date: 2023-03-01 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 d8ac383049b86..60074a15c73e2 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-28 +date: 2023-03-01 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 c48d1e9a662a6..728d3f0f26f7a 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-28 +date: 2023-03-01 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 8e93da50c1e5a..c4e44c06c233e 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-28 +date: 2023-03-01 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 681850c64b442..aec2d7668382f 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-28 +date: 2023-03-01 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 da7e5cf17aa8b..0c7c522d8cd52 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-28 +date: 2023-03-01 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 6b022a38b7bd6..df2aca4d29022 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -5625,7 +5625,8 @@ "docId": "kibSpacesPluginApi", "section": "def-server.SpacesPluginStart", "text": "SpacesPluginStart" - } + }, + " | undefined" ], "path": "x-pack/plugins/fleet/server/plugin.ts", "deprecated": false, @@ -6029,6 +6030,86 @@ ], "returnComment": [] }, + { + "parentPluginId": "fleet", + "id": "def-server.PackageClient.getPackages", + "type": "Function", + "tags": [], + "label": "getPackages", + "description": [], + "signature": [ + "(params?: { excludeInstallStatus?: false | undefined; category?: string | undefined; prerelease?: false | undefined; } | undefined) => Promise<", + { + "pluginId": "fleet", + "scope": "common", + "docId": "kibFleetPluginApi", + "section": "def-common.PackageList", + "text": "PackageList" + }, + ">" + ], + "path": "x-pack/plugins/fleet/server/services/epm/package_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.PackageClient.getPackages.$1", + "type": "Object", + "tags": [], + "label": "params", + "description": [], + "path": "x-pack/plugins/fleet/server/services/epm/package_service.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "fleet", + "id": "def-server.PackageClient.getPackages.$1.excludeInstallStatus", + "type": "boolean", + "tags": [], + "label": "excludeInstallStatus", + "description": [], + "signature": [ + "false | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/epm/package_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackageClient.getPackages.$1.category", + "type": "string", + "tags": [], + "label": "category", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/epm/package_service.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "fleet", + "id": "def-server.PackageClient.getPackages.$1.prerelease", + "type": "boolean", + "tags": [], + "label": "prerelease", + "description": [], + "signature": [ + "false | undefined" + ], + "path": "x-pack/plugins/fleet/server/services/epm/package_service.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "returnComment": [] + }, { "parentPluginId": "fleet", "id": "def-server.PackageClient.reinstallEsAssets", diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index e605c7ee935e0..12c56be0b77ba 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-28 +date: 2023-03-01 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 | |-------------------|-----------|------------------------|-----------------| -| 1089 | 3 | 984 | 27 | +| 1094 | 3 | 989 | 27 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 4cd3f5543c815..5d9f0fa08839e 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-28 +date: 2023-03-01 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 ccd8dc54f268d..c5c5a26a41c68 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-28 +date: 2023-03-01 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 6e9c53480fdae..707ae9a95aac6 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-28 +date: 2023-03-01 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 fa1b8a61ad548..6e42d9a770f91 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-28 +date: 2023-03-01 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 bb61d5ca51b3f..dfeb32bb9975d 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-28 +date: 2023-03-01 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 5dc3493807348..d3a18506f2bce 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-28 +date: 2023-03-01 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 1bce234957b6d..8a11e37afd294 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-28 +date: 2023-03-01 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 894e811cb6f8f..adf41779fff68 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-28 +date: 2023-03-01 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 d575dd2ad8d69..efcd3b891dbc6 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-28 +date: 2023-03-01 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 6daa5009ec5ce..d1da2608b6daa 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-28 +date: 2023-03-01 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 938b5bd49c8b0..7e21ddd11bfd1 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-28 +date: 2023-03-01 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 15a61db6deb96..12024f602f215 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-28 +date: 2023-03-01 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 317fbd1e1da7c..94b33154d07b0 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 992e51d5ca374..8c6a728b96826 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2023-02-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 0182fb114a71d..e19c88b434998 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-28 +date: 2023-03-01 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 9684fb67be844..a561d8cd44c93 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-28 +date: 2023-03-01 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 1ba2bd42b6394..6c9c67c02e850 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-28 +date: 2023-03-01 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 6d48a60192c3c..50a6c08fa198b 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-28 +date: 2023-03-01 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 b4a362286f94b..e9998ea2c1028 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-28 +date: 2023-03-01 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 6cc59522d9f39..8eaf4e8926976 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-28 +date: 2023-03-01 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 004b9f13a4dee..cef0978935b54 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-28 +date: 2023-03-01 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 a0ab0a9f8c901..6b9fb907ac953 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-28 +date: 2023-03-01 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 10fe54398cb26..ed07b9e5fa4c8 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-28 +date: 2023-03-01 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 2513fff6c64fd..0649db4100861 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-28 +date: 2023-03-01 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 72c107abb92cb..58f1ad8f586fc 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-28 +date: 2023-03-01 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 49e481e6ae3f9..ceb84d0bca94c 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-28 +date: 2023-03-01 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 368f913d5c27e..1aecaa5c2de78 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-28 +date: 2023-03-01 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 c74cd3217452b..08bdd99ee670e 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-28 +date: 2023-03-01 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 c793d1c5a5c10..83573b77a2ea3 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-28 +date: 2023-03-01 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 4daaf41d72959..5d002c32c79c1 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-28 +date: 2023-03-01 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 dccd9a9031be5..08e14a926934e 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-28 +date: 2023-03-01 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 eab94ac6595e4..cf1d231ea3a8a 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-28 +date: 2023-03-01 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 07ae40b17946c..4927891257687 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-28 +date: 2023-03-01 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 73a06511196e7..d5477842f3195 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-28 +date: 2023-03-01 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 3787f059786a8..f108522506807 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-28 +date: 2023-03-01 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 2178f170966fc..79106555bf1b3 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-28 +date: 2023-03-01 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 09a047af41856..c60be8d19bbc4 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-28 +date: 2023-03-01 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 620e35d139390..1d3df732a5c52 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-28 +date: 2023-03-01 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 e28a6f5f0959e..e9c939110219b 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-28 +date: 2023-03-01 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 d3c4cd303f272..7cb770f30088b 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-28 +date: 2023-03-01 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 7d646114fb442..502f68f9bafc6 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-28 +date: 2023-03-01 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 2172cd92ee114..24dd88818d012 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-28 +date: 2023-03-01 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 a7f6b6fb80369..19be442f12401 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-28 +date: 2023-03-01 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 fe9deb4b585ac..3cf223d811a50 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-28 +date: 2023-03-01 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 38fb24b930ca7..15c50b14ddbcc 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-28 +date: 2023-03-01 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 432774cbff830..949d647c0fb4e 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-28 +date: 2023-03-01 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 9c3b01c84d7de..423d3d61683c8 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-28 +date: 2023-03-01 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 c142aabd9a321..611a4afcf75de 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-28 +date: 2023-03-01 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 f868c799f5928..304c873831fd4 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-28 +date: 2023-03-01 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 6f8e2526177fa..25efcb0bb8a3a 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-28 +date: 2023-03-01 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 8f4d90f1df324..892c8c76b89b1 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-28 +date: 2023-03-01 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 b0c74a42b25ac..fd8b79f885895 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-28 +date: 2023-03-01 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 f194c2065f746..d4b49e2544472 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-28 +date: 2023-03-01 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 7ddaa26562b22..52e6b016b9574 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-28 +date: 2023-03-01 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 27b03ed3a1a21..ef0f271766eb3 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-28 +date: 2023-03-01 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 aa9b5e329e9e8..6f270b901e057 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-28 +date: 2023-03-01 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 26dbd86f7ff30..56dd0c4a1e434 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-28 +date: 2023-03-01 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 50a40e42e8f38..b2aeca83bc43c 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-28 +date: 2023-03-01 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 b8f1c44efe947..365cb851bbd98 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-28 +date: 2023-03-01 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 2ebce3e9b4460..9cc170403d766 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-28 +date: 2023-03-01 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 0093670745c9d..588562c1397a9 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-28 +date: 2023-03-01 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 2d97c57d5a937..d298d07536f0e 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-28 +date: 2023-03-01 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 f6998d9b6f6bd..06c64391d23da 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-28 +date: 2023-03-01 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 a5164a238b129..5093d5f89d334 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-28 +date: 2023-03-01 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 40a0b78ba18ea..284888ef0efa2 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-28 +date: 2023-03-01 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 9adcd8599792f..897aca49852db 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-28 +date: 2023-03-01 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 3c464b4c79406..c728f1c726c88 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-28 +date: 2023-03-01 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 3065855251657..3bf75aeb93ca0 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-28 +date: 2023-03-01 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 8ec8f5a3543ce..f39bbcfc2e829 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-28 +date: 2023-03-01 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 347beed689407..8e0adfa179bd7 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-28 +date: 2023-03-01 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 85b0225e69aea..4fe374fa41898 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-28 +date: 2023-03-01 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 6f6646157d997..2a0d3f8cdcfdc 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-28 +date: 2023-03-01 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 f94be732c56bb..0cb7943689f4c 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-28 +date: 2023-03-01 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 1e6dddce80d5a..afbe971181a21 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-28 +date: 2023-03-01 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 04072fdc8bbfe..45246eee42da7 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-28 +date: 2023-03-01 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 95222a6ac1824..b4333d4f00a98 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-28 +date: 2023-03-01 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 0f1e4720014ac..945ab8c314633 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-28 +date: 2023-03-01 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 c497ffb4366d2..2ded9a267e91e 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-28 +date: 2023-03-01 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 fb218b43f4269..9611a707c6dc6 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-28 +date: 2023-03-01 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 0d095d6f7c53d..1aea29fbe68a7 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-28 +date: 2023-03-01 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 e2ea45eb55375..58be39da715ec 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-28 +date: 2023-03-01 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 bb0d0cc31bead..30091366a1a87 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-28 +date: 2023-03-01 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 2cee9209cdbef..54a70b26db85c 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-28 +date: 2023-03-01 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 7a30a0bed12ef..50d2412b58338 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-28 +date: 2023-03-01 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 b815a71f4dea4..efeac69f19104 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-28 +date: 2023-03-01 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 24e0983a06988..d96d09fa696bd 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-28 +date: 2023-03-01 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 8940205ac39e7..057a636ae9fe1 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-28 +date: 2023-03-01 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 09cf5a04b533b..05f8ec97e7a28 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-28 +date: 2023-03-01 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 a89837fea7fa1..22b6049591aa8 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-28 +date: 2023-03-01 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 32bca8361a9f2..aea775f4fbbf8 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-28 +date: 2023-03-01 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 dd94662c3b9a4..1bd54e9d84665 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-28 +date: 2023-03-01 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 c2260e5150dd2..d18ea0eb5556b 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-28 +date: 2023-03-01 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 5035a999507ef..f4cf588a1fd8b 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-28 +date: 2023-03-01 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 32c3f93a2147d..5a758ea2d6657 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-28 +date: 2023-03-01 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 9e817bea42692..c0c4118d6aff2 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-28 +date: 2023-03-01 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 38992012702e3..c794d34a2c2ed 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-28 +date: 2023-03-01 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 997277de0992c..d9d062fae9ca7 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-28 +date: 2023-03-01 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 590a32f7b6804..65e0ad45dffbe 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-28 +date: 2023-03-01 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 0a2e946d0ef46..4acd4a82dab31 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-28 +date: 2023-03-01 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 6b4a94c7a65c0..f0f05e7622c07 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-28 +date: 2023-03-01 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 9a009a36d14b0..0408099e8cc8c 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-28 +date: 2023-03-01 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 b71faf9a8d6ce..d0dfa1fd74e5e 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-28 +date: 2023-03-01 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 dcbda996bb75e..85dfa7ad743be 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-28 +date: 2023-03-01 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 62c46d3b36627..22496bc87fb99 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-28 +date: 2023-03-01 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 198ef483d2837..b4cad3b542bd7 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-28 +date: 2023-03-01 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 7f339abb6cb8a..3fc2357f914eb 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-28 +date: 2023-03-01 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 8c04ac064bebe..7ac2f6b11f718 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-28 +date: 2023-03-01 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 82dea39db37f3..f1e3e2fd849bd 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-28 +date: 2023-03-01 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 c7f2baee7037c..85fd6e03831da 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-28 +date: 2023-03-01 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 5c962b28d9886..aa21951eb20b1 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-28 +date: 2023-03-01 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 cce44307af439..ed909df42d85d 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-28 +date: 2023-03-01 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 b7547349d8917..25e80d604cfcf 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-28 +date: 2023-03-01 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 d65a953512a37..4baa71f0f02b1 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-28 +date: 2023-03-01 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 96aadf2d16be1..389b11f7db33c 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-28 +date: 2023-03-01 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 489443cba0e0b..89701f27f330d 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-28 +date: 2023-03-01 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 f50069c3f3d4a..a89aa6d00bb67 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-28 +date: 2023-03-01 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 d634637079eca..5ebbce42719eb 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-28 +date: 2023-03-01 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 ef3c68b517d8c..289f2bdc2d395 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-28 +date: 2023-03-01 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 8b3b165d647b1..fafb8cc5d0390 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-28 +date: 2023-03-01 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 46b7c178fcc81..f53885b8e9dac 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-28 +date: 2023-03-01 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 67f4789cf12a7..1eadd9211d2bc 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-28 +date: 2023-03-01 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 4b3c13625ec7b..54085404b5a38 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-28 +date: 2023-03-01 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 ea11c4da9c361..c572a6fa7b685 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-28 +date: 2023-03-01 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.devdocs.json b/api_docs/kbn_core_lifecycle_browser.devdocs.json index 92a9bfa433892..4f364f01dd84f 100644 --- a/api_docs/kbn_core_lifecycle_browser.devdocs.json +++ b/api_docs/kbn_core_lifecycle_browser.devdocs.json @@ -677,10 +677,6 @@ "plugin": "discover", "path": "src/plugins/discover/public/application/main/discover_main_route.tsx" }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, { "plugin": "fileUpload", "path": "x-pack/plugins/file_upload/public/kibana_services.ts" @@ -833,10 +829,6 @@ "plugin": "visualizations", "path": "src/plugins/visualizations/public/visualize_app/components/visualize_listing.tsx" }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/plugin.tsx" - }, { "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx" diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 3f09d5bddec53..aedc842ef153f 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-28 +date: 2023-03-01 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 8c504dfc42433..75b29d3494e6c 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-28 +date: 2023-03-01 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 6e1ad00dc2109..1a706abe318b6 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-28 +date: 2023-03-01 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 8866307025a39..bbfd13ed51049 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-28 +date: 2023-03-01 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 f8f39b499356f..136c12c56ac4b 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-28 +date: 2023-03-01 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 546977f0811d0..4ecb58cdd9906 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-28 +date: 2023-03-01 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 0b0c961bc0b74..144ae1d9d1e8c 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-28 +date: 2023-03-01 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 0e38ee4bee9cb..517f631ad858f 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-28 +date: 2023-03-01 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 477dc6dcfbfae..e943f5e00a460 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-28 +date: 2023-03-01 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 16858dd741c08..fd538cc9343ac 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-28 +date: 2023-03-01 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 cd7556995b5b1..8e2b9d0a15b1e 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-28 +date: 2023-03-01 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 a1e3c4bcf55e3..853a3c1e872d7 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-28 +date: 2023-03-01 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 b4382c5f92369..d5aee4c7654e0 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-28 +date: 2023-03-01 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 5301a90c90b28..24332a70fa701 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-28 +date: 2023-03-01 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 4f6bf040660eb..30db9430b487d 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-28 +date: 2023-03-01 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 972b3c1597f3c..492b442149946 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-28 +date: 2023-03-01 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 965ec4d1acd3e..f7b33406a3820 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-28 +date: 2023-03-01 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 ba8bd02cacbc1..feb9dc2ab14ec 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-28 +date: 2023-03-01 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 fa35561e301dc..c3932ab62690f 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-28 +date: 2023-03-01 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 1401f5adcf067..9ed261b31e520 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-28 +date: 2023-03-01 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 ab530789c88d6..53901c99c26eb 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-28 +date: 2023-03-01 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 67fbc659c9ed1..7ef2add6594c3 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-28 +date: 2023-03-01 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 f4a4ac81b9b4e..c5b2275067509 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-28 +date: 2023-03-01 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 19a6cecb35764..91222ce58d1f3 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-28 +date: 2023-03-01 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 a75e5e40ce83b..9f893da6f4cdb 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-28 +date: 2023-03-01 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 5ca8c83b6ce61..ac6c24d330cd0 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-28 +date: 2023-03-01 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 2f22103dbf192..c77bdc341cbae 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-28 +date: 2023-03-01 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 3c4c88afbd8a5..ea41b943c5e51 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-28 +date: 2023-03-01 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 94fbe3c381272..26c8e4e5cd2c1 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-28 +date: 2023-03-01 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 4bb4a6293a868..d2a828db81119 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-28 +date: 2023-03-01 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 f5f81a45db236..2d0cf533be77e 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-28 +date: 2023-03-01 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 aa0d29f8cd612..da0ab5e88b51e 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-28 +date: 2023-03-01 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 ca6bc8c89dbf2..a7a23df24f99c 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-28 +date: 2023-03-01 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 d33764a007ee1..14d1c29129edb 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-28 +date: 2023-03-01 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.devdocs.json b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json index 47616ddb798b9..a7830aa795a0b 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json @@ -2243,10 +2243,6 @@ "plugin": "lens", "path": "x-pack/plugins/lens/public/persistence/saved_objects_utils/find_object_by_title.ts" }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx" @@ -4000,50 +3996,6 @@ "plugin": "ml", "path": "x-pack/plugins/ml/common/types/kibana.ts" }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, - { - "plugin": "cases", - "path": "x-pack/plugins/cases/public/components/markdown_editor/plugins/lens/saved_objects_finder.tsx" - }, { "plugin": "maps", "path": "x-pack/plugins/maps/public/maps_vis_type_alias.ts" diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 9925c7d54e924..b234e165f5193 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-28 +date: 2023-03-01 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 371aec9bdd901..5ac110837d25a 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-28 +date: 2023-03-01 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 52030b02bde3d..a7883f71673c9 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-28 +date: 2023-03-01 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 297fa858fc441..6744441152126 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-28 +date: 2023-03-01 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 5b47d36f7b4e3..f9423495a45b7 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-28 +date: 2023-03-01 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 08754e85a429e..e40ed8d0d733d 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-28 +date: 2023-03-01 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 3f72172ad2624..688d1d555bec8 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-28 +date: 2023-03-01 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 0e2f1a128dc24..8713804799d47 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-28 +date: 2023-03-01 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 e9cad4c0e296d..48afdf8837561 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-28 +date: 2023-03-01 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 abdd31b8265e9..a335192d95087 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-28 +date: 2023-03-01 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 e2eacb6b852ff..3f22fd666b55c 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-28 +date: 2023-03-01 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 c386a8bac46dd..539a0fc832619 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-28 +date: 2023-03-01 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 da9c17cfc84dc..9b334a940a32d 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-28 +date: 2023-03-01 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 b7ff18bfe97db..29cea64b32846 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-28 +date: 2023-03-01 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 3708f94bd910b..eca87703c355f 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-28 +date: 2023-03-01 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 2af33c48974f5..c8af573bde495 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-28 +date: 2023-03-01 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 c63669a42313a..7c2ec8a7a83ee 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-28 +date: 2023-03-01 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 30311cf44a269..e210a1228ec23 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-28 +date: 2023-03-01 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 c4464831aa731..a11aed7d32d8a 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-28 +date: 2023-03-01 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 967ee90a4af04..d7e00df6fc8a3 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-28 +date: 2023-03-01 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 36ab7c3c06d35..cb0d5036718ed 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-28 +date: 2023-03-01 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 294abb3b0c19a..0a96f49ffa4f6 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-28 +date: 2023-03-01 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 844f75cab333a..327e3a271a3dd 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-28 +date: 2023-03-01 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 5639a6c086857..c96e4fd0af6a1 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-28 +date: 2023-03-01 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 5c0b770e2c434..096a5cf9c010d 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-28 +date: 2023-03-01 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 d9e9ac63049ae..fb1f6004cad61 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-28 +date: 2023-03-01 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 d9fbb1ee32328..5bdb15b6bf91c 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-28 +date: 2023-03-01 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 a0448c7fa78bf..698eacb03771d 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-28 +date: 2023-03-01 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 04bfe87b1f780..54165d1e0c654 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-28 +date: 2023-03-01 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 1eb0414dd45c8..9ef8f2333fe52 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-28 +date: 2023-03-01 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 8c09095a3e3b5..4d0b8b852b174 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-28 +date: 2023-03-01 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 822f2d74702df..fc433f2993985 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-28 +date: 2023-03-01 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 28564e1638de5..60bdeaf388128 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-28 +date: 2023-03-01 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 14a983d39a21d..aba1f92ba7723 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-28 +date: 2023-03-01 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 e7e4dc709985f..a5e94c54239ea 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-28 +date: 2023-03-01 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 f1f131ca9ae40..7bb50d06aebc7 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-28 +date: 2023-03-01 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 322a944c92407..3c1d1da90502f 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-28 +date: 2023-03-01 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 972e4fea27a2b..db46d9394da82 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-28 +date: 2023-03-01 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 ad1a2af0c26dd..253d2892a934b 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-28 +date: 2023-03-01 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 7986cb3e189ac..da766dfd397e6 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-28 +date: 2023-03-01 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 948602f8b16ce..fd300908ba5ff 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-28 +date: 2023-03-01 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 a1939bcf16477..611326ca0ca1b 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-28 +date: 2023-03-01 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 3e6ba58a589e0..b67b17f6a2b76 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-28 +date: 2023-03-01 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 cd7c5ec1315f8..6b16b88b54504 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-28 +date: 2023-03-01 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 dc4e0302a3840..bcf02b08bbd13 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-28 +date: 2023-03-01 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 7701ace42bb65..9608ba018aa9b 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-28 +date: 2023-03-01 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 ee43d20b0961e..8ae612c0cd7cf 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-28 +date: 2023-03-01 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 3d9236ee8431d..a620da438f055 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-28 +date: 2023-03-01 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 a4503d762f0c2..6e9803ca19ca3 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-28 +date: 2023-03-01 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 690befe3cbb83..5c26c1f7ae912 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-28 +date: 2023-03-01 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 0399b4f8c746f..92321620ae072 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-28 +date: 2023-03-01 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 4657ed79be42d..86c05cddc426a 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-28 +date: 2023-03-01 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 bd5b4c146878d..833dce59d69af 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-28 +date: 2023-03-01 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 8fe18eca0bc56..b1052fab18d8a 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-28 +date: 2023-03-01 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 ba011e6bbf167..f2edd04564e87 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-28 +date: 2023-03-01 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 9421f34bd8b83..25691edd038ab 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-28 +date: 2023-03-01 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 fe513e762d0e9..a775b77d0c03b 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-28 +date: 2023-03-01 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 e0903de48be62..40d30548e2c75 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-28 +date: 2023-03-01 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 847febd25c24d..53f09c9a56f21 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-28 +date: 2023-03-01 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 d399dc95f270c..c755e7e49ec70 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 22fbc24cf88a1..8cd64f4bf5007 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2023-02-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index e6ea6c2915b92..882ddbccdafc2 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-28 +date: 2023-03-01 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 67f7f707c8648..9408b6512bfc6 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-28 +date: 2023-03-01 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 9ac919b0a22a4..7aa6edd01eaed 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-28 +date: 2023-03-01 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 938c566cab0ad..c96a7fec26b54 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-28 +date: 2023-03-01 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 15e3f4473cc4d..41402fb54e395 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-28 +date: 2023-03-01 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 d52887d5f386a..5892aaecb2692 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-28 +date: 2023-03-01 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 2f6f53b29bcc8..58903a768057d 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-28 +date: 2023-03-01 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 3c704dc1082d2..638f50b6e417a 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-28 +date: 2023-03-01 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 d2449d916ce71..f6f8c68a13a53 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-28 +date: 2023-03-01 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 2b2abfa098b6b..a89d578374865 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-28 +date: 2023-03-01 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 ccc93fbc3ff29..dcd9cecd5658a 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-28 +date: 2023-03-01 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 2c78806ed6e46..625e6d1fc8700 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-28 +date: 2023-03-01 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 72bd7cf1cb0f0..d724067993dff 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-28 +date: 2023-03-01 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 50d4412ff5b81..6d236d56a476c 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-28 +date: 2023-03-01 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 20a8be80b5c93..60f0704834cb7 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-28 +date: 2023-03-01 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 93621cf47e0aa..901358d2ad029 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-28 +date: 2023-03-01 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 d742be4326672..8be26edb38791 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-28 +date: 2023-03-01 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 610d8fc4a18f5..7cf30e73b07e4 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-28 +date: 2023-03-01 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 ff7cb5480240d..5b32cf0eab32b 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-28 +date: 2023-03-01 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 94f433a05f257..000ee3800cb54 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-28 +date: 2023-03-01 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 4e0fcbffc46f9..e0814e0c41bce 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-28 +date: 2023-03-01 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 4d5f32f707390..28ad3c57ee2b1 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-28 +date: 2023-03-01 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 6d92d1ead30b5..9e6c619a43f72 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-28 +date: 2023-03-01 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 7a15ccfa87ed5..2b6014f157459 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-28 +date: 2023-03-01 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 3a50b4adcfb53..82fb3b8156135 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-28 +date: 2023-03-01 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 dfeeb1510c9f7..e22d099c43982 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-28 +date: 2023-03-01 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 6874332a26f30..7106fef0d31ec 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-28 +date: 2023-03-01 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 6670e94eb4eee..da6012691ecbe 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-28 +date: 2023-03-01 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 bbd025fe1fa5a..e2ac91904af64 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-28 +date: 2023-03-01 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 c0554041a68a5..76e448217a11e 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-28 +date: 2023-03-01 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 be947c303ff24..1aaaba5d9d1b1 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-28 +date: 2023-03-01 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 12f3acbcf3dd9..b605bd7a7d0c1 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-28 +date: 2023-03-01 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 6a6b54987f4c0..b58e96af08251 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-28 +date: 2023-03-01 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 78a9557f3a8e2..0b3b1dcbb8d71 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-28 +date: 2023-03-01 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 796787cdff114..6b8831494e1fc 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-28 +date: 2023-03-01 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 4c2ced69cd354..fefd5513c3a89 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-28 +date: 2023-03-01 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 fcd4299d7dec6..0daafacb70363 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-28 +date: 2023-03-01 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 8735a6ebf7771..135064793ced7 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-28 +date: 2023-03-01 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 2fe0e395a926a..2e7737d3d09a9 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-28 +date: 2023-03-01 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 b42e4ff694c8e..1b0874efd96a0 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-28 +date: 2023-03-01 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 26651728d35af..e626443c3a86c 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-28 +date: 2023-03-01 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 97902ffe415b4..97cf561b76dbe 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-28 +date: 2023-03-01 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 90bce3b337ef4..bb83af20d577b 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-28 +date: 2023-03-01 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 ea301fcb7bf65..ed3fd24bf1ca0 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-28 +date: 2023-03-01 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 f027a5abaee44..09b2b34589146 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-28 +date: 2023-03-01 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 67b113801852c..50073a95415d4 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-28 +date: 2023-03-01 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 314a0e7da1a48..95ddbf97b66e6 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-28 +date: 2023-03-01 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 5a8bc014bed9c..f3b12dba64e8f 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-28 +date: 2023-03-01 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 5ee5d919296b0..8cfec1a146f1f 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-28 +date: 2023-03-01 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 bd64b1db81bfc..e2d46df9fa528 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-28 +date: 2023-03-01 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 85aceb9690e36..f65f4b5d15f06 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-28 +date: 2023-03-01 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 5bc067d5e6340..6db5d2665ed2d 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-28 +date: 2023-03-01 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 9864d4070a64f..4fa8e0495146f 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-28 +date: 2023-03-01 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 f2095245ff1ac..dcf633ba8463d 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-28 +date: 2023-03-01 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 5668e299d77f0..24f4035a6e10f 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-28 +date: 2023-03-01 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 d8d0c9c9871d8..115cb421ce21e 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-28 +date: 2023-03-01 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 82a67efe6b38a..1bdb1d69ada89 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-28 +date: 2023-03-01 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 e0f50cd3efed4..666f7d64dc4c0 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-28 +date: 2023-03-01 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 cf55a63421c8d..10a5bd75e918e 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-28 +date: 2023-03-01 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 73199675135f7..4f279c8da7457 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-28 +date: 2023-03-01 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 d8cc6bdea546d..21c514be81803 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-28 +date: 2023-03-01 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 be04da8990108..30d9b478e5fb2 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-28 +date: 2023-03-01 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 b870995270f14..a9e0ce333f4ac 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-28 +date: 2023-03-01 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 e2f2fa7144b85..b75e7bd174f09 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-28 +date: 2023-03-01 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 733dda4175166..4608fd2d9fae0 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-28 +date: 2023-03-01 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 e58c594bf32bf..dbed2431570ba 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-28 +date: 2023-03-01 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 2269ceb340140..49369a523c57d 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-28 +date: 2023-03-01 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 8e47740cb12e6..de603c176f88d 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-28 +date: 2023-03-01 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 07e493a7cb81a..6dc92cb308995 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-28 +date: 2023-03-01 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 0c681b7541cb9..d18090ddcfca4 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-28 +date: 2023-03-01 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 606d8505db64b..d5438a3b81231 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-28 +date: 2023-03-01 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 168ffd1305214..e7f87b3faead1 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-28 +date: 2023-03-01 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 df21948c046b9..bbc60b7b0930e 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-28 +date: 2023-03-01 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 17a197cb50150..f96d798bfdd70 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-28 +date: 2023-03-01 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 4ca4a262aac6c..6ed126b1f0272 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-28 +date: 2023-03-01 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 3bd8feca9cc06..5059a2104ecc6 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-28 +date: 2023-03-01 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 14e59f85eee8b..99a891466643c 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-28 +date: 2023-03-01 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 f4abb5309c5e6..48e442ff2f4a7 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-28 +date: 2023-03-01 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_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index 8209bfcad95c2..9f65fa210e7b8 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2023-02-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 4a7f1131800f7..017044bc1816e 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-28 +date: 2023-03-01 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 b769fcf74f510..da482330aa69f 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-28 +date: 2023-03-01 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 3e784736600a3..dc7da9fdb3de0 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-28 +date: 2023-03-01 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 fc64a58d11b5b..34433ea142c25 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-28 +date: 2023-03-01 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 940644b3fd59d..16a4ef53f43e0 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-28 +date: 2023-03-01 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 b202f9f8b5870..cb9dd8a0c0be1 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-28 +date: 2023-03-01 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 156eda71b5a8c..5e2e601161b23 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-28 +date: 2023-03-01 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 0d4be286761e6..c721d2065548a 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-28 +date: 2023-03-01 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 c6f9fc4ef80ad..32ccb3a824df6 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-28 +date: 2023-03-01 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 ae05839415131..449c6cb561b0f 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-28 +date: 2023-03-01 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 250d876c321e9..8eb428b3ec1fd 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-28 +date: 2023-03-01 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 724150dcc5ac9..34cc61f2f9c01 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-28 +date: 2023-03-01 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 7b1b989ba6cee..08aab682ce2e6 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-28 +date: 2023-03-01 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 5727efb34acce..9824ac22ba569 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-28 +date: 2023-03-01 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 c6af6866069c9..cd3c126d99beb 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-28 +date: 2023-03-01 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 87981ddb8777f..f2df637ff592a 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-28 +date: 2023-03-01 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 5ba46cdcc14c4..93dda125813c3 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-28 +date: 2023-03-01 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 4a0264e15a351..2c0e1ec941c8d 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-28 +date: 2023-03-01 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 f8f479bc82736..7e2646fc8085a 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-28 +date: 2023-03-01 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 e71df0240d9a5..2ace684381a43 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-28 +date: 2023-03-01 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 c36b9563d5951..440066e3a8f57 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-28 +date: 2023-03-01 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 060a5d9374f60..43b990ab9241f 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-28 +date: 2023-03-01 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 7aa8b9b5469d8..3ba733b898ba3 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-28 +date: 2023-03-01 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 302f019a118b7..62b3ffd910949 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-28 +date: 2023-03-01 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 61068adab2e94..2a7caa471b5ac 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-28 +date: 2023-03-01 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 a725bef6d1dfd..77215eafe5c39 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-28 +date: 2023-03-01 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 26d5e2905557a..e123f38fb650b 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-28 +date: 2023-03-01 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 ebaaad4fe200f..7f6765e55f8e4 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-28 +date: 2023-03-01 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 bc9fc88083646..a4a057a5ea50a 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-28 +date: 2023-03-01 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 8d729da1d0c13..a957674b23663 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-28 +date: 2023-03-01 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 af4f7c3196754..9614a088a92bc 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-28 +date: 2023-03-01 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 8ac5a54019cef..c557e001a9435 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-28 +date: 2023-03-01 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 2e5cc062ce04f..25eee237600e1 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-28 +date: 2023-03-01 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 01ab9a6025585..78ba4948685c5 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-28 +date: 2023-03-01 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 b87d54e58c159..91cffd61ed3b8 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-28 +date: 2023-03-01 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 db3164da08dfc..6a1a4743dd6e1 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-28 +date: 2023-03-01 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 458810012a7dd..aac73b858246a 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-28 +date: 2023-03-01 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 d58966203073b..4cc5120445c02 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-28 +date: 2023-03-01 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 68704c5518edc..fca8308cff965 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-28 +date: 2023-03-01 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 125fb40ae685c..f6106da7ed875 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-28 +date: 2023-03-01 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 6e7c773415301..75a89bba49dca 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-28 +date: 2023-03-01 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 0c7dc2488443a..3ee6c92133ecc 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-28 +date: 2023-03-01 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 0d8c7b33c2bd6..a5833d2b4ed60 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-28 +date: 2023-03-01 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 3e65e26219007..85dc335a2bb76 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-28 +date: 2023-03-01 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 f78260916241f..5dc2d050d2806 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-28 +date: 2023-03-01 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 6c0fb6464f98c..f70f533212865 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-28 +date: 2023-03-01 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 f381f2825210d..3bed1d4269ddb 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-28 +date: 2023-03-01 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 58fc492ba9ca5..12c873652a03e 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-28 +date: 2023-03-01 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 dccc3f7001254..01d10baf1cbed 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-28 +date: 2023-03-01 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 c33e99100df1e..3dc29d6ecc73e 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-28 +date: 2023-03-01 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 23daa345f6194..c7783c09c4649 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-28 +date: 2023-03-01 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 2d3259a4aee8b..34117f2a0bb22 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-28 +date: 2023-03-01 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 3038e387bec74..65eee5cb0ce4a 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-28 +date: 2023-03-01 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 d25c61a4e27c9..98ebb58f999bb 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-28 +date: 2023-03-01 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 d416a6004f48d..94eda5f98ae19 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.devdocs.json b/api_docs/maps.devdocs.json index a9dd4fac83ae3..f5b00c78a59d4 100644 --- a/api_docs/maps.devdocs.json +++ b/api_docs/maps.devdocs.json @@ -834,10 +834,10 @@ }, { "parentPluginId": "maps", - "id": "def-public.MapEmbeddable._getFilters", + "id": "def-public.MapEmbeddable._getInputFilters", "type": "Function", "tags": [], - "label": "_getFilters", + "label": "_getInputFilters", "description": [], "signature": [ "() => ", diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index 18079ba00f748..f296fc984ecb4 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-28 +date: 2023-03-01 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 4615a906a1cd7..f44c6c7d72960 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-28 +date: 2023-03-01 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 fbfca60b77b13..063b121d33eeb 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-28 +date: 2023-03-01 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 886a4ce48b798..07694d7e71b2f 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-28 +date: 2023-03-01 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 f3b8c8d1be282..60334ad4da977 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-28 +date: 2023-03-01 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 838c42c39dbb3..d64152c39b1ac 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-28 +date: 2023-03-01 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 75c74e1f19b30..cb334f1c5899e 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-28 +date: 2023-03-01 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 4d8591294aa9b..cb927160b6980 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-28 +date: 2023-03-01 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 d2af532fc95fe..1e474ec45c730 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-28 +date: 2023-03-01 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 04f0bad23e2fe..876a6cbb91d01 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-28 +date: 2023-03-01 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 e548f18220b28..0258630d7d754 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 67775 | 514 | 58529 | 1233 | +| 67878 | 515 | 58596 | 1234 | ## Plugin Directory @@ -40,14 +40,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 41 | 0 | 11 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | Chat available on Elastic Cloud deployments for quicker assistance. | 1 | 0 | 0 | 0 | | | [@elastic/platform-onboarding](https://github.com/orgs/elastic/teams/platform-onboarding) | Static migration page where self-managed users can see text/copy about migrating to Elastic Cloud | 8 | 1 | 8 | 1 | -| | [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) | Defend for Containers | 2 | 0 | 2 | 0 | +| | [@elastic/sec-cloudnative-integrations](https://github.com/orgs/elastic/teams/sec-cloudnative-integrations) | Defend for containers (D4C) | 15 | 0 | 4 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | Provides the necessary APIs to implement A/B testing scenarios, fetching the variations in configuration and reporting back metrics to track conversion rates of the experiments. | 12 | 0 | 0 | 0 | | cloudFullStory | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | When Kibana runs on Elastic Cloud, this plugin registers FullStory as a shipper for telemetry. | 0 | 0 | 0 | 0 | | cloudGainsight | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | When Kibana runs on Elastic Cloud, this plugin registers Gainsight as a shipper for telemetry. | 0 | 0 | 0 | 0 | | 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 | 46 | 0 | 46 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | Content management app | 110 | 0 | 96 | 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 | 272 | 0 | 268 | 11 | | 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 | @@ -64,7 +64,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 97 | 0 | 78 | 7 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | APIs used to assess the quality of data in Elasticsearch indexes | 2 | 0 | 0 | 0 | -| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 532 | 8 | 430 | 4 | +| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 538 | 9 | 435 | 4 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides encryption and decryption utilities for saved objects containing sensitive information. | 51 | 0 | 44 | 0 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Adds dashboards for discovering and managing Enterprise Search products. | 9 | 0 | 9 | 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. | 214 | 0 | 10 | 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) | - | 1089 | 3 | 984 | 27 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1094 | 3 | 989 | 27 | | ftrApis | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 0 | 0 | 0 | 0 | @@ -137,7 +137,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 21 | 0 | 21 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 258 | 0 | 229 | 13 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 24 | 0 | 19 | 2 | -| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 216 | 2 | 175 | 5 | +| | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 231 | 2 | 180 | 5 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 39 | 0 | 39 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 154 | 0 | 140 | 2 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 79 | 0 | 73 | 3 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index a9ab65763cfb8..10ac8aa29d17d 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-28 +date: 2023-03-01 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 deba0cdcd5085..78f89c756ed1a 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-28 +date: 2023-03-01 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 aaab91fddc3a4..dad0ad96c8b86 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-28 +date: 2023-03-01 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 9dfd0ab61a8ae..a163a3e5f48fc 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-28 +date: 2023-03-01 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 a2a19da59470f..695c084c67059 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-28 +date: 2023-03-01 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 bafd718f19619..546f47c4b94aa 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-28 +date: 2023-03-01 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 ff7aa047cba3c..300fb2cc0fa5e 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.devdocs.json b/api_docs/saved_objects.devdocs.json index b6ed1819ec684..366db1e5b33db 100644 --- a/api_docs/saved_objects.devdocs.json +++ b/api_docs/saved_objects.devdocs.json @@ -499,6 +499,195 @@ "trackAdoption": false } ] + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFormRowProps", + "type": "Function", + "tags": [], + "label": "euiFormRowProps", + "description": [], + "signature": [ + "Requireable", + "" + ], + "path": "src/plugins/saved_objects/public/finder/saved_object_finder.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFormRowProps.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "{ [key: string]: any; }" + ], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFormRowProps.$2", + "type": "string", + "tags": [], + "label": "propName", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFormRowProps.$3", + "type": "string", + "tags": [], + "label": "componentName", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFormRowProps.$4", + "type": "string", + "tags": [], + "label": "location", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFormRowProps.$5", + "type": "string", + "tags": [], + "label": "propFullName", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFieldSearchProps", + "type": "Function", + "tags": [], + "label": "euiFieldSearchProps", + "description": [], + "signature": [ + "Requireable", + "" + ], + "path": "src/plugins/saved_objects/public/finder/saved_object_finder.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFieldSearchProps.$1", + "type": "Object", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "{ [key: string]: any; }" + ], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFieldSearchProps.$2", + "type": "string", + "tags": [], + "label": "propName", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFieldSearchProps.$3", + "type": "string", + "tags": [], + "label": "componentName", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFieldSearchProps.$4", + "type": "string", + "tags": [], + "label": "location", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.propTypes.euiFieldSearchProps.$5", + "type": "string", + "tags": [], + "label": "propFullName", + "description": [], + "path": "node_modules/@types/prop-types/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ] + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.defaultProps", + "type": "Object", + "tags": [], + "label": "defaultProps", + "description": [], + "path": "src/plugins/saved_objects/public/finder/saved_object_finder.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.defaultProps.euiFormRowProps", + "type": "Object", + "tags": [], + "label": "euiFormRowProps", + "description": [], + "path": "src/plugins/saved_objects/public/finder/saved_object_finder.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [] + }, + { + "parentPluginId": "savedObjects", + "id": "def-public.SavedObjectFinderUi.defaultProps.euiFieldSearchProps", + "type": "Object", + "tags": [], + "label": "euiFieldSearchProps", + "description": [], + "path": "src/plugins/saved_objects/public/finder/saved_object_finder.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [] } ] }, diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index 16d7f54784ed1..0e01a4ef5ae8f 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 216 | 2 | 175 | 5 | +| 231 | 2 | 180 | 5 | ## Client diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index ace1059c4bed5..367ab10b93f95 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-28 +date: 2023-03-01 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 6fd979ecdbb86..ab25f08c08353 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-28 +date: 2023-03-01 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 18541c12418b1..cf634e8bcf4d2 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-28 +date: 2023-03-01 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 442d516371a8d..58754d7347a9a 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-28 +date: 2023-03-01 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 2ddbf2b3f440a..d366a5659c2d0 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-28 +date: 2023-03-01 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 fbab93eac15de..f73392463bf85 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-28 +date: 2023-03-01 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 5a9f3c7f4a93e..5aeff28137085 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-28 +date: 2023-03-01 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 913ea2418a097..41a4f223df1c3 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-28 +date: 2023-03-01 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 eeced72ec06fe..888af88e4afd8 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-28 +date: 2023-03-01 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 597c0533242ca..8e622aa8c0fbe 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-28 +date: 2023-03-01 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 ce9b271f3639c..280a9087fffdc 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-28 +date: 2023-03-01 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 5ffe5a5072c6f..23bdf19710ba6 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-28 +date: 2023-03-01 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 f05bf8794e108..1887661117d27 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-28 +date: 2023-03-01 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 53063d23c2cc2..d6e565746caed 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-28 +date: 2023-03-01 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 7f1f52fa198db..74034e03d1606 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-28 +date: 2023-03-01 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 aa72caf8ee862..7fcd51007ee22 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-28 +date: 2023-03-01 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 ead6ab9d2fc06..25f3f0790c8e5 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-28 +date: 2023-03-01 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 bea30d56e7f3a..3b445eef5c9f8 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-28 +date: 2023-03-01 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 2eaa03df603b3..494d687861aef 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-28 +date: 2023-03-01 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 e445e28aa62ef..8c43e25170a8a 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-28 +date: 2023-03-01 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 14fe41c6b8535..f10c81a6c4bf9 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-28 +date: 2023-03-01 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 34740ef1b0b8a..dffa97af77387 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-28 +date: 2023-03-01 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 860c46a6aaca7..356e1f00b40fe 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-28 +date: 2023-03-01 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 2aab69671f429..25e1f7667b80f 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-28 +date: 2023-03-01 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 c8bbb58cd83b2..af0e4ad1fe0e4 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-28 +date: 2023-03-01 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 7aa3001fe08eb..237e122541d20 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-28 +date: 2023-03-01 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 6fe0b991d6fa1..53e998016795e 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-28 +date: 2023-03-01 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 11a20aaa28491..f9421f8e37385 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.devdocs.json b/api_docs/unified_search.devdocs.json index fb9811aaea206..d0f779daec6fb 100644 --- a/api_docs/unified_search.devdocs.json +++ b/api_docs/unified_search.devdocs.json @@ -377,7 +377,7 @@ "section": "def-common.Filter", "text": "Filter" }, - "[] | undefined; dataTestSubj?: string | undefined; indexPatterns?: ", + "[] | undefined; dataTestSubj?: string | undefined; isLoading?: boolean | undefined; indexPatterns?: ", { "pluginId": "dataViews", "scope": "common", @@ -385,7 +385,7 @@ "section": "def-common.DataView", "text": "DataView" }, - "[] | undefined; isDisabled?: boolean | undefined; isLoading?: boolean | undefined; timeHistory?: ", + "[] | undefined; isDisabled?: boolean | undefined; timeHistory?: ", { "pluginId": "data", "scope": "public", @@ -1937,9 +1937,9 @@ "Omit", ", \"options\" | \"onChange\" | \"selectedOptions\" | \"isLoading\" | \"onSearchChange\">, \"placeholder\"> & Required, \"options\" | \"onChange\" | \"isLoading\" | \"selectedOptions\" | \"onSearchChange\">, \"placeholder\"> & Required, \"options\" | \"onChange\" | \"selectedOptions\" | \"isLoading\" | \"onSearchChange\">, \"placeholder\">> & { onChange: (indexPatternId?: string | undefined) => void; indexPatternId: string; onNoIndexPatterns?: (() => void) | undefined; }" + ", \"options\" | \"onChange\" | \"isLoading\" | \"selectedOptions\" | \"onSearchChange\">, \"placeholder\">> & { onChange: (indexPatternId?: string | undefined) => void; indexPatternId: string; onNoIndexPatterns?: (() => void) | undefined; }" ], "path": "src/plugins/unified_search/public/index_pattern_select/index_pattern_select.tsx", "deprecated": false, diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 64d361f9de3a8..e253a60f45f2f 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-28 +date: 2023-03-01 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 938acbf44f8f1..7b878eafe283c 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-28 +date: 2023-03-01 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 be3bbff9a466a..823876429efb1 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-28 +date: 2023-03-01 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 36998816dcddc..109cbf52dc582 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-28 +date: 2023-03-01 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 185f5306ae783..638a8ea29d98e 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-28 +date: 2023-03-01 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 2bb4750747ba0..c31cbd33a8736 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-28 +date: 2023-03-01 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 8d9aea5b9f72e..f5b9dd978f640 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-28 +date: 2023-03-01 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 efe160318e302..dbc51a17cbeba 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-28 +date: 2023-03-01 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 42329bc9873f6..12355ae17b46c 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-28 +date: 2023-03-01 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 a4d39e8071188..a84e017f11233 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-28 +date: 2023-03-01 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 c7663b05e89cc..87a277e1cd1db 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-28 +date: 2023-03-01 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 62b8b9db10bc0..c1fc09b66945d 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-28 +date: 2023-03-01 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 2cccc99f502f2..234f683885678 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-28 +date: 2023-03-01 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 813c2d581da8f..9584fabdc1fb9 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-28 +date: 2023-03-01 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 7530cbec77b3f..cfaf9011a3e5e 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-28 +date: 2023-03-01 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 638333102c3b5..b7661a706bb18 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-28 +date: 2023-03-01 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 60b34d14619fbbeeef477b3b7a9894a0562772dd Mon Sep 17 00:00:00 2001 From: Shahzad Date: Wed, 1 Mar 2023 07:36:38 +0100 Subject: [PATCH 073/131] [Synthetics] Private location , remove deprecated api usage (#151996) Co-authored-by: Dominique Clarke --- .../common/constants/synthetics/rest_api.ts | 1 + .../hooks/use_locations_api.test.tsx | 121 ++++++++---------- .../hooks/use_locations_api.ts | 30 ++--- .../private_locations/location_form.tsx | 44 ++++++- .../manage_private_locations.tsx | 1 - .../private_locations/policy_name.tsx | 15 ++- .../components/settings/route_config.ts | 35 +++-- .../synthetics/state/private_locations/api.ts | 38 ++---- .../apps/synthetics/state/root_effect.ts | 1 - .../plugins/synthetics/server/routes/index.ts | 6 + .../private_locations/add_private_location.ts | 56 ++++++++ .../delete_private_location.ts | 43 +++++++ .../get_private_locations.ts | 38 ++++++ 13 files changed, 293 insertions(+), 136 deletions(-) create mode 100644 x-pack/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts create mode 100644 x-pack/plugins/synthetics/server/routes/settings/private_locations/delete_private_location.ts create mode 100644 x-pack/plugins/synthetics/server/routes/settings/private_locations/get_private_locations.ts diff --git a/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts b/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts index 7e61e0a9e5e08..a0875d9df4977 100644 --- a/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts +++ b/x-pack/plugins/synthetics/common/constants/synthetics/rest_api.ts @@ -12,6 +12,7 @@ export enum SYNTHETICS_API_URLS { OVERVIEW_STATUS = `/internal/synthetics/overview_status`, INDEX_SIZE = `/internal/synthetics/index_size`, PARAMS = `/synthetics/params`, + PRIVATE_LOCATIONS = `/synthetics/private_locations`, SYNC_GLOBAL_PARAMS = `/synthetics/sync_global_params`, ENABLE_DEFAULT_ALERTING = `/synthetics/enable_default_alerting`, JOURNEY = `/internal/synthetics/journey/{checkGroup}`, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx index e343e9faf1aec..ce80c7d97e71e 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx @@ -5,12 +5,25 @@ * 2.0. */ -import { renderHook } from '@testing-library/react-hooks'; -import { defaultCore, WrappedHelper } from '../../../../utils/testing'; - +import { renderHook, act } from '@testing-library/react-hooks'; +import { WrappedHelper } from '../../../../utils/testing'; +import { getServiceLocations } from '../../../../state/service_locations'; +import { setAddingNewPrivateLocation } from '../../../../state/private_locations'; import { useLocationsAPI } from './use_locations_api'; +import * as locationAPI from '../../../../state/private_locations/api'; +import * as reduxHooks from 'react-redux'; describe('useLocationsAPI', () => { + const dispatch = jest.fn(); + const addAPI = jest.spyOn(locationAPI, 'addSyntheticsPrivateLocations').mockResolvedValue({ + locations: [], + }); + const deletedAPI = jest.spyOn(locationAPI, 'deleteSyntheticsPrivateLocations').mockResolvedValue({ + locations: [], + }); + const getAPI = jest.spyOn(locationAPI, 'getSyntheticsPrivateLocations'); + jest.spyOn(reduxHooks, 'useDispatch').mockReturnValue(dispatch); + it('returns expected results', () => { const { result } = renderHook(() => useLocationsAPI(), { wrapper: WrappedHelper, @@ -22,20 +35,15 @@ describe('useLocationsAPI', () => { privateLocations: [], }) ); - expect(defaultCore.savedObjects.client.get).toHaveBeenCalledWith( - 'synthetics-privates-locations', - 'synthetics-privates-locations-singleton' - ); + expect(getAPI).toHaveBeenCalledTimes(1); }); - defaultCore.savedObjects.client.get = jest.fn().mockReturnValue({ - attributes: { - locations: [ - { - id: 'Test', - agentPolicyId: 'testPolicy', - }, - ], - }, + jest.spyOn(locationAPI, 'getSyntheticsPrivateLocations').mockResolvedValue({ + locations: [ + { + id: 'Test', + agentPolicyId: 'testPolicy', + } as any, + ], }); it('returns expected results after data', async () => { const { result, waitForNextUpdate } = renderHook(() => useLocationsAPI(), { @@ -71,77 +79,50 @@ describe('useLocationsAPI', () => { await waitForNextUpdate(); - result.current.onSubmit({ - id: 'new', - agentPolicyId: 'newPolicy', - label: 'new', + act(() => { + result.current.onSubmit({ + id: 'new', + agentPolicyId: 'newPolicy', + label: 'new', + concurrentMonitors: 1, + geo: { + lat: 0, + lon: 0, + }, + }); + }); + + await waitForNextUpdate(); + + expect(addAPI).toHaveBeenCalledWith({ concurrentMonitors: 1, + id: 'newPolicy', geo: { lat: 0, lon: 0, }, + label: 'new', + agentPolicyId: 'newPolicy', }); - - await waitForNextUpdate(); - - expect(defaultCore.savedObjects.client.create).toHaveBeenCalledWith( - 'synthetics-privates-locations', - { - locations: [ - { id: 'Test', agentPolicyId: 'testPolicy' }, - { - concurrentMonitors: 1, - id: 'newPolicy', - geo: { - lat: 0, - lon: 0, - }, - label: 'new', - agentPolicyId: 'newPolicy', - }, - ], - }, - { id: 'synthetics-privates-locations-singleton', overwrite: true } - ); + expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); + expect(dispatch).toBeCalledWith(getServiceLocations()); }); it('deletes location on delete', async () => { - defaultCore.savedObjects.client.get = jest.fn().mockReturnValue({ - attributes: { - locations: [ - { - id: 'Test', - agentPolicyId: 'testPolicy', - }, - { - id: 'Test1', - agentPolicyId: 'testPolicy1', - }, - ], - }, - }); - const { result, waitForNextUpdate } = renderHook(() => useLocationsAPI(), { wrapper: WrappedHelper, }); await waitForNextUpdate(); - result.current.onDelete('Test'); + act(() => { + result.current.onDelete('Test'); + }); await waitForNextUpdate(); - expect(defaultCore.savedObjects.client.create).toHaveBeenLastCalledWith( - 'synthetics-privates-locations', - { - locations: [ - { - id: 'Test1', - agentPolicyId: 'testPolicy1', - }, - ], - }, - { id: 'synthetics-privates-locations-singleton', overwrite: true } - ); + expect(deletedAPI).toHaveBeenLastCalledWith('Test'); + expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); + expect(dispatch).toBeCalledWith(getServiceLocations()); }); }); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts index 6b35e79152c87..8678328445a62 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts @@ -7,12 +7,13 @@ import { useFetcher } from '@kbn/observability-plugin/public'; import { useState } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useDispatch } from 'react-redux'; +import { getServiceLocations } from '../../../../state/service_locations'; import { setAddingNewPrivateLocation } from '../../../../state/private_locations'; import { + addSyntheticsPrivateLocations, + deleteSyntheticsPrivateLocations, getSyntheticsPrivateLocations, - setSyntheticsPrivateLocations, } from '../../../../state/private_locations/api'; import { PrivateLocation } from '../../../../../../../common/runtime_types'; @@ -21,31 +22,29 @@ export const useLocationsAPI = () => { const [deleteId, setDeleteId] = useState(); const [privateLocations, setPrivateLocations] = useState([]); - const { savedObjects } = useKibana().services; - const dispatch = useDispatch(); const setIsAddingNew = (val: boolean) => dispatch(setAddingNewPrivateLocation(val)); const { loading: fetchLoading } = useFetcher(async () => { - const result = await getSyntheticsPrivateLocations(savedObjects?.client!); - setPrivateLocations(result); + const result = await getSyntheticsPrivateLocations(); + setPrivateLocations(result.locations); return result; }, []); const { loading: saveLoading } = useFetcher(async () => { - if (privateLocations && formData) { - const existingLocations = privateLocations.filter((loc) => loc.id !== formData.agentPolicyId); - - const result = await setSyntheticsPrivateLocations(savedObjects?.client!, { - locations: [...(existingLocations ?? []), { ...formData, id: formData.agentPolicyId }], + if (formData) { + const result = await addSyntheticsPrivateLocations({ + ...formData, + id: formData.agentPolicyId, }); setPrivateLocations(result.locations); setFormData(undefined); setIsAddingNew(false); + dispatch(getServiceLocations()); return result; } - }, [formData, privateLocations]); + }, [formData]); const onSubmit = (data: PrivateLocation) => { setFormData(data); @@ -57,14 +56,13 @@ export const useLocationsAPI = () => { const { loading: deleteLoading } = useFetcher(async () => { if (deleteId) { - const result = await setSyntheticsPrivateLocations(savedObjects?.client!, { - locations: (privateLocations ?? []).filter((loc) => loc.id !== deleteId), - }); + const result = await deleteSyntheticsPrivateLocations(deleteId); setPrivateLocations(result.locations); setDeleteId(undefined); + dispatch(getServiceLocations()); return result; } - }, [deleteId, privateLocations]); + }, [deleteId]); return { formData, diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx index 38bdac2592fb7..a001c503697b1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx @@ -33,8 +33,10 @@ export const LocationForm = ({ hasPermissions: boolean; }) => { const { data } = useSelector(selectAgentPolicies); - const { control, register } = useFormContext(); + const { control, register, watch } = useFormContext(); const { errors } = useFormState(); + const selectedPolicyId = watch('agentPolicyId'); + const selectedPolicy = data?.items.find((item) => item.id === selectedPolicyId); const tagsList = privateLocations.reduce((acc, item) => { const tags = item.tags || []; @@ -97,6 +99,39 @@ export const LocationForm = ({ }

    + + + {selectedPolicy?.agents === 0 && ( + +

    + { + + + + ), + }} + /> + } +

    +
    + )} ); @@ -109,6 +144,13 @@ export const AGENT_CALLOUT_TITLE = i18n.translate( } ); +export const AGENT_MISSING_CALLOUT_TITLE = i18n.translate( + 'xpack.synthetics.monitorManagement.agentMissingCallout.title', + { + defaultMessage: 'Selected agent policy has no agents', + } +); + export const LOCATION_NAME_LABEL = i18n.translate( 'xpack.synthetics.monitorManagement.locationName', { 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 dd140ffd3b3f5..e8246aa13221e 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 @@ -26,7 +26,6 @@ export const ManagePrivateLocations = () => { const dispatch = useDispatch(); const isAddingNew = useSelector(selectAddingNewPrivateLocation); - const setIsAddingNew = (val: boolean) => dispatch(setAddingNewPrivateLocation(val)); const { onSubmit, loading, privateLocations, onDelete, deleteLoading } = useLocationsAPI(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx index a1a4f586e63bf..2c44bc80fed36 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { EuiLink, EuiLoadingSpinner, EuiText, EuiTextColor } from '@elastic/eui'; +import { EuiBadge, EuiLink, EuiLoadingSpinner, EuiText, EuiTextColor } from '@elastic/eui'; import { useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { useSyntheticsSettingsContext } from '../../../contexts'; @@ -28,7 +28,7 @@ export const PolicyName = ({ agentPolicyId }: { agentPolicyId: string }) => { return ( - {canReadAgentPolicies && ( + {canReadAgentPolicies ? ( {policy ? ( @@ -40,7 +40,14 @@ export const PolicyName = ({ agentPolicyId }: { agentPolicyId: string }) => { )} + ) : ( + agentPolicyId )} +     + + {AGENTS_LABEL} + {policy?.agents} + ); }; @@ -48,3 +55,7 @@ export const PolicyName = ({ agentPolicyId }: { agentPolicyId: string }) => { const POLICY_IS_DELETED = i18n.translate('xpack.synthetics.monitorManagement.deletedPolicy', { defaultMessage: 'Policy is deleted', }); + +const AGENTS_LABEL = i18n.translate('xpack.synthetics.monitorManagement.agents', { + defaultMessage: 'Agents: ', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts index ee9b6c34bd8f9..51ddf14ee5f67 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/route_config.ts @@ -17,32 +17,27 @@ export const getSettingsRouteConfig = ( syntheticsPath: string, baseTitle: string ) => { + const sharedProps = { + title: i18n.translate('xpack.synthetics.settingsRoute.title', { + defaultMessage: 'Settings | {baseTitle}', + values: { baseTitle }, + }), + component: SettingsPage, + pageHeader: getSettingsPageHeader(history, syntheticsPath), + dataTestSubj: 'syntheticsSettingsPage', + pageSectionProps: { + paddingSize: 'm', + }, + }; + return [ { - title: i18n.translate('xpack.synthetics.settingsRoute.title', { - defaultMessage: 'Settings | {baseTitle}', - values: { baseTitle }, - }), + ...sharedProps, path: SETTINGS_ROUTE, - component: SettingsPage, - dataTestSubj: 'syntheticsSettingsPage', - pageSectionProps: { - paddingSize: 'm', - }, - pageHeader: getSettingsPageHeader(history, syntheticsPath), }, { - title: i18n.translate('xpack.synthetics.settingsRoute.title', { - defaultMessage: 'Settings | {baseTitle}', - values: { baseTitle }, - }), + ...sharedProps, path: SYNTHETICS_SETTINGS_ROUTE, - component: SettingsPage, - dataTestSubj: 'syntheticsSettingsPage', - pageSectionProps: { - paddingSize: 'm', - }, - pageHeader: getSettingsPageHeader(history, syntheticsPath), }, ] as RouteProps[]; }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts index 3c48696c685b9..50683fdd87a35 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts @@ -5,14 +5,10 @@ * 2.0. */ -import { SavedObjectsClientContract } from '@kbn/core/public'; -import { SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; +import { SYNTHETICS_API_URLS } from '../../../../../common/constants'; +import { PrivateLocation, SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; import { apiService } from '../../../../utils/api_service/api_service'; import { AgentPoliciesList } from '.'; -import { - privateLocationsSavedObjectId, - privateLocationsSavedObjectName, -} from '../../../../../common/saved_objects/private_locations'; const FLEET_URLS = { AGENT_POLICIES: '/api/fleet/agent_policies', @@ -33,26 +29,18 @@ export const fetchAgentPolicies = async (): Promise => { ); }; -export const setSyntheticsPrivateLocations = async ( - client: SavedObjectsClientContract, - privateLocations: SyntheticsPrivateLocations -) => { - const result = await client.create(privateLocationsSavedObjectName, privateLocations, { - id: privateLocationsSavedObjectId, - overwrite: true, - }); +export const addSyntheticsPrivateLocations = async ( + newLocation: PrivateLocation +): Promise => { + return await apiService.post(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, newLocation); +}; - return result.attributes; +export const getSyntheticsPrivateLocations = async (): Promise => { + return await apiService.get(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS); }; -export const getSyntheticsPrivateLocations = async (client: SavedObjectsClientContract) => { - try { - const obj = await client.get( - privateLocationsSavedObjectName, - privateLocationsSavedObjectId - ); - return obj?.attributes.locations ?? []; - } catch (getErr) { - return []; - } +export const deleteSyntheticsPrivateLocations = async ( + locationId: string +): Promise => { + return await apiService.delete(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS + `/${locationId}`); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts index ced9c212e83cf..371e054476c79 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts @@ -45,7 +45,6 @@ export const rootEffect = function* root(): Generator { fork(fetchAgentPoliciesEffect), fork(fetchDynamicSettingsEffect), fork(setDynamicSettingsEffect), - fork(fetchAgentPoliciesEffect), fork(fetchAlertConnectorsEffect), fork(syncGlobalParamsEffect), fork(enableDefaultAlertingEffect), diff --git a/x-pack/plugins/synthetics/server/routes/index.ts b/x-pack/plugins/synthetics/server/routes/index.ts index 6978a38b2be46..b394c53f20142 100644 --- a/x-pack/plugins/synthetics/server/routes/index.ts +++ b/x-pack/plugins/synthetics/server/routes/index.ts @@ -44,6 +44,9 @@ import { getHasIntegrationMonitorsRoute } from './fleet/get_has_integration_moni import { addSyntheticsParamsRoute } from './settings/add_param'; import { enableDefaultAlertingRoute } from './default_alerts/enable_default_alert'; import { getDefaultAlertingRoute } from './default_alerts/get_default_alert'; +import { addPrivateLocationRoute } from './settings/private_locations/add_private_location'; +import { deletePrivateLocationRoute } from './settings/private_locations/delete_private_location'; +import { getPrivateLocationsRoute } from './settings/private_locations/get_private_locations'; export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [ addSyntheticsMonitorRoute, @@ -77,6 +80,9 @@ export const syntheticsAppRestApiRoutes: SyntheticsRestApiRouteFactory[] = [ getDefaultAlertingRoute, updateDefaultAlertingRoute, createJourneyRoute, + addPrivateLocationRoute, + deletePrivateLocationRoute, + getPrivateLocationsRoute, ]; export const syntheticsAppStreamingApiRoutes: SyntheticsStreamingRouteFactory[] = [ diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts new file mode 100644 index 0000000000000..9edd4bf53f81a --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/add_private_location.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { getAllPrivateLocations } from './get_private_locations'; +import { + privateLocationsSavedObjectId, + privateLocationsSavedObjectName, +} from '../../../../common/saved_objects/private_locations'; +import { SyntheticsRestApiRouteFactory } from '../../../legacy_uptime/routes'; +import { SYNTHETICS_API_URLS } from '../../../../common/constants'; +import { PrivateLocation } from '../../../../common/runtime_types'; + +export const PrivateLocationSchema = schema.object({ + label: schema.string(), + id: schema.string(), + agentPolicyId: schema.string(), + concurrentMonitors: schema.number(), + tags: schema.maybe(schema.arrayOf(schema.string())), + geo: schema.maybe( + schema.object({ + lat: schema.oneOf([schema.number(), schema.string()]), + lon: schema.oneOf([schema.number(), schema.string()]), + }) + ), +}); + +export const addPrivateLocationRoute: SyntheticsRestApiRouteFactory = () => ({ + method: 'POST', + path: SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, + validate: { + body: PrivateLocationSchema, + }, + writeAccess: true, + handler: async ({ request, server, savedObjectsClient }): Promise => { + const location = request.body as PrivateLocation; + + const { locations } = await getAllPrivateLocations(savedObjectsClient); + const existingLocations = locations.filter((loc) => loc.id !== location.agentPolicyId); + + const result = await savedObjectsClient.create( + privateLocationsSavedObjectName, + { locations: [...existingLocations, location] }, + { + id: privateLocationsSavedObjectId, + overwrite: true, + } + ); + + return result.attributes; + }, +}); diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/delete_private_location.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/delete_private_location.ts new file mode 100644 index 0000000000000..7360adfbc0b60 --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/delete_private_location.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 } from '@kbn/config-schema'; +import { getAllPrivateLocations } from './get_private_locations'; +import { SyntheticsRestApiRouteFactory } from '../../../legacy_uptime/routes'; +import { SYNTHETICS_API_URLS } from '../../../../common/constants'; +import { + privateLocationsSavedObjectId, + privateLocationsSavedObjectName, +} from '../../../../common/saved_objects/private_locations'; + +export const deletePrivateLocationRoute: SyntheticsRestApiRouteFactory = () => ({ + method: 'DELETE', + path: SYNTHETICS_API_URLS.PRIVATE_LOCATIONS + '/{locationId}', + validate: { + params: schema.object({ + locationId: schema.string({ minLength: 1, maxLength: 1024 }), + }), + }, + writeAccess: true, + handler: async ({ savedObjectsClient, request, server }): Promise => { + const { locationId } = request.params as { locationId: string }; + + const { locations } = await getAllPrivateLocations(savedObjectsClient); + const remainingLocations = locations.filter((loc) => loc.id !== locationId); + + const result = await savedObjectsClient.create( + privateLocationsSavedObjectName, + { locations: remainingLocations }, + { + id: privateLocationsSavedObjectId, + overwrite: true, + } + ); + + return result.attributes; + }, +}); diff --git a/x-pack/plugins/synthetics/server/routes/settings/private_locations/get_private_locations.ts b/x-pack/plugins/synthetics/server/routes/settings/private_locations/get_private_locations.ts new file mode 100644 index 0000000000000..82b1f4f4e0e8a --- /dev/null +++ b/x-pack/plugins/synthetics/server/routes/settings/private_locations/get_private_locations.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { SyntheticsPrivateLocations } from '../../../../common/runtime_types'; +import { SyntheticsRestApiRouteFactory } from '../../../legacy_uptime/routes'; +import { SYNTHETICS_API_URLS } from '../../../../common/constants'; +import { + privateLocationsSavedObjectId, + privateLocationsSavedObjectName, +} from '../../../../common/saved_objects/private_locations'; + +export const getPrivateLocationsRoute: SyntheticsRestApiRouteFactory = () => ({ + method: 'GET', + path: SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, + validate: {}, + handler: async ({ savedObjectsClient }): Promise => { + return await getAllPrivateLocations(savedObjectsClient); + }, +}); + +export const getAllPrivateLocations = async ( + savedObjectsClient: SavedObjectsClientContract +): Promise => { + try { + const obj = await savedObjectsClient.get( + privateLocationsSavedObjectName, + privateLocationsSavedObjectId + ); + return obj?.attributes ?? { locations: [] }; + } catch (getErr) { + return { locations: [] }; + } +}; From b867701ab8a0438bf6c6893f2b7e66e5e992b923 Mon Sep 17 00:00:00 2001 From: Ido Cohen <90558359+CohenIdo@users.noreply.github.com> Date: Wed, 1 Mar 2023 10:38:50 +0200 Subject: [PATCH 074/131] [Cloud Security] update transform max age --- .../create_transforms/create_transforms.ts | 26 ++++++++++++++++--- .../latest_findings_transform.ts | 4 +-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/server/create_transforms/create_transforms.ts b/x-pack/plugins/cloud_security_posture/server/create_transforms/create_transforms.ts index eecc50da0ba4c..2f902d03f62dc 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_transforms/create_transforms.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_transforms/create_transforms.ts @@ -10,14 +10,18 @@ import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { errors } from '@elastic/elasticsearch'; import { latestFindingsTransform } from './latest_findings_transform'; +const LATEST_TRANSFORM_V830 = 'cloud_security_posture.findings_latest-default-0.0.1'; +const LATEST_TRANSFORM_V840 = 'cloud_security_posture.findings_latest-default-8.4.0'; + +const PREVIOUS_TRANSFORMS = [LATEST_TRANSFORM_V830, LATEST_TRANSFORM_V840]; + // TODO: Move transforms to integration package export const initializeCspTransforms = async ( esClient: ElasticsearchClient, logger: Logger ): Promise => { // Deletes old assets from previous versions as part of upgrade process - const LATEST_TRANSFORM_V830 = 'cloud_security_posture.findings_latest-default-0.0.1'; - await deleteTransformSafe(esClient, logger, LATEST_TRANSFORM_V830); + await deletePreviousTransformsVersions(esClient, logger); await initializeTransform(esClient, latestFindingsTransform, logger); }; @@ -107,16 +111,30 @@ export const startTransformIfNotStarted = async ( } }; -const deleteTransformSafe = async (esClient: ElasticsearchClient, logger: Logger, name: string) => { +const deletePreviousTransformsVersions = async (esClient: ElasticsearchClient, logger: Logger) => { + for (const transform of PREVIOUS_TRANSFORMS) { + const response = await deleteTransformSafe(esClient, logger, transform); + if (response) return; + } +}; + +const deleteTransformSafe = async ( + esClient: ElasticsearchClient, + logger: Logger, + name: string +): Promise => { try { await esClient.transform.deleteTransform({ transform_id: name, force: true }); logger.info(`Deleted transform successfully [Name: ${name}]`); + return true; } catch (e) { if (e instanceof errors.ResponseError && e.statusCode === 404) { - logger.trace(`Transform no longer exists [Name: ${name}]`); + logger.trace(`Transform not exists [Name: ${name}]`); + return false; } else { logger.error(`Failed to delete transform [Name: ${name}]`); logger.error(e); + return false; } } }; diff --git a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts index 9775b260c6949..9e9192e7690e8 100644 --- a/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts +++ b/x-pack/plugins/cloud_security_posture/server/create_transforms/latest_findings_transform.ts @@ -12,7 +12,7 @@ import { } from '../../common/constants'; export const latestFindingsTransform: TransformPutTransformRequest = { - transform_id: 'cloud_security_posture.findings_latest-default-8.4.0', + transform_id: 'cloud_security_posture.findings_latest-default-8.8.0', description: 'Defines findings transformation to view only the latest finding per resource', source: { index: FINDINGS_INDEX_PATTERN, @@ -30,7 +30,7 @@ export const latestFindingsTransform: TransformPutTransformRequest = { retention_policy: { time: { field: '@timestamp', - max_age: '5h', + max_age: '26h', }, }, latest: { From 5514f93fc8ecccc007d1e25c9413df1c739feae9 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Wed, 1 Mar 2023 10:04:31 +0100 Subject: [PATCH 075/131] [Security Solution] Re-enable a skipped url state e2e test (#152075) **Relates to:** https://github.com/elastic/kibana/pull/151244 ## Summary Re-enable `Do not clears kql when navigating to a new page` url state e2e test. ## Details Investigation has shown that https://github.com/elastic/kibana/pull/150787 lead to breaking this test. While it's not clear from the EUI upgrade PR itself the cause lays under the hood. It fixes retrieving the state (current KQL) from the url. As the test visits the page with the saved KQL which is properly restored the next `kqlSearch()` command types the same KQL in the query bar leading to invalid KQL and broken test eventually. For some reason the KQL wasn't able to restore on this page while it's not an issue anymore I removed `kqlSearch()` command and fixed the test this way. --- x-pack/plugins/security_solution/cypress/e2e/urls/state.cy.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/e2e/urls/state.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/urls/state.cy.ts index 1daaa206a67f4..0cbd85ffcba43 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/urls/state.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/urls/state.cy.ts @@ -274,10 +274,8 @@ describe('url state', () => { ); }); - // Failing on `main`, skipping for now, to be addressed by security-detection-rules-area - it.skip('Do not clears kql when navigating to a new page', () => { + it('Do not clears kql when navigating to a new page', () => { visitWithoutDateRange(ABSOLUTE_DATE_RANGE.urlKqlHostsHosts); - kqlSearch('source.ip: "10.142.0.9"{enter}'); navigateFromHeaderTo(NETWORK); cy.get(KQL_INPUT).should('have.text', 'source.ip: "10.142.0.9"'); }); From 5dd8742d1750c9307fa1af05acc1a38e48a949b2 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Wed, 1 Mar 2023 10:26:04 +0100 Subject: [PATCH 076/131] Allow for additive mappings update without creating a new version index (#149326) Fixes [#147237](https://github.com/elastic/kibana/issues/147237) Based on the same principle as [#147371](https://github.com/elastic/kibana/pull/147371), the goal of this PR is to **avoid reindexing if possible**. This time, the idea is to check whether the new mappings are still compatible with the ones stored in ES. To to so, we attempt to update the mappings in place in the existing index, introducing a new `CHECK_COMPATIBLE_MAPPINGS` step: * If the update operation fails, we assume the mappings are NOT compatible, and we continue with the normal reindexing flow. * If the update operation succeeds, we assume the mappings ARE compatible, and we skip reindexing, just like [#147371](https://github.com/elastic/kibana/pull/147371) does. ![image](https://user-images.githubusercontent.com/25349407/216979882-9fe9f034-b521-4171-b85d-50be6a13e179.png) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../index.ts | 2 +- .../src/actions/index.ts | 14 +- .../update_and_pickup_mappings.test.ts | 9 +- .../src/actions/update_and_pickup_mappings.ts | 4 +- .../src/actions/update_mappings.test.ts | 147 +++++++ .../src/actions/update_mappings.ts | 63 +++ .../update_target_mappings_meta.test.ts | 80 ---- .../actions/update_target_mappings_meta.ts | 55 --- .../src/model/helpers.ts | 8 +- .../src/model/model.test.ts | 51 ++- .../src/model/model.ts | 29 +- .../src/next.ts | 62 +-- .../src/state.ts | 8 + .../archives/7.13.0_with_corrupted_so.zip | Bin 46485 -> 0 bytes .../group1/7_13_0_failed_action_tasks.test.ts | 160 ++++---- .../group1/7_13_0_transform_failures.test.ts | 30 +- .../group2/check_target_mappings.test.ts | 73 +--- .../migrations/group2/cleanup.test.ts | 255 +++++++----- .../group2/multiple_kibana_nodes.test.ts | 10 +- .../migrations/group2/outdated_docs.test.ts | 4 +- .../migrations/group3/actions/actions.test.ts | 84 +++- .../migrations/group3/active_delete.test.ts | 388 ++++++++++-------- .../group3/multiple_es_nodes.test.ts | 6 +- .../migrations/group3/rewriting_id.test.ts | 4 +- .../migrations/group3/skip_reindex.test.ts | 220 +++++----- .../kibana_migrator_test_kit.fixtures.ts | 82 ++++ .../migrations/kibana_migrator_test_kit.ts | 136 +++++- 27 files changed, 1254 insertions(+), 730 deletions(-) create mode 100644 packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.test.ts create mode 100644 packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.ts delete mode 100644 packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.test.ts delete mode 100644 packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.ts delete mode 100644 src/core/server/integration_tests/saved_objects/migrations/archives/7.13.0_with_corrupted_so.zip create mode 100644 src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts index 9a4a728184388..61856a30cfc10 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/index.ts @@ -28,7 +28,7 @@ export { cloneIndex, waitForTask, updateAndPickupMappings, - updateTargetMappingsMeta, + updateMappings, updateAliases, transformDocs, setWriteBlock, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts index 2593ac7867d1e..7e380d3a7ad17 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/index.ts @@ -6,7 +6,8 @@ * Side Public License, v 1. */ -import { type Either, right } from 'fp-ts/lib/Either'; +import type { Either } from 'fp-ts/lib/Either'; +import { right } from 'fp-ts/lib/Either'; import type { RetryableEsClientError } from './catch_retryable_es_client_errors'; import type { DocumentsTransformFailed } from '../core/migrate_raw_docs'; @@ -37,11 +38,8 @@ export type { CloneIndexResponse, CloneIndexParams } from './clone_index'; export { cloneIndex } from './clone_index'; export type { WaitForIndexStatusParams, IndexNotYellowTimeout } from './wait_for_index_status'; -import { - type IndexNotGreenTimeout, - type IndexNotYellowTimeout, - waitForIndexStatus, -} from './wait_for_index_status'; +import type { IndexNotGreenTimeout, IndexNotYellowTimeout } from './wait_for_index_status'; +import { waitForIndexStatus } from './wait_for_index_status'; export type { WaitForTaskResponse, WaitForTaskCompletionTimeout } from './wait_for_task'; import { waitForTask, WaitForTaskCompletionTimeout } from './wait_for_task'; @@ -85,8 +83,6 @@ export { createIndex } from './create_index'; export { checkTargetMappings } from './check_target_mappings'; -export { updateTargetMappingsMeta } from './update_target_mappings_meta'; - export const noop = async (): Promise> => right('noop' as const); export type { @@ -95,6 +91,8 @@ export type { } from './update_and_pickup_mappings'; export { updateAndPickupMappings } from './update_and_pickup_mappings'; +export { updateMappings } from './update_mappings'; + import type { UnknownDocsFound } from './check_for_unknown_docs'; import type { IncompatibleClusterRoutingAllocation } from './initialize_action'; import { ClusterShardLimitExceeded } from './create_index'; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.test.ts index c1fd2f7b0b0fb..da243af9a7ebc 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.test.ts @@ -46,7 +46,7 @@ describe('updateAndPickupMappings', () => { expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(retryableError); }); - it('updates the _mapping properties but not the _meta information', async () => { + it('calls the indices.putMapping with the mapping properties as well as the _meta information', async () => { const task = updateAndPickupMappings({ client, index: 'new_index', @@ -82,6 +82,13 @@ describe('updateAndPickupMappings', () => { dynamic: false, }, }, + _meta: { + migrationMappingPropertyHashes: { + references: '7997cf5a56cc02bdc9c93361bde732b0', + 'epm-packages': '860e23f4404fa1c33f430e6dad5d8fa2', + 'cases-connector-mappings': '17d2e9e0e170a21a471285a5d845353c', + }, + }, }); }); }); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts index 7f89f862ce128..653a90746dea0 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_and_pickup_mappings.ts @@ -45,13 +45,11 @@ export const updateAndPickupMappings = ({ RetryableEsClientError, 'update_mappings_succeeded' > = () => { - // ._meta property will be updated on a later step - const { _meta, ...mappingsWithoutMeta } = mappings; return client.indices .putMapping({ index, timeout: DEFAULT_TIMEOUT, - ...mappingsWithoutMeta, + ...mappings, }) .then(() => { // Ignore `acknowledged: false`. When the coordinating node accepts diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.test.ts new file mode 100644 index 0000000000000..133f07d7460e5 --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.test.ts @@ -0,0 +1,147 @@ +/* + * Copyright 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 * as Either from 'fp-ts/lib/Either'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { errors as EsErrors } from '@elastic/elasticsearch'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; +import { updateMappings } from './update_mappings'; +import { DEFAULT_TIMEOUT } from './constants'; + +jest.mock('./catch_retryable_es_client_errors'); + +describe('updateMappings', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const createErrorClient = (response: Partial>>) => { + // Create a mock client that returns the desired response + const apiResponse = elasticsearchClientMock.createApiResponse(response); + const error = new EsErrors.ResponseError(apiResponse); + const client = elasticsearchClientMock.createInternalClient( + elasticsearchClientMock.createErrorTransportRequestPromise(error) + ); + + return { client, error }; + }; + + it('resolves left if the mappings are not compatible (aka 400 illegal_argument_exception from ES)', async () => { + const { client } = createErrorClient({ + statusCode: 400, + body: { + error: { + type: 'illegal_argument_exception', + reason: 'mapper [action.actionTypeId] cannot be changed from type [keyword] to [text]', + }, + }, + }); + + const task = updateMappings({ + client, + index: 'new_index', + mappings: { + properties: { + created_at: { + type: 'date', + }, + }, + _meta: { + migrationMappingPropertyHashes: { + references: '7997cf5a56cc02bdc9c93361bde732b0', + 'epm-packages': '860e23f4404fa1c33f430e6dad5d8fa2', + 'cases-connector-mappings': '17d2e9e0e170a21a471285a5d845353c', + }, + }, + }, + }); + + const res = await task(); + + expect(Either.isLeft(res)).toEqual(true); + expect(res).toMatchInlineSnapshot(` + Object { + "_tag": "Left", + "left": Object { + "type": "incompatible_mapping_exception", + }, + } + `); + }); + + it('calls catchRetryableEsClientErrors when the promise rejects', async () => { + const { client, error: retryableError } = createErrorClient({ + statusCode: 503, + body: { error: { type: 'es_type', reason: 'es_reason' } }, + }); + + const task = updateMappings({ + client, + index: 'new_index', + mappings: { + properties: { + created_at: { + type: 'date', + }, + }, + _meta: {}, + }, + }); + try { + await task(); + } catch (e) { + /** ignore */ + } + + expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(retryableError); + }); + + it('updates the mapping information of the desired index', async () => { + const client = elasticsearchClientMock.createInternalClient(); + + const task = updateMappings({ + client, + index: 'new_index', + mappings: { + properties: { + created_at: { + type: 'date', + }, + }, + _meta: { + migrationMappingPropertyHashes: { + references: '7997cf5a56cc02bdc9c93361bde732b0', + 'epm-packages': '860e23f4404fa1c33f430e6dad5d8fa2', + 'cases-connector-mappings': '17d2e9e0e170a21a471285a5d845353c', + }, + }, + }, + }); + + const res = await task(); + expect(Either.isRight(res)).toBe(true); + expect(client.indices.putMapping).toHaveBeenCalledTimes(1); + expect(client.indices.putMapping).toHaveBeenCalledWith({ + index: 'new_index', + timeout: DEFAULT_TIMEOUT, + properties: { + created_at: { + type: 'date', + }, + }, + _meta: { + migrationMappingPropertyHashes: { + references: '7997cf5a56cc02bdc9c93361bde732b0', + 'epm-packages': '860e23f4404fa1c33f430e6dad5d8fa2', + 'cases-connector-mappings': '17d2e9e0e170a21a471285a5d845353c', + }, + }, + }); + }); +}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.ts new file mode 100644 index 0000000000000..4cf57f3ce7a8d --- /dev/null +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 * as Either from 'fp-ts/lib/Either'; +import * as TaskEither from 'fp-ts/lib/TaskEither'; +import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import type { IndexMapping } from '@kbn/core-saved-objects-base-server-internal'; +import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; +import type { RetryableEsClientError } from './catch_retryable_es_client_errors'; +import { DEFAULT_TIMEOUT } from './constants'; + +/** @internal */ +export interface UpdateMappingsParams { + client: ElasticsearchClient; + index: string; + mappings: IndexMapping; +} + +/** @internal */ +export interface IncompatibleMappingException { + type: 'incompatible_mapping_exception'; +} + +/** + * Updates an index's mappings and runs an pickupUpdatedMappings task so that the mapping + * changes are "picked up". Returns a taskId to track progress. + */ +export const updateMappings = ({ + client, + index, + mappings, +}: UpdateMappingsParams): TaskEither.TaskEither< + RetryableEsClientError | IncompatibleMappingException, + 'update_mappings_succeeded' +> => { + return () => { + return client.indices + .putMapping({ + index, + timeout: DEFAULT_TIMEOUT, + ...mappings, + }) + .then(() => Either.right('update_mappings_succeeded' as const)) + .catch((res) => { + const errorType = res?.body?.error?.type; + // ES throws this exact error when attempting to make incompatible updates to the mappigns + if ( + res?.statusCode === 400 && + (errorType === 'illegal_argument_exception' || + errorType === 'strict_dynamic_mapping_exception' || + errorType === 'mapper_parsing_exception') + ) { + return Either.left({ type: 'incompatible_mapping_exception' }); + } + return catchRetryableEsClientErrors(res); + }); + }; +}; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.test.ts deleted file mode 100644 index 9116d5389f2ec..0000000000000 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 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 { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; -import { errors as EsErrors } from '@elastic/elasticsearch'; -import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; -import { updateTargetMappingsMeta } from './update_target_mappings_meta'; -import { DEFAULT_TIMEOUT } from './constants'; - -jest.mock('./catch_retryable_es_client_errors'); - -describe('updateTargetMappingsMeta', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - // Create a mock client that rejects all methods with a 503 status code - // response. - const retryableError = new EsErrors.ResponseError( - elasticsearchClientMock.createApiResponse({ - statusCode: 503, - body: { error: { type: 'es_type', reason: 'es_reason' } }, - }) - ); - const client = elasticsearchClientMock.createInternalClient( - elasticsearchClientMock.createErrorTransportRequestPromise(retryableError) - ); - - it('calls catchRetryableEsClientErrors when the promise rejects', async () => { - const task = updateTargetMappingsMeta({ - client, - index: 'new_index', - meta: {}, - }); - try { - await task(); - } catch (e) { - /** ignore */ - } - - expect(catchRetryableEsClientErrors).toHaveBeenCalledWith(retryableError); - }); - - it('updates the _meta information of the desired index', async () => { - const task = updateTargetMappingsMeta({ - client, - index: 'new_index', - meta: { - migrationMappingPropertyHashes: { - references: '7997cf5a56cc02bdc9c93361bde732b0', - 'epm-packages': '860e23f4404fa1c33f430e6dad5d8fa2', - 'cases-connector-mappings': '17d2e9e0e170a21a471285a5d845353c', - }, - }, - }); - try { - await task(); - } catch (e) { - /** ignore */ - } - - expect(client.indices.putMapping).toHaveBeenCalledTimes(1); - expect(client.indices.putMapping).toHaveBeenCalledWith({ - index: 'new_index', - timeout: DEFAULT_TIMEOUT, - _meta: { - migrationMappingPropertyHashes: { - references: '7997cf5a56cc02bdc9c93361bde732b0', - 'epm-packages': '860e23f4404fa1c33f430e6dad5d8fa2', - 'cases-connector-mappings': '17d2e9e0e170a21a471285a5d845353c', - }, - }, - }); - }); -}); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.ts deleted file mode 100644 index 05f954b38fe71..0000000000000 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.ts +++ /dev/null @@ -1,55 +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 * as Either from 'fp-ts/lib/Either'; -import * as TaskEither from 'fp-ts/lib/TaskEither'; - -import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { IndexMappingMeta } from '@kbn/core-saved-objects-base-server-internal'; - -import { - catchRetryableEsClientErrors, - RetryableEsClientError, -} from './catch_retryable_es_client_errors'; -import { DEFAULT_TIMEOUT } from './constants'; - -/** @internal */ -export interface UpdateTargetMappingsMetaParams { - client: ElasticsearchClient; - index: string; - meta?: IndexMappingMeta; -} -/** - * Updates an index's mappings _meta information - */ -export const updateTargetMappingsMeta = - ({ - client, - index, - meta, - }: UpdateTargetMappingsMetaParams): TaskEither.TaskEither< - RetryableEsClientError, - 'update_mappings_meta_succeeded' - > => - () => { - return client.indices - .putMapping({ - index, - timeout: DEFAULT_TIMEOUT, - _meta: meta || {}, - }) - .then(() => { - // Ignore `acknowledged: false`. When the coordinating node accepts - // the new cluster state update but not all nodes have applied the - // update within the timeout `acknowledged` will be false. However, - // retrying this update will always immediately result in `acknowledged: - // true` even if there are still nodes which are falling behind with - // cluster state updates. - return Either.right('update_mappings_meta_succeeded' as const); - }) - .catch(catchRetryableEsClientErrors); - }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts index 19ef5d66c0eb5..15691632a4399 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/helpers.ts @@ -107,12 +107,12 @@ export function addExcludedTypesToBoolQuery( /** * Add the given clauses to the 'must' of the given query + * @param filterClauses the clauses to be added to a 'must' * @param boolQuery the bool query to be enriched - * @param mustClauses the clauses to be added to a 'must' * @returns a new query container with the enriched query */ export function addMustClausesToBoolQuery( - mustClauses: QueryDslQueryContainer[], + filterClauses: QueryDslQueryContainer[], boolQuery?: QueryDslBoolQuery ): QueryDslQueryContainer { let must: QueryDslQueryContainer[] = []; @@ -121,7 +121,7 @@ export function addMustClausesToBoolQuery( must = must.concat(boolQuery.must); } - must.push(...mustClauses); + must.push(...filterClauses); return { bool: { @@ -133,8 +133,8 @@ export function addMustClausesToBoolQuery( /** * Add the given clauses to the 'must_not' of the given query - * @param boolQuery the bool query to be enriched * @param filterClauses the clauses to be added to a 'must_not' + * @param boolQuery the bool query to be enriched * @returns a new query container with the enriched query */ export function addMustNotClausesToBoolQuery( diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts index c07538d1c1184..4eccf11e6a65b 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.test.ts @@ -13,6 +13,7 @@ import type { IndexMapping } from '@kbn/core-saved-objects-base-server-internal' import type { BaseState, CalculateExcludeFiltersState, + UpdateSourceMappingsState, CheckTargetMappingsState, CheckUnknownDocumentsState, CheckVersionIndexReadyActions, @@ -1298,13 +1299,12 @@ describe('migrations v2 model', () => { sourceIndexMappings: actualMappings, }; - test('WAIT_FOR_YELLOW_SOURCE -> CHECK_UNKNOWN_DOCUMENTS', () => { + test('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS', () => { const res: ResponseType<'WAIT_FOR_YELLOW_SOURCE'> = Either.right({}); const newState = model(changedMappingsState, res); - expect(newState.controlState).toEqual('CHECK_UNKNOWN_DOCUMENTS'); expect(newState).toMatchObject({ - controlState: 'CHECK_UNKNOWN_DOCUMENTS', + controlState: 'UPDATE_SOURCE_MAPPINGS', sourceIndex: Option.some('.kibana_7.11.0_001'), sourceIndexMappings: actualMappings, }); @@ -1330,6 +1330,49 @@ describe('migrations v2 model', () => { }); }); + describe('UPDATE_SOURCE_MAPPINGS', () => { + const checkCompatibleMappingsState: UpdateSourceMappingsState = { + ...baseState, + controlState: 'UPDATE_SOURCE_MAPPINGS', + sourceIndex: Option.some('.kibana_7.11.0_001') as Option.Some, + sourceIndexMappings: baseState.targetIndexMappings, + aliases: { + '.kibana': '.kibana_7.11.0_001', + '.kibana_7.11.0': '.kibana_7.11.0_001', + }, + }; + + describe('if action succeeds', () => { + test('UPDATE_SOURCE_MAPPINGS -> CLEANUP_UNKNOWN_AND_EXCLUDED', () => { + const res: ResponseType<'UPDATE_SOURCE_MAPPINGS'> = Either.right( + 'update_mappings_succeeded' as const + ); + const newState = model(checkCompatibleMappingsState, res); + + expect(newState).toMatchObject({ + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', + targetIndex: '.kibana_7.11.0_001', + versionIndexReadyActions: Option.none, + }); + }); + }); + + describe('if action fails', () => { + test('UPDATE_SOURCE_MAPPINGS -> CHECK_UNKNOWN_DOCUMENTS', () => { + const res: ResponseType<'UPDATE_SOURCE_MAPPINGS'> = Either.left({ + type: 'incompatible_mapping_exception', + }); + const newState = model(checkCompatibleMappingsState, res); + + expect(newState).toMatchObject({ + controlState: 'CHECK_UNKNOWN_DOCUMENTS', + sourceIndex: Option.some('.kibana_7.11.0_001'), + sourceIndexMappings: baseState.targetIndexMappings, + }); + }); + }); + }); + describe('CLEANUP_UNKNOWN_AND_EXCLUDED', () => { const cleanupUnknownAndExcluded: CleanupUnknownAndExcluded = { ...baseState, @@ -2693,7 +2736,7 @@ describe('migrations v2 model', () => { test('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS if the mapping _meta information is successfully updated', () => { const res: ResponseType<'UPDATE_TARGET_MAPPINGS_META'> = Either.right( - 'update_mappings_meta_succeeded' + 'update_mappings_succeeded' ); const newState = model(updateTargetMappingsMetaState, res) as CheckVersionIndexReadyActions; expect(newState.controlState).toBe('CHECK_VERSION_INDEX_READY_ACTIONS'); diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts index 4c2a9147eb125..f1cb94d276b35 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/model/model.ts @@ -424,7 +424,6 @@ export const model = (currentState: State, resW: ResponseType): } else if (stateP.controlState === 'WAIT_FOR_YELLOW_SOURCE') { const res = resW as ExcludeRetryableEsError>; if (Either.isRight(res)) { - // check the existing mappings to see if we can avoid reindexing if ( // source exists Boolean(stateP.sourceIndexMappings._meta?.migrationMappingPropertyHashes) && @@ -434,9 +433,9 @@ export const model = (currentState: State, resW: ResponseType): stateP.sourceIndexMappings, /* expected */ stateP.targetIndexMappings - ) && - Math.random() < 10 + ) ) { + // the existing mappings match, we can avoid reindexing return { ...stateP, controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', @@ -446,7 +445,7 @@ export const model = (currentState: State, resW: ResponseType): } else { return { ...stateP, - controlState: 'CHECK_UNKNOWN_DOCUMENTS', + controlState: 'UPDATE_SOURCE_MAPPINGS', }; } } else if (Either.isLeft(res)) { @@ -465,6 +464,28 @@ export const model = (currentState: State, resW: ResponseType): } else { return throwBadResponse(stateP, res); } + } else if (stateP.controlState === 'UPDATE_SOURCE_MAPPINGS') { + const res = resW as ExcludeRetryableEsError>; + if (Either.isRight(res)) { + return { + ...stateP, + controlState: 'CLEANUP_UNKNOWN_AND_EXCLUDED', + targetIndex: stateP.sourceIndex.value!, // We preserve the same index, source == target (E.g: ".xx8.7.0_001") + versionIndexReadyActions: Option.none, + }; + } else if (Either.isLeft(res)) { + const left = res.left; + if (isTypeof(left, 'incompatible_mapping_exception')) { + return { + ...stateP, + controlState: 'CHECK_UNKNOWN_DOCUMENTS', + }; + } else { + return throwBadResponse(stateP, left as never); + } + } else { + return throwBadResponse(stateP, res); + } } else if (stateP.controlState === 'CLEANUP_UNKNOWN_AND_EXCLUDED') { const res = resW as ExcludeRetryableEsError>; if (Either.isRight(res)) { diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts index 605dd149855e7..8cebce9995900 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/next.ts @@ -7,44 +7,46 @@ */ import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { omit } from 'lodash'; import type { AllActionStates, - ReindexSourceToTempOpenPit, - ReindexSourceToTempRead, - ReindexSourceToTempClosePit, - ReindexSourceToTempTransform, - MarkVersionIndexReady, + CalculateExcludeFiltersState, + UpdateSourceMappingsState, + CheckTargetMappingsState, + CheckUnknownDocumentsState, + CleanupUnknownAndExcluded, + CleanupUnknownAndExcludedWaitForTaskState, + CloneTempToSource, + CreateNewTargetState, + CreateReindexTempState, InitState, LegacyCreateReindexTargetState, LegacyDeleteState, LegacyReindexState, LegacyReindexWaitForTaskState, LegacySetWriteBlockState, + MarkVersionIndexReady, + MarkVersionIndexReadyConflict, + OutdatedDocumentsRefresh, + OutdatedDocumentsSearchClosePit, + OutdatedDocumentsSearchOpenPit, + OutdatedDocumentsSearchRead, OutdatedDocumentsTransform, + PrepareCompatibleMigration, + RefreshTarget, + ReindexSourceToTempClosePit, + ReindexSourceToTempIndexBulk, + ReindexSourceToTempOpenPit, + ReindexSourceToTempRead, + ReindexSourceToTempTransform, SetSourceWriteBlockState, + SetTempWriteBlock, State, + TransformedDocumentsBulkIndex, UpdateTargetMappingsState, UpdateTargetMappingsWaitForTaskState, - CreateReindexTempState, - MarkVersionIndexReadyConflict, - CreateNewTargetState, - CloneTempToSource, - SetTempWriteBlock, - WaitForYellowSourceState, - TransformedDocumentsBulkIndex, - ReindexSourceToTempIndexBulk, - OutdatedDocumentsSearchOpenPit, - OutdatedDocumentsSearchRead, - OutdatedDocumentsSearchClosePit, - RefreshTarget, - OutdatedDocumentsRefresh, - CheckUnknownDocumentsState, - CalculateExcludeFiltersState, WaitForMigrationCompletionState, - CheckTargetMappingsState, - PrepareCompatibleMigration, - CleanupUnknownAndExcluded, - CleanupUnknownAndExcludedWaitForTaskState, + WaitForYellowSourceState, } from './state'; import type { TransformRawDocs } from './types'; import * as Actions from './actions'; @@ -70,6 +72,12 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra Actions.fetchIndices({ client, indices: [state.currentAlias, state.versionAlias] }), WAIT_FOR_YELLOW_SOURCE: (state: WaitForYellowSourceState) => Actions.waitForIndexStatus({ client, index: state.sourceIndex.value, status: 'yellow' }), + UPDATE_SOURCE_MAPPINGS: (state: UpdateSourceMappingsState) => + Actions.updateMappings({ + client, + index: state.sourceIndex.value, // attempt to update source mappings in-place + mappings: omit(state.targetIndexMappings, ['_meta']), // ._meta property will be updated on a later step + }), CLEANUP_UNKNOWN_AND_EXCLUDED: (state: CleanupUnknownAndExcluded) => Actions.cleanupUnknownAndExcluded({ client, @@ -163,7 +171,7 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra Actions.updateAndPickupMappings({ client, index: state.targetIndex, - mappings: state.targetIndexMappings, + mappings: omit(state.targetIndexMappings, ['_meta']), // ._meta property will be updated on a later step }), UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK: (state: UpdateTargetMappingsWaitForTaskState) => Actions.waitForPickupUpdatedMappingsTask({ @@ -172,10 +180,10 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra timeout: '60s', }), UPDATE_TARGET_MAPPINGS_META: (state: UpdateTargetMappingsState) => - Actions.updateTargetMappingsMeta({ + Actions.updateMappings({ client, index: state.targetIndex, - meta: state.targetIndexMappings._meta, + mappings: state.targetIndexMappings, }), CHECK_VERSION_INDEX_READY_ACTIONS: () => Actions.noop, OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT: (state: OutdatedDocumentsSearchOpenPit) => diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts index a091a2972343f..4ac550c89ff58 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/state.ts @@ -243,6 +243,13 @@ export interface WaitForYellowSourceState extends BaseWithSource { readonly aliases: Record; } +export interface UpdateSourceMappingsState extends BaseState { + readonly controlState: 'UPDATE_SOURCE_MAPPINGS'; + readonly sourceIndex: Option.Some; + readonly sourceIndexMappings: IndexMapping; + readonly aliases: Record; +} + export interface CheckUnknownDocumentsState extends BaseWithSource { /** Check if any unknown document is present in the source index */ readonly controlState: 'CHECK_UNKNOWN_DOCUMENTS'; @@ -493,6 +500,7 @@ export type State = Readonly< | WaitForMigrationCompletionState | DoneState | WaitForYellowSourceState + | UpdateSourceMappingsState | CheckUnknownDocumentsState | SetSourceWriteBlockState | CalculateExcludeFiltersState diff --git a/src/core/server/integration_tests/saved_objects/migrations/archives/7.13.0_with_corrupted_so.zip b/src/core/server/integration_tests/saved_objects/migrations/archives/7.13.0_with_corrupted_so.zip deleted file mode 100644 index f4a89fbcb251480f71b36698f9b9ad28ac212079..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46485 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 ZyHfxM)C*l+a)|(?-~$0I$6fx{{{f3b)u;df diff --git a/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_failed_action_tasks.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_failed_action_tasks.test.ts index 1538e9cfe8ef4..89478ea377f6c 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_failed_action_tasks.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_failed_action_tasks.test.ts @@ -24,90 +24,104 @@ async function removeLogFile() { } describe('migration from 7.13 to 7.14+ with many failed action_tasks', () => { - let esServer: TestElasticsearchUtils; - let root: Root; - let startES: () => Promise; + describe('if mappings are incompatible (reindex required)', () => { + let esServer: TestElasticsearchUtils; + let root: Root; + let startES: () => Promise; - beforeAll(async () => { - await removeLogFile(); - }); + beforeAll(async () => { + await removeLogFile(); + }); - beforeEach(() => { - ({ startES } = createTestServers({ - adjustTimeout: (t: number) => jest.setTimeout(t), - settings: { - es: { - license: 'basic', - dataArchive: Path.join(__dirname, '..', 'archives', '7.13_1.5k_failed_action_tasks.zip'), + beforeEach(() => { + ({ startES } = createTestServers({ + adjustTimeout: (t: number) => jest.setTimeout(t), + settings: { + es: { + license: 'basic', + dataArchive: Path.join( + __dirname, + '..', + 'archives', + '7.13_1.5k_failed_action_tasks.zip' + ), + }, }, - }, - })); - }); + })); + }); - afterEach(async () => { - if (root) { - await root.shutdown(); - } - if (esServer) { - await esServer.stop(); - } + afterEach(async () => { + if (root) { + await root.shutdown(); + } + if (esServer) { + await esServer.stop(); + } - await new Promise((resolve) => setTimeout(resolve, 10000)); - }); + await new Promise((resolve) => setTimeout(resolve, 10000)); + }); - const getCounts = async ( - kibanaIndexName = '.kibana', - taskManagerIndexName = '.kibana_task_manager' - ): Promise<{ tasksCount: number; actionTaskParamsCount: number }> => { - const esClient: ElasticsearchClient = esServer.es.getClient(); - - const actionTaskParamsResponse = await esClient.count({ - index: kibanaIndexName, - body: { - query: { - bool: { must: { term: { type: 'action_task_params' } } }, + const getCounts = async ( + kibanaIndexName = '.kibana', + taskManagerIndexName = '.kibana_task_manager' + ): Promise<{ tasksCount: number; actionTaskParamsCount: number }> => { + const esClient: ElasticsearchClient = esServer.es.getClient(); + + const actionTaskParamsResponse = await esClient.count({ + index: kibanaIndexName, + body: { + query: { + bool: { must: { term: { type: 'action_task_params' } } }, + }, }, - }, - }); - const tasksResponse = await esClient.count({ - index: taskManagerIndexName, - body: { - query: { - bool: { must: { term: { type: 'task' } } }, + }); + const tasksResponse = await esClient.count({ + index: taskManagerIndexName, + body: { + query: { + bool: { must: { term: { type: 'task' } } }, + }, }, - }, - }); + }); - return { - actionTaskParamsCount: actionTaskParamsResponse.count, - tasksCount: tasksResponse.count, + return { + actionTaskParamsCount: actionTaskParamsResponse.count, + tasksCount: tasksResponse.count, + }; }; - }; - - it('filters out all outdated action_task_params and action tasks', async () => { - esServer = await startES(); - - // Verify counts in current index before migration starts - expect(await getCounts()).toEqual({ - actionTaskParamsCount: 2010, - tasksCount: 2020, - }); - root = createRoot(); - await root.preboot(); - await root.setup(); - await root.start(); - - // Bulk of tasks should have been filtered out of current index - const { actionTaskParamsCount, tasksCount } = await getCounts(); - // Use toBeLessThan to avoid flakiness in the case that TM starts manipulating docs before the counts are taken - expect(actionTaskParamsCount).toBeLessThan(1000); - expect(tasksCount).toBeLessThan(1000); - - // Verify that docs were not deleted from old index - expect(await getCounts('.kibana_7.13.5_001', '.kibana_task_manager_7.13.5_001')).toEqual({ - actionTaskParamsCount: 2010, - tasksCount: 2020, + it('filters out all outdated action_task_params and action tasks', async () => { + esServer = await startES(); + + // Verify counts in current index before migration starts + expect(await getCounts()).toEqual({ + actionTaskParamsCount: 2010, + tasksCount: 2020, + }); + + root = createRoot(); + await root.preboot(); + await root.setup(); + await root.start(); + + // Bulk of tasks should have been filtered out of current index + const { actionTaskParamsCount, tasksCount } = await getCounts(); + // Use toBeLessThan to avoid flakiness in the case that TM starts manipulating docs before the counts are taken + expect(actionTaskParamsCount).toBeLessThan(1000); + expect(tasksCount).toBeLessThan(1000); + + const { + actionTaskParamsCount: oldIndexActionTaskParamsCount, + tasksCount: oldIndexTasksCount, + } = await getCounts('.kibana_7.13.5_001', '.kibana_task_manager_7.13.5_001'); + + // .kibana mappings changes are NOT compatible, we reindex and preserve old index's documents + expect(oldIndexActionTaskParamsCount).toEqual(2010); + + // ATM .kibana_task_manager mappings changes are compatible, we skip reindex and actively delete unwanted documents + // if the mappings become incompatible in the future, the we will reindex and the old index must still contain all 2020 docs + // if the mappings remain compatible, we reuse the existing index and actively delete unwanted documents from it + expect(oldIndexTasksCount === 2020 || oldIndexTasksCount < 1000).toEqual(true); }); }); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_transform_failures.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_transform_failures.test.ts index 065a4a4241d07..8a798508ce18f 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_transform_failures.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group1/7_13_0_transform_failures.test.ts @@ -122,30 +122,30 @@ describe('migration v2', () => { // 23 saved objects + 14 corrupt (discarded) = 37 total in the old index expect((docs.hits.total as SearchTotalHits).value).toEqual(23); - expect(docs.hits.hits.map(({ _id }) => _id)).toEqual([ + expect(docs.hits.hits.map(({ _id }) => _id).sort()).toEqual([ 'config:7.13.0', 'index-pattern:logs-*', 'index-pattern:metrics-*', + 'ui-metric:console:DELETE_delete', + 'ui-metric:console:GET_get', + 'ui-metric:console:GET_search', + 'ui-metric:console:POST_delete_by_query', + 'ui-metric:console:POST_index', + 'ui-metric:console:PUT_indices.put_mapping', 'usage-counters:uiCounter:21052021:click:global_search_bar:user_navigated_to_application', + 'usage-counters:uiCounter:21052021:click:global_search_bar:user_navigated_to_application_unknown', + 'usage-counters:uiCounter:21052021:count:console:DELETE_delete', 'usage-counters:uiCounter:21052021:count:console:GET_cat.aliases', - 'usage-counters:uiCounter:21052021:loaded:console:opened_app', 'usage-counters:uiCounter:21052021:count:console:GET_cat.indices', + 'usage-counters:uiCounter:21052021:count:console:GET_get', + 'usage-counters:uiCounter:21052021:count:console:GET_search', + 'usage-counters:uiCounter:21052021:count:console:POST_delete_by_query', + 'usage-counters:uiCounter:21052021:count:console:POST_index', + 'usage-counters:uiCounter:21052021:count:console:PUT_indices.put_mapping', 'usage-counters:uiCounter:21052021:count:global_search_bar:search_focus', - 'usage-counters:uiCounter:21052021:click:global_search_bar:user_navigated_to_application_unknown', 'usage-counters:uiCounter:21052021:count:global_search_bar:search_request', 'usage-counters:uiCounter:21052021:count:global_search_bar:shortcut_used', - 'ui-metric:console:POST_delete_by_query', - 'usage-counters:uiCounter:21052021:count:console:PUT_indices.put_mapping', - 'usage-counters:uiCounter:21052021:count:console:POST_delete_by_query', - 'usage-counters:uiCounter:21052021:count:console:GET_search', - 'ui-metric:console:PUT_indices.put_mapping', - 'ui-metric:console:GET_search', - 'usage-counters:uiCounter:21052021:count:console:DELETE_delete', - 'ui-metric:console:DELETE_delete', - 'usage-counters:uiCounter:21052021:count:console:GET_get', - 'ui-metric:console:GET_get', - 'usage-counters:uiCounter:21052021:count:console:POST_index', - 'ui-metric:console:POST_index', + 'usage-counters:uiCounter:21052021:loaded:console:opened_app', ]); }); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/check_target_mappings.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/check_target_mappings.test.ts index 19326c15e0f25..54ab116d2c596 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/check_target_mappings.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/check_target_mappings.test.ts @@ -8,12 +8,10 @@ import Path from 'path'; import fs from 'fs/promises'; -import JSON5 from 'json5'; import { Env } from '@kbn/config'; import { REPO_ROOT } from '@kbn/repo-info'; import { getEnvOptions } from '@kbn/config-mocks'; import { Root } from '@kbn/core-root-server-internal'; -import { LogRecord } from '@kbn/logging'; import { createRootWithCorePlugins, createTestServers, @@ -23,30 +21,14 @@ import { delay } from '../test_utils'; const logFilePath = Path.join(__dirname, 'check_target_mappings.log'); -async function removeLogFile() { - // ignore errors if it doesn't exist - await fs.unlink(logFilePath).catch(() => void 0); -} - -async function parseLogFile() { - const logFileContent = await fs.readFile(logFilePath, 'utf-8'); - - return logFileContent - .split('\n') - .filter(Boolean) - .map((str) => JSON5.parse(str)) as LogRecord[]; -} - -function logIncludes(logs: LogRecord[], message: string): boolean { - return Boolean(logs?.find((rec) => rec.message.includes(message))); -} - describe('migration v2 - CHECK_TARGET_MAPPINGS', () => { let esServer: TestElasticsearchUtils; let root: Root; - let logs: LogRecord[]; + let logs: string; - beforeEach(async () => await removeLogFile()); + beforeEach(async () => { + await fs.unlink(logFilePath).catch(() => {}); + }); afterEach(async () => { await root?.shutdown(); @@ -71,9 +53,10 @@ describe('migration v2 - CHECK_TARGET_MAPPINGS', () => { await root.start(); // Check for migration steps present in the logs - logs = await parseLogFile(); - expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(true); - expect(logIncludes(logs, 'CHECK_TARGET_MAPPINGS')).toEqual(false); + logs = await fs.readFile(logFilePath, 'utf-8'); + + expect(logs).toMatch('CREATE_NEW_TARGET'); + expect(logs).not.toMatch('CHECK_TARGET_MAPPINGS'); }); describe('when the indices are aligned with the stack version', () => { @@ -98,7 +81,7 @@ describe('migration v2 - CHECK_TARGET_MAPPINGS', () => { // stop Kibana and remove logs await root.shutdown(); await delay(10); - await removeLogFile(); + await fs.unlink(logFilePath).catch(() => {}); root = createRoot(); await root.preboot(); @@ -106,14 +89,12 @@ describe('migration v2 - CHECK_TARGET_MAPPINGS', () => { await root.start(); // Check for migration steps present in the logs - logs = await parseLogFile(); - expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(false); - expect( - logIncludes(logs, 'CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS') - ).toEqual(true); - expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS')).toEqual(false); - expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK')).toEqual(false); - expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_META')).toEqual(false); + logs = await fs.readFile(logFilePath, 'utf-8'); + expect(logs).not.toMatch('CREATE_NEW_TARGET'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS'); + expect(logs).not.toMatch('UPDATE_TARGET_MAPPINGS'); + expect(logs).not.toMatch('UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK'); + expect(logs).not.toMatch('UPDATE_TARGET_MAPPINGS_META'); }); }); @@ -140,23 +121,13 @@ describe('migration v2 - CHECK_TARGET_MAPPINGS', () => { await root.start(); // Check for migration steps present in the logs - logs = await parseLogFile(); - expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(false); - expect(logIncludes(logs, 'CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS')).toEqual(true); - expect( - logIncludes(logs, 'UPDATE_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK') - ).toEqual(true); - expect( - logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK -> UPDATE_TARGET_MAPPINGS_META') - ).toEqual(true); - expect( - logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS') - ).toEqual(true); - expect( - logIncludes(logs, 'CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY') - ).toEqual(true); - expect(logIncludes(logs, 'MARK_VERSION_INDEX_READY -> DONE')).toEqual(true); - expect(logIncludes(logs, 'Migration completed')).toEqual(true); + logs = await fs.readFile(logFilePath, 'utf-8'); + expect(logs).not.toMatch('CREATE_NEW_TARGET'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK -> UPDATE_TARGET_MAPPINGS_META'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS'); + expect(logs).toMatch('Migration completed'); }); }); }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts index 8df491c36f4e3..e1030fe9805e9 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/cleanup.test.ts @@ -10,122 +10,48 @@ import Path from 'path'; import Fs from 'fs'; import Util from 'util'; import JSON5 from 'json5'; +import { type TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; +import { SavedObjectsType } from '@kbn/core-saved-objects-server'; +import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { getMigrationDocLink, delay } from '../test_utils'; import { - createTestServers, - createRootWithCorePlugins, - type TestElasticsearchUtils, -} from '@kbn/core-test-helpers-kbn-server'; -import { Root } from '@kbn/core-root-server-internal'; -import { getMigrationDocLink } from '../test_utils'; + clearLog, + currentVersion, + defaultKibanaIndex, + getKibanaMigratorTestKit, + nextMinor, + startElasticsearch, +} from '../kibana_migrator_test_kit'; const migrationDocLink = getMigrationDocLink().resolveMigrationFailures; const logFilePath = Path.join(__dirname, 'cleanup.log'); -const asyncUnlink = Util.promisify(Fs.unlink); const asyncReadFile = Util.promisify(Fs.readFile); -async function removeLogFile() { - // ignore errors if it doesn't exist - await asyncUnlink(logFilePath).catch(() => void 0); -} - -function createRoot() { - return createRootWithCorePlugins( - { - migrations: { - skip: false, - }, - logging: { - appenders: { - file: { - type: 'file', - fileName: logFilePath, - layout: { - type: 'json', - }, - }, - }, - loggers: [ - { - name: 'root', - appenders: ['file'], - level: 'debug', // DEBUG logs are required to retrieve the PIT _id from the action response logs - }, - ], - }, - }, - { - oss: true, - } - ); -} - describe('migration v2', () => { - let esServer: TestElasticsearchUtils; - let root: Root; + let esServer: TestElasticsearchUtils['es']; + let esClient: ElasticsearchClient; beforeAll(async () => { - await removeLogFile(); + esServer = await startElasticsearch(); }); - afterAll(async () => { - if (root) { - await root.shutdown(); - } - if (esServer) { - await esServer.stop(); - } - - await new Promise((resolve) => setTimeout(resolve, 10000)); + beforeEach(async () => { + esClient = await setupBaseline(); + await clearLog(logFilePath); }); it('clean ups if migration fails', async () => { - const { startES } = createTestServers({ - adjustTimeout: (t: number) => jest.setTimeout(t), - settings: { - es: { - license: 'basic', - // original SO: - // { - // _index: '.kibana_7.13.0_001', - // _type: '_doc', - // _id: 'index-pattern:test_index*', - // _version: 1, - // result: 'created', - // _shards: { total: 2, successful: 1, failed: 0 }, - // _seq_no: 0, - // _primary_term: 1 - // } - dataArchive: Path.join(__dirname, '..', 'archives', '7.13.0_with_corrupted_so.zip'), - }, - }, - }); - - root = createRoot(); - - esServer = await startES(); - await root.preboot(); - const coreSetup = await root.setup(); - - coreSetup.savedObjects.registerType({ - name: 'foo', - hidden: false, - mappings: { - properties: {}, - }, - namespaceType: 'agnostic', - migrations: { - '7.14.0': (doc) => doc, - }, - }); + const { migrator, client } = await setupNextMinor(); + migrator.prepareMigrations(); - await expect(root.start()).rejects.toThrowErrorMatchingInlineSnapshot(` - "Unable to complete saved object migrations for the [.kibana] index: Migrations failed. Reason: 1 corrupt saved object documents were found: index-pattern:test_index* + await expect(migrator.runMigrations()).rejects.toThrowErrorMatchingInlineSnapshot(` + "Unable to complete saved object migrations for the [${defaultKibanaIndex}] index: Migrations failed. Reason: 1 corrupt saved object documents were found: corrupt:2baf4de0-a6d4-11ed-ba5a-39196fc76e60 - To allow migrations to proceed, please delete or fix these documents. - Note that you can configure Kibana to automatically discard corrupt documents and transform errors for this migration. - Please refer to ${migrationDocLink} for more information." - `); + To allow migrations to proceed, please delete or fix these documents. + Note that you can configure Kibana to automatically discard corrupt documents and transform errors for this migration. + Please refer to ${migrationDocLink} for more information." + `); const logFileContent = await asyncReadFile(logFilePath, 'utf-8'); const records = logFileContent @@ -134,7 +60,7 @@ describe('migration v2', () => { .map((str) => JSON5.parse(str)); const logRecordWithPit = records.find( - (rec) => rec.message === '[.kibana] REINDEX_SOURCE_TO_TEMP_OPEN_PIT RESPONSE' + (rec) => rec.message === `[${defaultKibanaIndex}] REINDEX_SOURCE_TO_TEMP_OPEN_PIT RESPONSE` ); expect(logRecordWithPit).toBeTruthy(); @@ -142,7 +68,6 @@ describe('migration v2', () => { const pitId = logRecordWithPit.right.pitId; expect(pitId).toBeTruthy(); - const client = esServer.es.getClient(); await expect( client.search({ body: { @@ -152,4 +77,132 @@ describe('migration v2', () => { // throws an exception that cannot search with closed PIT ).rejects.toThrow(/search_phase_execution_exception/); }); + + afterEach(async () => { + await esClient?.indices.delete({ index: `${defaultKibanaIndex}_${currentVersion}_001` }); + }); + + afterAll(async () => { + await esServer?.stop(); + await delay(10); + }); }); + +const setupBaseline = async () => { + const typesCurrent: SavedObjectsType[] = [ + { + name: 'complex', + hidden: false, + namespaceType: 'agnostic', + mappings: { + properties: { + name: { type: 'text' }, + value: { type: 'integer' }, + }, + }, + migrations: {}, + }, + ]; + + const savedObjects = [ + { + id: 'complex:4baf4de0-a6d4-11ed-ba5a-39196fc76e60', + body: { + type: 'complex', + complex: { + name: 'foo', + value: 5, + }, + references: [], + coreMigrationVersion: currentVersion, + updated_at: '2023-02-07T11:04:44.914Z', + created_at: '2023-02-07T11:04:44.914Z', + }, + }, + { + id: 'corrupt:2baf4de0-a6d4-11ed-ba5a-39196fc76e60', // incorrect id => corrupt object + body: { + type: 'complex', + complex: { + name: 'bar', + value: 3, + }, + references: [], + coreMigrationVersion: currentVersion, + updated_at: '2023-02-07T11:04:44.914Z', + created_at: '2023-02-07T11:04:44.914Z', + }, + }, + ]; + + const { migrator: baselineMigrator, client } = await getKibanaMigratorTestKit({ + types: typesCurrent, + logFilePath, + }); + + baselineMigrator.prepareMigrations(); + await baselineMigrator.runMigrations(); + + // inject corrupt saved objects directly using esClient + await Promise.all( + savedObjects.map((savedObject) => { + client.create({ + index: defaultKibanaIndex, + refresh: 'wait_for', + ...savedObject, + }); + }) + ); + + return client; +}; + +const setupNextMinor = async () => { + const typesNextMinor: SavedObjectsType[] = [ + { + name: 'complex', + hidden: false, + namespaceType: 'agnostic', + mappings: { + properties: { + name: { type: 'keyword' }, + value: { type: 'long' }, + }, + }, + migrations: { + [nextMinor]: (doc) => doc, + }, + }, + ]; + + const { migrator, client } = await getKibanaMigratorTestKit({ + types: typesNextMinor, + kibanaVersion: nextMinor, + logFilePath, + settings: { + migrations: { + skip: false, + }, + logging: { + appenders: { + file: { + type: 'file', + fileName: logFilePath, + layout: { + type: 'json', + }, + }, + }, + loggers: [ + { + name: 'root', + appenders: ['file'], + level: 'debug', // DEBUG logs are required to retrieve the PIT _id from the action response logs + }, + ], + }, + }, + }); + + return { migrator, client }; +}; diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts index f4577c0379096..51e3c7ce53fe0 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/multiple_kibana_nodes.test.ts @@ -112,7 +112,7 @@ describe('migration v2', () => { let rootB: Root; let rootC: Root; - const migratedIndex = `.kibana_${pkg.version}_001`; + const migratedIndexAlias = `.kibana_${pkg.version}`; const fooType: SavedObjectsType = { name: 'foo', hidden: false, @@ -189,7 +189,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 0); const esClient = esServer.es.getClient(); - const migratedDocs = await fetchDocs(esClient, migratedIndex); + const migratedDocs = await fetchDocs(esClient, migratedIndexAlias); expect(migratedDocs.length).toBe(5000); @@ -208,7 +208,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 1); const esClient = esServer.es.getClient(); - const migratedDocs = await fetchDocs(esClient, migratedIndex); + const migratedDocs = await fetchDocs(esClient, migratedIndexAlias); expect(migratedDocs.length).toBe(5000); @@ -227,7 +227,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 5); const esClient = esServer.es.getClient(); - const migratedDocs = await fetchDocs(esClient, migratedIndex); + const migratedDocs = await fetchDocs(esClient, migratedIndexAlias); expect(migratedDocs.length).toBe(5000); @@ -246,7 +246,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 20); const esClient = esServer.es.getClient(); - const migratedDocs = await fetchDocs(esClient, migratedIndex); + const migratedDocs = await fetchDocs(esClient, migratedIndexAlias); expect(migratedDocs.length).toBe(5000); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group2/outdated_docs.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group2/outdated_docs.test.ts index 119ee16e9cddc..5c9ee13f3f825 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group2/outdated_docs.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group2/outdated_docs.test.ts @@ -46,7 +46,7 @@ describe('migration v2', () => { }); it('migrates the documents to the highest version', async () => { - const migratedIndex = `.kibana_${pkg.version}_001`; + const migratedIndexAlias = `.kibana_${pkg.version}`; const { startES } = createTestServers({ adjustTimeout: (t: number) => jest.setTimeout(t), settings: { @@ -90,7 +90,7 @@ describe('migration v2', () => { const coreStart = await root.start(); const esClient = coreStart.elasticsearch.client.asInternalUser; - const migratedDocs = await fetchDocs(esClient, migratedIndex); + const migratedDocs = await fetchDocs(esClient, migratedIndexAlias); expect(migratedDocs.length).toBe(1); const [doc] = migratedDocs; diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts index 691800feee0e3..64592be985719 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions.test.ts @@ -34,7 +34,7 @@ import { type UpdateByQueryResponse, updateAndPickupMappings, type UpdateAndPickupMappingsResponse, - updateTargetMappingsMeta, + updateMappings, removeWriteBlock, transformDocs, waitForIndexStatus, @@ -71,7 +71,11 @@ describe('migration actions', () => { indexName: 'existing_index_with_docs', mappings: { dynamic: true, - properties: {}, + properties: { + someProperty: { + type: 'integer', + }, + }, _meta: { migrationMappingPropertyHashes: { references: '7997cf5a56cc02bdc9c93361bde732b0', @@ -1486,15 +1490,22 @@ describe('migration actions', () => { }); }); - describe('updateTargetMappingsMeta', () => { + describe('updateMappings', () => { it('rejects if ES throws an error', async () => { - const task = updateTargetMappingsMeta({ + const task = updateMappings({ client, index: 'no_such_index', - meta: { - migrationMappingPropertyHashes: { - references: 'updateda56cc02bdc9c93361bupdated', - newReferences: 'fooBarHashMd509387420934879300d9', + mappings: { + properties: { + created_at: { + type: 'date', + }, + }, + _meta: { + migrationMappingPropertyHashes: { + references: 'updateda56cc02bdc9c93361bupdated', + newReferences: 'fooBarHashMd509387420934879300d9', + }, }, }, })(); @@ -1502,13 +1513,51 @@ describe('migration actions', () => { await expect(task).rejects.toThrow('index_not_found_exception'); }); - it('resolves right when mappings._meta are correctly updated', async () => { - const res = await updateTargetMappingsMeta({ + it('resolves left when the mappings are incompatible', async () => { + const res = await updateMappings({ client, index: 'existing_index_with_docs', - meta: { - migrationMappingPropertyHashes: { - newReferences: 'fooBarHashMd509387420934879300d9', + mappings: { + properties: { + someProperty: { + type: 'date', // attempt to change an existing field's type in an incompatible fashion + }, + }, + _meta: { + migrationMappingPropertyHashes: { + references: 'updateda56cc02bdc9c93361bupdated', + newReferences: 'fooBarHashMd509387420934879300d9', + }, + }, + }, + })(); + + expect(Either.isLeft(res)).toBe(true); + expect(res).toMatchInlineSnapshot(` + Object { + "_tag": "Left", + "left": Object { + "type": "incompatible_mapping_exception", + }, + } + `); + }); + + it('resolves right when mappings are correctly updated', async () => { + const res = await updateMappings({ + client, + index: 'existing_index_with_docs', + mappings: { + properties: { + created_at: { + type: 'date', + }, + }, + _meta: { + migrationMappingPropertyHashes: { + references: 'updateda56cc02bdc9c93361bupdated', + newReferences: 'fooBarHashMd509387420934879300d9', + }, }, }, })(); @@ -1519,8 +1568,17 @@ describe('migration actions', () => { index: ['existing_index_with_docs'], }); + expect(indices.existing_index_with_docs.mappings?.properties).toEqual( + expect.objectContaining({ + created_at: { + type: 'date', + }, + }) + ); + expect(indices.existing_index_with_docs.mappings?._meta).toEqual({ migrationMappingPropertyHashes: { + references: 'updateda56cc02bdc9c93361bupdated', newReferences: 'fooBarHashMd509387420934879300d9', }, }); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.test.ts index 80681ffd0a5af..793ed9d100685 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/active_delete.test.ts @@ -6,56 +6,28 @@ * Side Public License, v 1. */ -import Path from 'path'; -import fs from 'fs/promises'; -import { SemVer } from 'semver'; -import { Env } from '@kbn/config'; -import type { AggregationsAggregate, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; -import { getEnvOptions } from '@kbn/config-mocks'; -import { REPO_ROOT } from '@kbn/repo-info'; -import { createTestServers, type TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; -import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; -import { getKibanaMigratorTestKit } from '../kibana_migrator_test_kit'; -import { baselineDocuments, baselineTypes } from './active_delete.fixtures'; +import { AggregationsAggregate, SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import { TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; +import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { + readLog, + clearLog, + nextMinor, + createBaseline, + currentVersion, + defaultKibanaIndex, + startElasticsearch, + getCompatibleMappingsMigrator, + getIdenticalMappingsMigrator, + getIncompatibleMappingsMigrator, + getNonDeprecatedMappingsMigrator, +} from '../kibana_migrator_test_kit'; import { delay } from '../test_utils'; -const kibanaIndex = '.kibana_migrator_tests'; -export const logFilePath = Path.join(__dirname, 'active_delete.test.log'); -const currentVersion = Env.createDefault(REPO_ROOT, getEnvOptions()).packageInfo.version; -const nextMinor = new SemVer(currentVersion).inc('minor').format(); - describe('when upgrading to a new stack version', () => { let esServer: TestElasticsearchUtils['es']; let esClient: ElasticsearchClient; - const startElasticsearch = async () => { - const { startES } = createTestServers({ - adjustTimeout: (t: number) => jest.setTimeout(t), - settings: { - es: { - license: 'basic', - }, - }, - }); - return await startES(); - }; - - const createBaseline = async () => { - const { client, runMigrations, savedObjectsRepository } = await getKibanaMigratorTestKit({ - kibanaIndex, - types: baselineTypes, - }); - - await runMigrations(); - - await savedObjectsRepository.bulkCreate(baselineDocuments, { - refresh: 'wait_for', - }); - - return client; - }; - beforeAll(async () => { esServer = await startElasticsearch(); }); @@ -65,92 +37,66 @@ describe('when upgrading to a new stack version', () => { await delay(10); }); - describe('and the mappings match (diffMappings() === false)', () => { + describe('if the mappings match (diffMappings() === false)', () => { describe('and discardUnknownObjects = true', () => { let indexContents: SearchResponse<{ type: string }, Record>; beforeAll(async () => { esClient = await createBaseline(); - await fs.unlink(logFilePath).catch(() => {}); + await clearLog(); // remove the 'deprecated' type from the mappings, so that it is considered unknown - const types = baselineTypes.filter((type) => type.name !== 'deprecated'); - const { client, runMigrations } = await getKibanaMigratorTestKit({ + const { client, runMigrations } = await getNonDeprecatedMappingsMigrator({ settings: { migrations: { discardUnknownObjects: nextMinor, }, }, - kibanaIndex, - types, - kibanaVersion: nextMinor, - logFilePath, }); await runMigrations(); - indexContents = await client.search({ index: kibanaIndex, size: 100 }); + indexContents = await client.search({ index: defaultKibanaIndex, size: 100 }); }); afterAll(async () => { - await esClient?.indices.delete({ index: `${kibanaIndex}_${currentVersion}_001` }); + await esClient?.indices.delete({ index: `${defaultKibanaIndex}_${currentVersion}_001` }); }); it('the migrator is skipping reindex operation and executing CLEANUP_UNKNOWN_AND_EXCLUDED step', async () => { - const logs = await fs.readFile(logFilePath, 'utf-8'); - expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); - expect(logs).toMatch( - '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED' - ); + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED'); // we gotta inform that we are deleting unknown documents too (discardUnknownObjects: true) expect(logs).toMatch( - '[.kibana_migrator_tests] Kibana has been configured to discard unknown documents for this migration.' + 'Kibana has been configured to discard unknown documents for this migration.' ); - expect(logs).toMatch( 'Therefore, the following documents with unknown types will not be taken into account and they will not be available after the migration:' ); expect(logs).toMatch( - '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK' - ); - expect(logs).toMatch( - '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION' - ); - expect(logs).toMatch( - '[.kibana_migrator_tests] PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET' - ); - expect(logs).toMatch( - '[.kibana_migrator_tests] REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT' + 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK' ); expect(logs).toMatch( - '[.kibana_migrator_tests] CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS' + 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION' ); - expect(logs).toMatch('[.kibana_migrator_tests] CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); + expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET'); + expect(logs).toMatch('REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); }); describe('CLEANUP_UNKNOWN_AND_EXCLUDED', () => { it('preserves documents with known types', async () => { - const basicDocumentCount = indexContents.hits.hits.filter( - (result) => result._source?.type === 'basic' - ).length; - - expect(basicDocumentCount).toEqual(3); + expect(countResultsByType(indexContents, 'basic')).toEqual(3); }); it('deletes documents with unknown types', async () => { - const deprecatedDocumentCount = indexContents.hits.hits.filter( - (result) => result._source?.type === 'deprecated' - ).length; - - expect(deprecatedDocumentCount).toEqual(0); + expect(countResultsByType(indexContents, 'deprecated')).toEqual(0); }); it('deletes documents that belong to REMOVED_TYPES', async () => { - const serverDocumentCount = indexContents.hits.hits.filter( - (result) => result._source?.type === 'server' - ).length; - - expect(serverDocumentCount).toEqual(0); + expect(countResultsByType(indexContents, 'server')).toEqual(0); }); it("deletes documents that have been excludeOnUpgrade'd via plugin hook", async () => { @@ -186,21 +132,15 @@ describe('when upgrading to a new stack version', () => { esClient = await createBaseline(); }); afterAll(async () => { - await esClient?.indices.delete({ index: `${kibanaIndex}_${currentVersion}_001` }); + await esClient?.indices.delete({ index: `${defaultKibanaIndex}_${currentVersion}_001` }); }); beforeEach(async () => { - await fs.unlink(logFilePath).catch(() => {}); + await clearLog(); }); it('fails if unknown documents exist', async () => { - // remove the 'deprecated' type from the mappings, so that SO of this type are considered unknown - const types = baselineTypes.filter((type) => type.name !== 'deprecated'); - const { runMigrations } = await getKibanaMigratorTestKit({ - kibanaIndex, - types, - kibanaVersion: nextMinor, - logFilePath, - }); + // remove the 'deprecated' type from the mappings, so that it is considered unknown + const { runMigrations } = await getNonDeprecatedMappingsMigrator(); try { await runMigrations(); @@ -215,121 +155,237 @@ describe('when upgrading to a new stack version', () => { expect(errorMessage).toMatch(/deprecated:.*\(type: "deprecated"\)/); } - const logs = await fs.readFile(logFilePath, 'utf-8'); - expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED.'); + expect(logs).toMatch('CLEANUP_UNKNOWN_AND_EXCLUDED -> FATAL.'); + }); + + it('proceeds if there are no unknown documents', async () => { + const { client, runMigrations } = await getIdenticalMappingsMigrator(); + + await runMigrations(); + + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED.'); + expect(logs).toMatch( + 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK.' + ); expect(logs).toMatch( - '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED' + 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION.' ); - expect(logs).toMatch('[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED -> FATAL'); + expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET.'); + expect(logs).toMatch('REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT.'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE.'); + + const indexContents = await client.search({ index: defaultKibanaIndex, size: 100 }); + expect(indexContents.hits.hits.length).toEqual(8); }); + }); + }); - it('proceeds if there are no unknown documents', async () => { - const { client, runMigrations } = await getKibanaMigratorTestKit({ - kibanaIndex, - types: baselineTypes, - kibanaVersion: nextMinor, - logFilePath, + describe('if the mappings are compatible', () => { + describe('and discardUnknownObjects = true', () => { + let indexContents: SearchResponse<{ type: string }, Record>; + + beforeAll(async () => { + esClient = await createBaseline(); + + await clearLog(); + const { client, runMigrations } = await getCompatibleMappingsMigrator({ + filterDeprecated: true, // remove the 'deprecated' type from the mappings, so that it is considered unknown + settings: { + migrations: { + discardUnknownObjects: nextMinor, + }, + }, }); await runMigrations(); - const logs = await fs.readFile(logFilePath, 'utf-8'); - expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); + indexContents = await client.search({ index: defaultKibanaIndex, size: 100 }); + }); + + afterAll(async () => { + await esClient?.indices.delete({ index: `${defaultKibanaIndex}_${currentVersion}_001` }); + }); + + it('the migrator is skipping reindex operation and executing CLEANUP_UNKNOWN_AND_EXCLUDED step', async () => { + const logs = await readLog(); + + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS.'); + // this step is run only if mappings are compatible but NOT equal + expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS -> CLEANUP_UNKNOWN_AND_EXCLUDED.'); + // we gotta inform that we are deleting unknown documents too (discardUnknownObjects: true), expect(logs).toMatch( - '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED' + 'Kibana has been configured to discard unknown documents for this migration.' ); expect(logs).toMatch( - '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK' + 'Therefore, the following documents with unknown types will not be taken into account and they will not be available after the migration:' ); expect(logs).toMatch( - '[.kibana_migrator_tests] CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION' + 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK.' ); expect(logs).toMatch( - '[.kibana_migrator_tests] PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET' + 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION.' ); + expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET.'); + expect(logs).toMatch('REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT.'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS.'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE.'); + }); + + describe('CLEANUP_UNKNOWN_AND_EXCLUDED', () => { + it('preserves documents with known types', async () => { + expect(countResultsByType(indexContents, 'basic')).toEqual(3); + }); + + it('deletes documents with unknown types', async () => { + expect(countResultsByType(indexContents, 'deprecated')).toEqual(0); + }); + + it('deletes documents that belong to REMOVED_TYPES', async () => { + expect(countResultsByType(indexContents, 'server')).toEqual(0); + }); + + it("deletes documents that have been excludeOnUpgrade'd via plugin hook", async () => { + const complexDocuments = indexContents.hits.hits.filter( + (result) => result._source?.type === 'complex' + ); + + expect(complexDocuments.length).toEqual(2); + expect(complexDocuments[0]._source).toEqual( + expect.objectContaining({ + complex: { + name: 'complex-baz', + value: 2, + }, + type: 'complex', + }) + ); + expect(complexDocuments[1]._source).toEqual( + expect.objectContaining({ + complex: { + name: 'complex-lipsum', + value: 3, + }, + type: 'complex', + }) + ); + }); + }); + }); + + describe('and discardUnknownObjects = false', () => { + beforeAll(async () => { + esClient = await createBaseline(); + }); + afterAll(async () => { + await esClient?.indices.delete({ index: `${defaultKibanaIndex}_${currentVersion}_001` }); + }); + beforeEach(async () => { + await clearLog(); + }); + + it('fails if unknown documents exist', async () => { + const { runMigrations } = await getCompatibleMappingsMigrator({ + filterDeprecated: true, // remove the 'deprecated' type from the mappings, so that it is considered unknown + }); + + try { + await runMigrations(); + } catch (err) { + const errorMessage = err.message; + expect(errorMessage).toMatch( + 'Unable to complete saved object migrations for the [.kibana_migrator_tests] index: Migration failed because some documents were found which use unknown saved object types:' + ); + expect(errorMessage).toMatch( + 'To proceed with the migration you can configure Kibana to discard unknown saved objects for this migration.' + ); + expect(errorMessage).toMatch(/deprecated:.*\(type: "deprecated"\)/); + } + + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS.'); // this step is run only if mappings are compatible but NOT equal + expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS -> CLEANUP_UNKNOWN_AND_EXCLUDED.'); + expect(logs).toMatch('CLEANUP_UNKNOWN_AND_EXCLUDED -> FATAL.'); + }); + + it('proceeds if there are no unknown documents', async () => { + const { client, runMigrations } = await getCompatibleMappingsMigrator(); + + await runMigrations(); + + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS.'); + expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS -> CLEANUP_UNKNOWN_AND_EXCLUDED.'); expect(logs).toMatch( - '[.kibana_migrator_tests] REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT' + 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK.' ); expect(logs).toMatch( - '[.kibana_migrator_tests] CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS' + 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION.' ); - expect(logs).toMatch('[.kibana_migrator_tests] CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); + expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET.'); + expect(logs).toMatch('REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT.'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS.'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE.'); - const indexContents = await client.search({ index: kibanaIndex, size: 100 }); + const indexContents = await client.search({ index: defaultKibanaIndex, size: 100 }); expect(indexContents.hits.hits.length).toEqual(8); }); }); }); - describe('and the mappings do NOT match (diffMappings() === true)', () => { + describe('if the mappings do NOT match (diffMappings() === true) and they are NOT compatible', () => { beforeAll(async () => { esClient = await createBaseline(); }); afterAll(async () => { - await esClient?.indices.delete({ index: `${kibanaIndex}_${currentVersion}_001` }); + await esClient?.indices.delete({ index: `${defaultKibanaIndex}_${currentVersion}_001` }); }); beforeEach(async () => { - await fs.unlink(logFilePath).catch(() => {}); + await clearLog(); }); it('the migrator does not skip reindexing', async () => { - const incompatibleTypes: Array> = baselineTypes.map((type) => { - if (type.name === 'complex') { - return { - ...type, - mappings: { - properties: { - name: { type: 'keyword' }, // text => keyword - value: { type: 'long' }, // integer => long - }, - }, - }; - } else { - return type; - } - }); - - const { client, runMigrations } = await getKibanaMigratorTestKit({ - kibanaIndex, - types: incompatibleTypes, - kibanaVersion: nextMinor, - logFilePath, - }); + const { client, runMigrations } = await getIncompatibleMappingsMigrator(); await runMigrations(); - const logs = await fs.readFile(logFilePath, 'utf-8'); - expect(logs).toMatch('[.kibana_migrator_tests] INIT -> WAIT_FOR_YELLOW_SOURCE'); - expect(logs).toMatch( - '[.kibana_migrator_tests] WAIT_FOR_YELLOW_SOURCE -> CHECK_UNKNOWN_DOCUMENTS.' - ); - expect(logs).toMatch( - '[.kibana_migrator_tests] CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK.' - ); - expect(logs).toMatch( - '[.kibana_migrator_tests] CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS.' - ); - expect(logs).toMatch( - '[.kibana_migrator_tests] UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.' - ); - expect(logs).toMatch( - '[.kibana_migrator_tests] CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY.' - ); - expect(logs).toMatch('[.kibana_migrator_tests] MARK_VERSION_INDEX_READY -> DONE'); + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS.'); + expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS -> CHECK_UNKNOWN_DOCUMENTS.'); + expect(logs).toMatch('CHECK_UNKNOWN_DOCUMENTS -> SET_SOURCE_WRITE_BLOCK.'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS.'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY.'); + expect(logs).toMatch('MARK_VERSION_INDEX_READY -> DONE'); const indexContents: SearchResponse< { type: string }, Record - > = await client.search({ index: kibanaIndex, size: 100 }); + > = await client.search({ index: defaultKibanaIndex, size: 100 }); expect(indexContents.hits.hits.length).toEqual(8); // we're removing a couple of 'complex' (value < = 1) // double-check that the deprecated documents have not been deleted - const deprecatedDocumentCount = indexContents.hits.hits.filter( - (result) => result._source?.type === 'deprecated' - ).length; - expect(deprecatedDocumentCount).toEqual(3); + expect(countResultsByType(indexContents, 'deprecated')).toEqual(3); }); }); }); + +const countResultsByType = ( + indexContents: SearchResponse<{ type: string }, Record>, + type: string +): number => { + return indexContents.hits.hits.filter((result) => result._source?.type === type).length; +}; diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/multiple_es_nodes.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/multiple_es_nodes.test.ts index 5cb4028eba2ca..1240f5873e3a0 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/multiple_es_nodes.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/multiple_es_nodes.test.ts @@ -97,7 +97,7 @@ function createRoot({ logFileName, hosts }: RootConfig) { describe('migration v2', () => { let esServer: TestElasticsearchUtils; let root: Root; - const migratedIndex = `.kibana_${pkg.version}_001`; + const migratedIndexAlias = `.kibana_${pkg.version}`; beforeAll(async () => { await removeLogFile(); @@ -186,7 +186,7 @@ describe('migration v2', () => { await root.start(); const esClient = esServer.es.getClient(); - const migratedFooDocs = await fetchDocs(esClient, migratedIndex, 'foo'); + const migratedFooDocs = await fetchDocs(esClient, migratedIndexAlias, 'foo'); expect(migratedFooDocs.length).toBe(2500); migratedFooDocs.forEach((doc, i) => { expect(doc.id).toBe(`foo:${i}`); @@ -194,7 +194,7 @@ describe('migration v2', () => { expect(doc.migrationVersion.foo).toBe('7.14.0'); }); - const migratedBarDocs = await fetchDocs(esClient, migratedIndex, 'bar'); + const migratedBarDocs = await fetchDocs(esClient, migratedIndexAlias, 'bar'); expect(migratedBarDocs.length).toBe(2500); migratedBarDocs.forEach((doc, i) => { expect(doc.id).toBe(`bar:${i}`); diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/rewriting_id.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/rewriting_id.test.ts index ae90b81482f4c..88193063d5526 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/rewriting_id.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/rewriting_id.test.ts @@ -113,7 +113,7 @@ describe('migration v2', () => { }); it('rewrites id deterministically for SO with namespaceType: "multiple" and "multiple-isolated"', async () => { - const migratedIndex = `.kibana_${pkg.version}_001`; + const migratedIndexAlias = `.kibana_${pkg.version}`; const { startES } = createTestServers({ adjustTimeout: (t: number) => jest.setTimeout(t), settings: { @@ -172,7 +172,7 @@ describe('migration v2', () => { const coreStart = await root.start(); const esClient = coreStart.elasticsearch.client.asInternalUser; - const migratedDocs = await fetchDocs(esClient, migratedIndex); + const migratedDocs = await fetchDocs(esClient, migratedIndexAlias); // each newly converted multi-namespace object in a non-default space has its ID deterministically regenerated, and a legacy-url-alias // object is created which links the old ID to the new ID diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts index aa5d1c0c06eb4..5354a958e8cb7 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/skip_reindex.test.ts @@ -5,121 +5,137 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import Path from 'path'; -import fs from 'fs/promises'; -import { Env } from '@kbn/config'; -import { getEnvOptions } from '@kbn/config-mocks'; -import { REPO_ROOT } from '@kbn/repo-info'; -import type { Root } from '@kbn/core-root-server-internal'; + +import { type TestElasticsearchUtils } from '@kbn/core-test-helpers-kbn-server'; +import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; +import { IKibanaMigrator } from '@kbn/core-saved-objects-base-server-internal'; import { - createRootWithCorePlugins, - createTestServers, - type TestElasticsearchUtils, -} from '@kbn/core-test-helpers-kbn-server'; + readLog, + clearLog, + createBaseline, + currentVersion, + defaultKibanaIndex, + getCompatibleMappingsMigrator, + getIdenticalMappingsMigrator, + getIncompatibleMappingsMigrator, + startElasticsearch, +} from '../kibana_migrator_test_kit'; import { delay } from '../test_utils'; -import { SemVer } from 'semver'; - -const logFilePath = Path.join(__dirname, 'skip_reindex.log'); -describe('skip reindexing', () => { - const currentVersion = Env.createDefault(REPO_ROOT, getEnvOptions()).packageInfo.version; +describe('when migrating to a new version', () => { let esServer: TestElasticsearchUtils['es']; - let root: Root; + let esClient: ElasticsearchClient; + let migrator: IKibanaMigrator; - afterEach(async () => { - await root?.shutdown(); - await esServer?.stop(); - await delay(10); + beforeAll(async () => { + esServer = await startElasticsearch(); + }); + + beforeEach(async () => { + esClient = await createBaseline(); + await clearLog(); }); - it('when migrating to a new version, but mappings remain the same', async () => { - let logs: string; - const { startES } = createTestServers({ - adjustTimeout: (t: number) => jest.setTimeout(t), - settings: { - es: { - license: 'basic', - }, - }, + describe('and the mappings remain the same', () => { + it('the migrator skips reindexing', async () => { + // we run the migrator with the same identic baseline types + migrator = (await getIdenticalMappingsMigrator()).migrator; + migrator.prepareMigrations(); + await migrator.runMigrations(); + + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED.'); + expect(logs).toMatch( + 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK.' + ); + expect(logs).toMatch( + 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION.' + ); + expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET.'); + expect(logs).toMatch('REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT.'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE.'); + + expect(logs).not.toMatch('CREATE_NEW_TARGET'); + expect(logs).not.toMatch('CHECK_UNKNOWN_DOCUMENTS'); + expect(logs).not.toMatch('REINDEX'); + expect(logs).not.toMatch('UPDATE_TARGET_MAPPINGS'); }); - esServer = await startES(); - root = createRoot(); + }); - // Run initial migrations - await root.preboot(); - await root.setup(); - await root.start(); + describe("and the mappings' changes are still compatible", () => { + it('the migrator skips reindexing', async () => { + // we run the migrator with altered, compatible mappings + migrator = (await getCompatibleMappingsMigrator()).migrator; + migrator.prepareMigrations(); + await migrator.runMigrations(); - // stop Kibana and remove logs - await root.shutdown(); - await delay(10); - await fs.unlink(logFilePath).catch(() => {}); - - const nextPatch = new SemVer(currentVersion).inc('patch').format(); - root = createRoot(nextPatch); - await root.preboot(); - await root.setup(); - await root.start(); - - logs = await fs.readFile(logFilePath, 'utf-8'); - - expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE'); - expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> CLEANUP_UNKNOWN_AND_EXCLUDED'); - expect(logs).toMatch( - 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK' - ); - expect(logs).toMatch( - 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION' - ); - expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT'); - expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS'); - expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE'); + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS.'); + expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS -> CLEANUP_UNKNOWN_AND_EXCLUDED.'); + expect(logs).toMatch( + 'CLEANUP_UNKNOWN_AND_EXCLUDED -> CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK.' + ); + expect(logs).toMatch( + 'CLEANUP_UNKNOWN_AND_EXCLUDED_WAIT_FOR_TASK -> PREPARE_COMPATIBLE_MIGRATION.' + ); + expect(logs).toMatch('PREPARE_COMPATIBLE_MIGRATION -> REFRESH_TARGET.'); + expect(logs).toMatch('REFRESH_TARGET -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT.'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS.'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE.'); - expect(logs).not.toMatch('CREATE_NEW_TARGET'); - expect(logs).not.toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS'); + expect(logs).not.toMatch('CREATE_NEW_TARGET'); + expect(logs).not.toMatch('CHECK_UNKNOWN_DOCUMENTS'); + expect(logs).not.toMatch('REINDEX'); + }); + }); - // We restart Kibana again after doing a "compatible migration" to ensure that - // the next time state is loaded everything still works as expected. - // For instance, we might see something like: - // Unable to complete saved object migrations for the [.kibana] index. Please check the health of your Elasticsearch cluster and try again. Unexpected Elasticsearch ResponseError: statusCode: 404, method: POST, url: /.kibana_8.7.1_001/_pit?keep_alive=10m error: [index_not_found_exception]: no such index [.kibana_8.7.1_001] - await root.shutdown(); - await delay(10); - await fs.unlink(logFilePath).catch(() => {}); + describe("and the mappings' changes are NOT compatible", () => { + it('the migrator reindexes documents to a new index', async () => { + // we run the migrator with altered, compatible mappings + migrator = (await getIncompatibleMappingsMigrator()).migrator; + migrator.prepareMigrations(); + await migrator.runMigrations(); - root = createRoot(nextPatch); - await root.preboot(); - await root.setup(); - await root.start(); + const logs = await readLog(); + expect(logs).toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE.'); + expect(logs).toMatch('WAIT_FOR_YELLOW_SOURCE -> UPDATE_SOURCE_MAPPINGS.'); + expect(logs).toMatch('UPDATE_SOURCE_MAPPINGS -> CHECK_UNKNOWN_DOCUMENTS.'); + expect(logs).toMatch('CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS.'); + expect(logs).toMatch('UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY.'); + expect(logs).toMatch('MARK_VERSION_INDEX_READY -> DONE.'); - logs = await fs.readFile(logFilePath, 'utf-8'); - expect(logs).toMatch('INIT -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT'); - expect(logs).not.toMatch('INIT -> WAIT_FOR_YELLOW_SOURCE'); + expect(logs).not.toMatch('CREATE_NEW_TARGET'); + expect(logs).not.toMatch('CLEANUP_UNKNOWN_AND_EXCLUDED'); + expect(logs).not.toMatch('PREPARE_COMPATIBLE_MIGRATION'); + }); + }); + + afterEach(async () => { + // we run the migrator again to ensure that the next time state is loaded everything still works as expected + await clearLog(); + await migrator.runMigrations({ rerun: true }); + + const logs = await readLog(); + expect(logs).toMatch('INIT -> OUTDATED_DOCUMENTS_SEARCH_OPEN_PIT.'); + expect(logs).toMatch('CHECK_VERSION_INDEX_READY_ACTIONS -> DONE.'); + + expect(logs).not.toMatch('WAIT_FOR_YELLOW_SOURCE'); + expect(logs).not.toMatch('CLEANUP_UNKNOWN_AND_EXCLUCED'); + expect(logs).not.toMatch('CREATE_NEW_TARGET'); + expect(logs).not.toMatch('PREPARE_COMPATIBLE_MIGRATION'); + expect(logs).not.toMatch('UPDATE_TARGET_MAPPINGS'); + + // clear the system index for next test + await esClient?.indices.delete({ index: `${defaultKibanaIndex}_${currentVersion}_001` }); }); -}); -function createRoot(kibanaVersion?: string): Root { - return createRootWithCorePlugins( - { - logging: { - appenders: { - file: { - type: 'file', - fileName: logFilePath, - layout: { - type: 'json', - }, - }, - }, - loggers: [ - { - name: 'root', - level: 'info', - appenders: ['file'], - }, - ], - }, - }, - { oss: true }, - kibanaVersion - ); -} + afterAll(async () => { + await esServer?.stop(); + await delay(10); + }); +}); diff --git a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts new file mode 100644 index 0000000000000..7d605cf116341 --- /dev/null +++ b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { SavedObjectsBulkCreateObject } from '@kbn/core-saved-objects-api-server'; +import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; + +const defaultType: SavedObjectsType = { + name: 'defaultType', + hidden: false, + namespaceType: 'agnostic', + mappings: { + properties: { + name: { type: 'keyword' }, + }, + }, + migrations: {}, +}; + +export const baselineTypes: Array> = [ + { + ...defaultType, + name: 'server', + }, + { + ...defaultType, + name: 'basic', + }, + { + ...defaultType, + name: 'deprecated', + }, + { + ...defaultType, + name: 'complex', + mappings: { + properties: { + name: { type: 'text' }, + value: { type: 'integer' }, + }, + }, + excludeOnUpgrade: () => { + return { + bool: { + must: [{ term: { type: 'complex' } }, { range: { 'complex.value': { lte: 1 } } }], + }, + }; + }, + }, +]; + +export const baselineDocuments: SavedObjectsBulkCreateObject[] = [ + ...['server-foo', 'server-bar', 'server-baz'].map((name) => ({ + type: 'server', + attributes: { + name, + }, + })), + ...['basic-foo', 'basic-bar', 'basic-baz'].map((name) => ({ + type: 'basic', + attributes: { + name, + }, + })), + ...['deprecated-foo', 'deprecated-bar', 'deprecated-baz'].map((name) => ({ + type: 'deprecated', + attributes: { + name, + }, + })), + ...['complex-foo', 'complex-bar', 'complex-baz', 'complex-lipsum'].map((name, index) => ({ + type: 'complex', + attributes: { + name, + value: index, + }, + })), +]; diff --git a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts index df3cce7dbdca6..f6760aa3264fc 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.ts @@ -7,6 +7,9 @@ */ import Path from 'path'; +import fs from 'fs/promises'; +import { SemVer } from 'semver'; + import { defaultsDeep } from 'lodash'; import { BehaviorSubject, firstValueFrom, map } from 'rxjs'; import { ConfigService, Env } from '@kbn/config'; @@ -19,8 +22,8 @@ import { type SavedObjectsConfigType, type SavedObjectsMigrationConfigType, SavedObjectTypeRegistry, - IKibanaMigrator, - MigrationResult, + type IKibanaMigrator, + type MigrationResult, } from '@kbn/core-saved-objects-base-server-internal'; import { SavedObjectsRepository } from '@kbn/core-saved-objects-api-server-internal'; import { @@ -32,20 +35,23 @@ import { type LoggingConfigType, LoggingSystem } from '@kbn/core-logging-server- import type { ISavedObjectTypeRegistry, SavedObjectsType } from '@kbn/core-saved-objects-server'; import { esTestConfig, kibanaServerTestUser } from '@kbn/test'; -import { LoggerFactory } from '@kbn/logging'; +import type { LoggerFactory } from '@kbn/logging'; +import { createTestServers } from '@kbn/core-test-helpers-kbn-server'; import type { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { registerServiceConfig } from '@kbn/core-root-server-internal'; -import { ISavedObjectsRepository } from '@kbn/core-saved-objects-api-server'; +import type { ISavedObjectsRepository } from '@kbn/core-saved-objects-api-server'; import { getDocLinks, getDocLinksMeta } from '@kbn/doc-links'; -import { DocLinksServiceStart } from '@kbn/core-doc-links-server'; -import { createTestServers } from '@kbn/core-test-helpers-kbn-server'; +import type { DocLinksServiceStart } from '@kbn/core-doc-links-server'; +import { baselineDocuments, baselineTypes } from './kibana_migrator_test_kit.fixtures'; export const defaultLogFilePath = Path.join(__dirname, 'kibana_migrator_test_kit.log'); const env = Env.createDefault(REPO_ROOT, getEnvOptions()); // Extract current stack version from Env, to use as a default -const currentVersion = env.packageInfo.version; -const currentBranch = env.packageInfo.branch; +export const currentVersion = env.packageInfo.version; +export const nextMinor = new SemVer(currentVersion).inc('minor').format(); +export const currentBranch = env.packageInfo.branch; +export const defaultKibanaIndex = '.kibana_migrator_tests'; export interface GetEsClientParams { settings?: Record; @@ -76,7 +82,7 @@ export const startElasticsearch = async ({ }: { basePath?: string; dataArchive?: string; -}) => { +} = {}) => { const { startES } = createTestServers({ adjustTimeout: (t: number) => jest.setTimeout(t), settings: { @@ -109,7 +115,7 @@ export const getEsClient = async ({ export const getKibanaMigratorTestKit = async ({ settings = {}, - kibanaIndex = '.kibana', + kibanaIndex = defaultKibanaIndex, kibanaVersion = currentVersion, kibanaBranch = currentBranch, types = [], @@ -272,3 +278,113 @@ const registerTypes = ( ) => { (types || []).forEach((type) => typeRegistry.registerType(type)); }; + +export const createBaseline = async () => { + const { client, migrator, savedObjectsRepository } = await getKibanaMigratorTestKit({ + kibanaIndex: defaultKibanaIndex, + types: baselineTypes, + }); + + migrator.prepareMigrations(); + await migrator.runMigrations(); + + await savedObjectsRepository.bulkCreate(baselineDocuments, { + refresh: 'wait_for', + }); + + return client; +}; + +interface GetMutatedMigratorParams { + kibanaVersion?: string; + settings?: Record; +} + +export const getIdenticalMappingsMigrator = async ({ + kibanaVersion = nextMinor, + settings = {}, +}: GetMutatedMigratorParams = {}) => { + return await getKibanaMigratorTestKit({ + types: baselineTypes, + kibanaVersion, + settings, + }); +}; + +export const getNonDeprecatedMappingsMigrator = async ({ + kibanaVersion = nextMinor, + settings = {}, +}: GetMutatedMigratorParams = {}) => { + return await getKibanaMigratorTestKit({ + types: baselineTypes.filter((type) => type.name !== 'deprecated'), + kibanaVersion, + settings, + }); +}; + +export const getCompatibleMappingsMigrator = async ({ + filterDeprecated = false, + kibanaVersion = nextMinor, + settings = {}, +}: GetMutatedMigratorParams & { filterDeprecated?: boolean } = {}) => { + const types = baselineTypes + .filter((type) => !filterDeprecated || type.name !== 'deprecated') + .map((type) => { + if (type.name === 'complex') { + return { + ...type, + mappings: { + properties: { + name: { type: 'text' }, + value: { type: 'integer' }, + createdAt: { type: 'date' }, + }, + }, + }; + } else { + return type; + } + }); + + return await getKibanaMigratorTestKit({ + types, + kibanaVersion, + settings, + }); +}; + +export const getIncompatibleMappingsMigrator = async ({ + kibanaVersion = nextMinor, + settings = {}, +}: GetMutatedMigratorParams = {}) => { + const types = baselineTypes.map((type) => { + if (type.name === 'complex') { + return { + ...type, + mappings: { + properties: { + name: { type: 'keyword' }, + value: { type: 'long' }, + createdAt: { type: 'date' }, + }, + }, + }; + } else { + return type; + } + }); + + return await getKibanaMigratorTestKit({ + types, + kibanaVersion, + settings, + }); +}; + +export const readLog = async (logFilePath: string = defaultLogFilePath): Promise => { + return await fs.readFile(logFilePath, 'utf-8'); +}; + +export const clearLog = async (logFilePath: string = defaultLogFilePath): Promise => { + await fs.truncate(logFilePath).catch(() => {}); +}; From c08cdc8db633a02ac65d0940a26e5f5a86542d9b Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Wed, 1 Mar 2023 09:46:23 +0000 Subject: [PATCH 077/131] [Security Solution][Alerts] addresses IM performance PR feedback (#150677) ## Summary - addresses feedback from https://github.com/elastic/kibana/pull/149208 - typings for `getSignalsQueryMapFromThreatIndex` - fixes interface name for `getSignalsQueryMapFromThreatIndex` - small code refactorings More details in comments of the initial PR --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../threat_mapping/build_threat_enrichment.ts | 1 + .../threat_mapping/create_event_signal.ts | 1 + .../get_signals_map_from_threat_index.test.ts | 8 +++ .../get_signals_map_from_threat_index.ts | 54 +++++++++++-------- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_enrichment.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_enrichment.ts index 70819f6896861..99b6834523ef5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_enrichment.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/build_threat_enrichment.ts @@ -61,6 +61,7 @@ export const buildThreatEnrichment = ({ const signalsQueryMap = await getSignalsQueryMapFromThreatIndex({ threatSearchParams, eventsCount: signals.length, + termsQueryAllowed: false, }); const enrichment = threatEnrichmentFactory({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts index 8fea8412be38a..17ce22aa40bee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/create_event_signal.ts @@ -86,6 +86,7 @@ export const createEventSignal = async ({ threatSearchParams, eventsCount: currentEventList.length, signalValueMap: getSignalValueMap({ eventList: currentEventList, threatMatchedFields }), + termsQueryAllowed: true, }); const ids = Array.from(signalsQueryMap.keys()); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.test.ts index 38a6947beebcb..4a48db4816b48 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.test.ts @@ -53,6 +53,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { await getSignalsQueryMapFromThreatIndex({ threatSearchParams: threatSearchParamsMock, eventsCount: 50, + termsQueryAllowed: false, }); expect(getThreatListMock).toHaveBeenCalledTimes(1); @@ -65,6 +66,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { const signalsQueryMap = await getSignalsQueryMapFromThreatIndex({ threatSearchParams: threatSearchParamsMock, eventsCount: 50, + termsQueryAllowed: false, }); expect(signalsQueryMap).toEqual(new Map()); @@ -98,6 +100,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { const signalsQueryMap = await getSignalsQueryMapFromThreatIndex({ threatSearchParams: threatSearchParamsMock, eventsCount: 50, + termsQueryAllowed: false, }); expect(signalsQueryMap).toEqual( @@ -153,6 +156,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { const signalsQueryMap = await getSignalsQueryMapFromThreatIndex({ threatSearchParams: threatSearchParamsMock, eventsCount: 50, + termsQueryAllowed: false, }); expect(signalsQueryMap.get('source-1')).toHaveLength(MAX_NUMBER_OF_SIGNAL_MATCHES); @@ -168,6 +172,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { const signalsQueryMap = await getSignalsQueryMapFromThreatIndex({ threatSearchParams: threatSearchParamsMock, eventsCount: 50, + termsQueryAllowed: false, }); expect(signalsQueryMap).toEqual(new Map()); @@ -201,6 +206,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { threatSearchParams: threatSearchParamsMock, eventsCount: 50, signalValueMap, + termsQueryAllowed: true, }); expect(signalsQueryMap).toEqual(new Map()); @@ -234,6 +240,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { threatSearchParams: threatSearchParamsMock, eventsCount: 50, signalValueMap, + termsQueryAllowed: true, }); const queries = [ @@ -283,6 +290,7 @@ describe('getSignalsQueryMapFromThreatIndex', () => { threatSearchParams: threatSearchParamsMock, eventsCount: 50, signalValueMap, + termsQueryAllowed: true, }); const queries = [ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.ts index 0deb3beeee2e8..7d0f49b548f37 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/indicator_match/threat_mapping/get_signals_map_from_threat_index.ts @@ -21,20 +21,34 @@ import { MAX_NUMBER_OF_SIGNAL_MATCHES } from './enrich_signal_threat_matches'; export type SignalsQueryMap = Map; -interface GetSignalsMatchesFromThreatIndexOptions { +interface GetSignalsQueryMapFromThreatIndexOptionsTerms { threatSearchParams: Omit; eventsCount: number; - signalValueMap?: SignalValuesMap; + signalValueMap: SignalValuesMap; + termsQueryAllowed: true; +} + +interface GetSignalsQueryMapFromThreatIndexOptionsMatch { + threatSearchParams: Omit; + eventsCount: number; + termsQueryAllowed: false; } /** * fetches threats and creates signals map from results, that matches signal is with list of threat queries */ -export const getSignalsQueryMapFromThreatIndex = async ({ - threatSearchParams, - eventsCount, - signalValueMap, -}: GetSignalsMatchesFromThreatIndexOptions): Promise => { +/** + * fetches threats and creates signals map from results, that matches signal is with list of threat queries + * @param options.termsQueryAllowed - if terms query allowed to be executed, then signalValueMap should be provided + * @param options.signalValueMap - map of signal values from terms query results + */ +export async function getSignalsQueryMapFromThreatIndex( + options: + | GetSignalsQueryMapFromThreatIndexOptionsTerms + | GetSignalsQueryMapFromThreatIndexOptionsMatch +): Promise { + const { threatSearchParams, eventsCount, termsQueryAllowed } = options; + let threatList: Awaited> | undefined; const signalsQueryMap = new Map(); // number of threat matches per signal is limited by MAX_NUMBER_OF_SIGNAL_MATCHES. Once it hits this number, threats stop to be processed for a signal @@ -50,9 +64,6 @@ export const getSignalsQueryMapFromThreatIndex = async ({ decodedQuery: ThreatMatchNamedQuery | ThreatTermNamedQuery; }) => { const signalMatch = signalsQueryMap.get(signalId); - if (!signalMatch) { - signalsQueryMap.set(signalId, []); - } const threatQuery = { id: threatHit._id, @@ -74,15 +85,9 @@ export const getSignalsQueryMapFromThreatIndex = async ({ } }; - while ( - maxThreatsReachedMap.size < eventsCount && - (threatList ? threatList?.hits.hits.length > 0 : true) - ) { - threatList = await getThreatList({ - ...threatSearchParams, - searchAfter: threatList?.hits.hits[threatList.hits.hits.length - 1].sort || undefined, - }); + threatList = await getThreatList({ ...threatSearchParams, searchAfter: undefined }); + while (maxThreatsReachedMap.size < eventsCount && threatList?.hits.hits.length > 0) { threatList.hits.hits.forEach((threatHit) => { const matchedQueries = threatHit?.matched_queries || []; @@ -90,13 +95,13 @@ export const getSignalsQueryMapFromThreatIndex = async ({ const decodedQuery = decodeThreatMatchNamedQuery(matchedQuery); const signalId = decodedQuery.id; - if (decodedQuery.queryType === ThreatMatchQueryType.term) { + if (decodedQuery.queryType === ThreatMatchQueryType.term && termsQueryAllowed) { const threatValue = get(threatHit?._source, decodedQuery.value); const values = Array.isArray(threatValue) ? threatValue : [threatValue]; values.forEach((value) => { - if (value && signalValueMap) { - const ids = signalValueMap[decodedQuery.field][value?.toString()]; + if (value && options.signalValueMap) { + const ids = options.signalValueMap[decodedQuery.field][value?.toString()]; ids?.forEach((id: string) => { addSignalValueToMap({ @@ -120,7 +125,12 @@ export const getSignalsQueryMapFromThreatIndex = async ({ } }); }); + + threatList = await getThreatList({ + ...threatSearchParams, + searchAfter: threatList.hits.hits[threatList.hits.hits.length - 1].sort, + }); } return signalsQueryMap; -}; +} From ad0ddd3d3c77a7edc217939270f6c0c2dddc23d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20St=C3=BCrmer?= Date: Wed, 1 Mar 2023 12:25:56 +0100 Subject: [PATCH 078/131] [Logs UI] Correctly round and update the log stream end timestamps (#152387) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../log_stream_position_state/src/state_machine.ts | 7 +++++-- .../log_stream_query_state/src/state_machine.ts | 7 +++++-- .../src/time_filter_state_service.ts | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/infra/public/observability_logs/log_stream_position_state/src/state_machine.ts b/x-pack/plugins/infra/public/observability_logs/log_stream_position_state/src/state_machine.ts index d4053d14ab304..96b7dbb687851 100644 --- a/x-pack/plugins/infra/public/observability_logs/log_stream_position_state/src/state_machine.ts +++ b/x-pack/plugins/infra/public/observability_logs/log_stream_position_state/src/state_machine.ts @@ -23,7 +23,7 @@ import type { import { initializeFromUrl, updateContextInUrl } from './url_state_storage_service'; export const createPureLogStreamPositionStateMachine = (initialContext: LogStreamPositionContext) => - /** @xstate-layout N4IgpgJg5mDOIC5QBsD2UDKAXATmAhgLYAK+M2+WYAdAK4B2Alk1o-sowF6QDEAMgHkAggBEAkgDkA4gH1BsgGpiAogHUZGACpCASpuUiA2gAYAuolAAHVLEatU9CyAAeiALQAmAJzUPHgGwArIEALAAcHmHhXsEhADQgAJ6IAQDM1IHGYQDs2ZnZxl5e-l6pAL5lCWiYuAQkZGAUVHRMLGwc3BD8wuLScgKKKuoAYkJifAYm5kgg1rb2jjOuCJ4hAIzUqZklHgX+xqlrkQnJCKlB1P4loYH+qV7hHoEVVejYeESk5FiUNAzMdnaXF4glEklk8hkSjUGgAqgBheHKAyTMxOOaAhxOZbZNbZajGXLBVIkrJrYInRBHYzUEIeVIhVJhNZZLws7IhF4garvOpfRo-Zr-NrsYFdUG9CEDKFDOGI5EiSZraZWGyYxagHEhEIEwkeI7Zc7GO6UhCZHzZML7MKBDwhQp0zmVblvWqfBpNGhofAQZhQPjoBSMMAAd26YL6kOhIzGEyMaJmGIW2JS4VpJTCWXp5K82Q8pvN1Et1tt9oedq5PLd9W+v2o3t99H9geDYYl4P6gxhGARSJR8ZVszVyaWiEZPnt-m8Ry8xjta38pqN1FK+uy+w8xhCgS8lddHxrArrDb9AagQdD4clnZl3d7CqVg6TjCxo4QISumy2MWNMWiAVNO58WMFkImMOc50CMI9xqA9+U9etUB9U8W1DYZ8EYZAQR6Dso1lLRdH0Ad0WHF8NRcdxvF8AJYgiKIwhiUIC1SDwMgNcC8g5O1nmdKs4I9QUaAAC3wWAzwvEMxHoX0AGM4BaAFWFFToeB0ZQkTEBQDBkSQxE0MQhD4GRiF0IQAFllH0HQMCmEj5jIlMEBnfxqAiYojjWVJCjnJcwnSIIrSuNZZ2CGJyl4-c+QEusRLE1DJOkxg5NgBSRQ6XgFEMsQRBkABFWFlB0ABNGR4QACSEaRUSfUjX01Kl-DyWk1giW0p3tElTTxfFwhCPYQIXXE1idV5YKi2tmli8TWyk2T5OFQFlN4SRMr4bK8oK4rSoqqriMTWryOWBdGtckCQMCEknn8MIl21FcWLxVJDUzfwWv8GDeXdCbhNE6bQ1mpL5MUoEVNW9b8sKkrysqqRqrs9VHMGwJmtagI7QOVICznFd1yebdMgutY1gqZ16FQCA4CcPjxqPKh4ZHeqVkiHwtl-XZjQOTzTTcNk2NtQ4-A5q0PureDBNSxb0ogemHLfOkurpahyXArIbTZIItxF-jvsQ5Cmz+kMZbqiiEF2DJQiuK0bVyH94iSRAmTCTZ3ICPMtj8HjRs+w8EJPfX4vQzDICNw7EGR5k7S8NJGrZNXAJ3IsnvtImt28aCIrGr7aZ+uLzxmxLkpDxHNxpC7dn2K404pe331YrwokNQ1GIF7ItZphCpvigHkolpSpaLt8jjTMv12NKd6+r04nlYgbDjxO0-KnNus4736u4LoG0rFAfGc8qIi0Cck1cCQ1K4LJ4iznS1zjzG0WOXn3xcIRhYFsf28-+jf4H2+zjaOw4XKbijt4YIWRbjZHjhaJ6T1cSwIxiTMoQA */ + /** @xstate-layout N4IgpgJg5mDOIC5QBsD2UDKAXATmAhgLYAKqsAlluagHbb5ZgB0Arjee1fsuQF6QBiAEoBRAMIiAkgDURAEQD6kgHKSAKpICCAGQUBFAKoihATQXFNQzQFkRa4xgDaABgC6iUAAcylajQ8gAB6IALQAbACsTAAcAEzRzgCcACzJccmxAIzR0QA0IACeiNkAzExhJSUA7FURsSXRYYklEVUAvm35aJi4BCQ+VLT0jEwcvtx8HFAAYjiohAY4yAIq6lrakgBa8grTQgDy1goGQtou7kgg3hSD-pfBCCGxTBHREYnOTelZ0bX5RQg0okmD8miVMhEwmEqmFGh0uuhsHgiKQbn5hswxlwePwIExrr5aLBRpxyBNcQIAFIGazEBRqfb0ywAcTs5n2GDW+2U5wCBNuAQeVUSz2SULCmQ+zlScQi-0QyWcVSYVU+QIhzlejQi8JA3SRfVRhLoWAYmNJ5Mg+IGfmJWLJOMEomI+yEagU0kknIAQtoROzORpuU43HybbRBYg6mEmGloskqrEqjkwrFYvLAdEyhkItLMlVqtVc+1OnrEb0UeGTWaSeNHXj+bba9i+IINLYFGIABKaZSsuS8y6NiP3RDC57ChOpZzStKxOWFRBZMqpqr5xIpT6xEXRXX6iv9NFDU0je2WvFYAAWcywWB4NCgxHwMBENAgylQVAAZuQAMYMJtyAgZAwGEEQXTdD0vUkX1-RdQNJGDQcvCrSMEHeTJygSWJkg+X5FQhDN4xjNNIk1V4xRKWIwj3ctkUPY0MWbB1Wwva9PzvKYnxfN8P2-P8AKJJgrxvTiHzAiD3U9H0-QDLllBDC4UKPO5QAeTJJTKVVITTRpt3iDMaiiCINUSDTMlw-Nklonp6KNW4mLPethPY2970fZ8wFfd9P3IH9-1uYkRI49yBECWAT2YfAv0YHAAApRG0TQNFkBQRGURQDGIORkv9OQRCSkwAEoBH3Oyq0ci1nOCtyuM87y+L8gTApc0T3OQq5UNHBAzOiFVohFEo5xKZx6mSDNeqYDTakyVMlWiTIhpsg1KxUyq61Y1qQrqnifP4gKmxqsSoDCiKa2i2KEoK5KZH9dLMuy3KFHywqSrKw0Ksi5jzy22qH24rzeN8-zBJoILXOOxxMiUzqVLQ2plTqEoRWnGcUgmpopvjRUYWSbJWhKZaD3s9EvqczajvcgGGuB5qmxoYGCimAQOuHVSggVGpymhMJnAhVUEjqDNMiVKJaiG+dfgG6prN1BmIDgAJ3tWxjIrDOHupCDSyjiBIUjnDJsjyRdHjSGJEwWjd8zeNGifKtavrYcncXV400IyIjMI3b36lVXmIgTO2PodmtnamWZ5kWZBXYFTXnmlWE-hNka+uoxIA6zRJZUJ0tlYYhyyaq1iY78NCSkiFULLnSFkYlaEMwacok2yGcRZF1pMiDlWC9DovcWtFT4CHLq1IVRaYnjapEmTRNnHBYXqKm5vhWaBIJTqLv89J3uNv7tm7T7yAS5HUfAQlCfkinmfYjnzIM23KI04z5Hs83knjx3lt+8pnbAb2pqDpEmPuzB4eMtJV1lBURIdcqgZlhH1PmJkcJDTqItEsCJbLB1Vp-Fi38IZU3qkDfaoM7TATAMA92581wynnFAmBRExQgmormCIFEKjUTfp9HBP0f7-UIf-EGLVeFQAod1cyzx4isKqHOfMkIGEkWYeRYiVEaK5zolgnup5D5sTar-GmxCWoM2-EzB8ojT5t2BK8HClFFqREIibduzgVQRCGiNJUyRWEig6B0IAA */ createMachine( { context: initialContext, @@ -92,7 +92,7 @@ export const createPureLogStreamPositionStateMachine = (initialContext: LogStrea }, throttling: { after: { - [RELATIVE_END_UPDATE_DELAY]: [ + RELATIVE_END_UPDATE_DELAY: [ { target: 'notifying', cond: 'hasReachedPageEndBuffer', @@ -185,6 +185,9 @@ export const createPureLogStreamPositionStateMachine = (initialContext: LogStrea : {} ), }, + delays: { + RELATIVE_END_UPDATE_DELAY, + }, guards: { // User is close to the bottom of the page. hasReachedPageEndBuffer: (context, event) => diff --git a/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/state_machine.ts b/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/state_machine.ts index bbae54bf8803e..16ddeb9352a31 100644 --- a/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/state_machine.ts +++ b/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/state_machine.ts @@ -55,7 +55,7 @@ import { DEFAULT_REFRESH_INTERVAL, DEFAULT_REFRESH_TIME_RANGE } from './defaults export const createPureLogStreamQueryStateMachine = ( initialContext: LogStreamQueryContextWithDataViews & LogStreamQueryContextWithTime ) => - /** @xstate-layout N4IgpgJg5mDOIC5QEUCuYBOBPAdKgdgJZEAuhAhgDaEBekAxANoAMAuoqAA4D2shZ3fBxAAPRAEYAHAGYck8QCYArAoAsC8QHZNygJySANCCwTpszc2njpANnH2FN1UtUBfV0bSZcxfhWo0xFAAYhjcALYAqhiU9ACSAHJxACpxAIIAMnEAWgCiACIA+sEASgDyALKFkSUZLOxIIDx8AkKNYghKzJJyCvJOurqqA4bGiPI4XczTdjbM2kq64u6e6Ng4vmRUtEGhEdGxiSnpWXlFpZXVtYziDVy8foLCHSpGJgjizj02SjYa3X0dH8ViAvOtNv4dvgQmFwslCOEwMFCJQSJgAMqYABuhAAxmB4klUpkcgViuUqqkKrlinEMslciVCujGQA1OIAYVy9WEzUebVAHWkkhsOGmmnkqnUumkzBsmmkb0Quk0ot0coUZnscukSkkILBPlIkLoEBwAEc1lh6MhIoyAJrky4stIlDkACUKACFXYUPWkEgBxAo8xp81rPcbiJQ4GzSPoKOXMX7RxVjD7MVTiOTyxOSVT5zRKCUGq0bY3bU0Wq30YJ0hkldFOqout2en1M-1BkNsXkPCPtKMxuMJpMppRp95LHrDZi6CfSbQ2STF0vect+SuQaveej5NLJNKFdm5ADqTa7wfyofuLUIT0HCHkw-jkkTc3Hk-GCgUYvm8kGAtCzXcEKwCbdLXXLFtggcgyGhehWRJfdUjKBJmUiDkuQKHs7iaft7wFUQJCzVQcGkdU7GjOdxF0JUECGZhyMUJRFGYBMVX1DxQTLCEtzNSD1mg6hYPgqBEOQg84jQ4o0jpXC+zvB9BRIz5yMo+wuiWOj03sOYcC0Wi+gA7RkxAo1N3AgSywwMBhMIUSggkrIUOk9DgjkjIFLDAjlOIj5SPUuVNJonT3nESxRVVX4FU0RQbH0aRzI3LYrJ3dZbPsxyEKQlypJk9FMOw-JvNvflIwCtSKOC6jtPo-ocEo5QEo0H9fmSvi0rIRF6CpGkLkpOJqVpelGWZNlORpS9SvwpSiI6Z9Y1fd9kzsCd6KkVRNFjX5-l0BQLCLLjVnXTraG3bqCUiAAFFCaT6woSgDYMb1m8rH0Wkc3zHNavw+eUmOkVRF2XFVhjmGwOrA86zUu+gbrux7clKXJ0U9RIG1y17w0IirPuWn7Uw21QZTFKx4wsH81CUJQocsmGcEulKTQYbHfPm0ws0mTVweBiV51UDadF0SYZDMYHJE0KUtrp1KGaZs7TSYW5FPelSPiB7MVCBmwnEXSQBaFyQem6LUpYogsdHcbj8G4CA4GEQ1VYHdWAFobHo12Y0GH3fb9pLuMNPAiGh01ndxx91A2+McAsKw7F1I7AVlk1dlhA5w78joDp6A383lRctC0wXdLnHBEysTU40UA2ZcD3jQ7TiJ4URZFUQxbE8TATOOYQeV6MGQHFkXRd51owYU-4nuKrikWvpWz96JJpimrsRwJQLaNJ7SwT3jKl3-NVbb58J9b02LGcNXJn8Cx+beGd3nAsrgoJp8fexJfL+Q2q0AtbBLqcLhJgUQiuIP4zgwHHR4qdUOEEyxZTfurMButYzzllBROYUo-j1WcDgKUjhjaEMsNYe+VZH7EAQT5OaFVkGigShOSwuhMHDAUBtOUMZZQaGBrqXUIo3D1xgfTMhNk7IwRftCRB-kP7bT6IoZQv8ZBOBwWROYMoZQ-klpITMpCLoIm7lQtWh95RLVHB+X60cY4TmsOqQuqot4CNAkI3RiJmZTwMQfDoigtCNWilote0wlBCyBuXEm+hpQWF1jo2GeicCwBIC-XEkjPGsTIrRCcE5dYS1okbUUZgzAHWTEDSwUTGYxLibZcg4RX7uIjkglJBk0EZL1gBIWB05B5OjFLYs+hNDW1cEAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QEUCuYBOBPAdKgdgJZEAuhAhgDaEBekAxANoAMAuoqAA4D2shZ3fBxAAPRAEYAHAGYck8QCYArAoAsC8QHZNygJySANCCwTpszc2njpANnH2FN1UtUBfV0bSZcxfhWo0xFAAYhjcALYAqhiU9ACSAHJxACpxAIIAMnEAWgCiACIA+sEASgDyALKFkSUZLOxIIDx8AkKNYghKzJJyCvJOurqqA4bGiPI4XczTdjbM2kq64u6e6Ng4vmRUtEGhEcmE4WDBhJQkmADKmABuhADGYPFJqZk5BcXlVakVucVxGclciVChcgQA1OIAYVy9WEzT8gmEHWkkhsOGmmnkqnUumkzBsmmkRhMCF0mjRunxCjM9nx0iUkhWIC8602-lokBwAEc1lh6MhIkCAJofSog3JpEqQgAShQAQpLCjK0gkAOIFWGNeGtJHjcRKHA2aR9BT45hKOxKIljBDiZiqcRyAmmySqV2aJSYpksnykdl0CDc3n0YL-QElC6iqqgyUy+WK5VqjVsOG8BFtUAdeQGo0ms0W-XWklLHrDZi6K3SbQ2SSe728jZ+7YBoPeej5NLJNKFCG5ADqkcT6vymq4aZ17T1OeNklNcwLVuJ4wUCnR83kgzd7vr3kbfmbnJ5u+u2wg5DI+Cg9DBrw7qTKCRBkUh0IKyYaY5ahERk9tDtUODSJSdj6uW4i6EupKqMwgGKEoijMCaZKMh4zINmyB6Bke6wntQZ4XleN5ZHecQPsUaT-O+qZfj+mYSP+gHAfYXRLBBNr2HMOBaOBfQbto5o7qyTYBIeDYYGAuGEPhQTXrenakY+wQURkVFauO34ZqI9HiABQH4sxYFsSSdq2Dg5IWoSmiKDY+jSIJvr7iJWFiRJp7njJRFxCRZEXM+r75Kpn7prqf46Yx+mgaxkH9DgwHKDZGgrha9l7lsTk4GQRz0N8vylGKOV-ACQLiiUELQkq0oqsOo5NOptFaQg2aGjOc7mpaRYSO6hoWho5YKBYHooasu4YelmWPJEAAKd6-AVJRVTCKZqTRmlZvqzV5vO7WQeIBIwdIqhVjWZLDHMNgpaNHKBuN9BTTNhQlLkpS5BcsqJOGRE1dqGkhU1uazvm23saouLolYxoWCuahKEoF3CVdGWHGAqX+gwX11atpgOpM1KnYdmIVqoO06LokwyGYh2SJo2KqJocOOQj40o5hTDiB+tUrSF1jYyoB02E4VaSITxOSD03Q0tTQFujo9NpYzSM4LAJDuXc9CTWk6qFLkCRFHKkTBMExWPWkMqBRzwW-rtFjosMQv0rSpqaDtVMAXauKYrO8HMDpsuo9dCtK+J5DhDJIhK+eyPkAAZucGAABTiVH4mwAAFgAlPy6Hwy2TOB2AwdBOjnOW4SpNC+6qICxuxMooBZgQ+aB2WO4qH4NwEBwMIPrURbdEIAAtDYkH9wagxj97tjDCuVZuKhPp4EQ2eQD3E59+oO3GmZli7dYnoMn0dNz1nDOBJeexRDEK8-b+-U9OXwyWVoLFE+x5Y4KaVjUkaihC7TvvNrsMI4QDhHBOGcS4Nx7hgCvvVDoBJIKDH2osKsVYKzgUGP-JyMDMYICsqTf6rUFwdQQCDGCcUpC6BNPIOyR8RpL2ct4bBIVySaA2gDLahZIKelLFSU0iE5hkkwQjbCuBJLSUvEwy2UhWF9EUMoLQbpJ4IJcJMICdpdrQ12kNNCdCT6iWPKeSRfddr80NBWPEQE5jYhsAoaKzgcDYkcKLZx28aHDSEnohhQkxFGIaiYtENkrSWF0FYqeO18QGjxBoQ69J6Solnu4hycsWwiJwOJMR7kJHLV7n46R795BJQUTIJwdiAICKAsaA+kh7RCJzkjXxHQWFsMIUDYyeI0RWmsALBCNZYa0I8ckzkTNLoBgaRIDQrCyQ2AZPpPhSga4ATUIMV0CgyT4nOv0pJftEZHEVsrMgdwxm2ngq7cxVp+aU3AiLNE9cG5Wmgm4nRAztm5xIEHEOWSgqrz8ScriZzbBVyuexHQrDyZWE9M4TQ+hD7uCAA */ createMachine( { context: initialContext, @@ -281,7 +281,10 @@ export const createPureLogStreamQueryStateMachine = ( updateTimeContextFromTimeRangeUpdate, updateTimeContextFromRefreshIntervalUpdate, refreshTime: send({ type: 'UPDATE_TIME_RANGE', timeRange: DEFAULT_REFRESH_TIME_RANGE }), - expandPageEnd: send({ type: 'UPDATE_TIME_RANGE', timeRange: { to: 'now' } }), + expandPageEnd: send((context) => ({ + type: 'UPDATE_TIME_RANGE', + timeRange: { to: context.timeRange.to }, + })), updateTimeContextFromUrl, }, guards: { diff --git a/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/time_filter_state_service.ts b/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/time_filter_state_service.ts index 3bc2adcb79315..c7ce0ac8b9c18 100644 --- a/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/time_filter_state_service.ts +++ b/x-pack/plugins/infra/public/observability_logs/log_stream_query_state/src/time_filter_state_service.ts @@ -143,7 +143,7 @@ export const updateTimeContextFromRefreshIntervalUpdate = actions.assign( ? { timestamps: { startTimestamp: datemathToEpochMillis(DEFAULT_REFRESH_TIME_RANGE.from, 'down') ?? 0, - endTimestamp: datemathToEpochMillis(DEFAULT_REFRESH_TIME_RANGE.to, 'down') ?? 0, + endTimestamp: datemathToEpochMillis(DEFAULT_REFRESH_TIME_RANGE.to, 'up') ?? 0, lastChangedTimestamp: nowTimestamp, }, } @@ -170,7 +170,7 @@ const getTimeFromEvent = (context: LogStreamQueryContext, event: LogStreamQueryE ? datemathToEpochMillis(from, 'down') : context.timestamps.startTimestamp; const toTimestamp = event.timeRange?.to - ? datemathToEpochMillis(to, 'down') + ? datemathToEpochMillis(to, 'up') : context.timestamps.endTimestamp; return { From 88be889e1c5bfd97943eaf5eef6c7002433e2169 Mon Sep 17 00:00:00 2001 From: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com> Date: Wed, 1 Mar 2023 11:29:53 +0000 Subject: [PATCH 079/131] [Security Solution][Alerts] fixes merge fields with source in Detection Engine on Alerts creation (#151004) ## Summary - fixes https://github.com/elastic/kibana/issues/147389 - `mergeMissingFieldsWithSource` and `mergeAllFieldsWithSource` method will not be merging anymore multi field values into source. ### 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 - [ ] 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: Marshall Main <55718608+marshallmain@users.noreply.github.com> --- .../merge_all_fields_with_source.test.ts | 55 ++++++++++++++ .../merge_all_fields_with_source.ts | 4 +- .../merge_missing_fields_with_source.test.ts | 62 ++++++++++++++++ .../merge_missing_fields_with_source.ts | 4 +- .../utils/is_path_valid.test.ts | 74 +++++++++++++++++++ .../utils/is_path_valid.ts | 30 ++++++++ .../rule_execution_logic/non_ecs_fields.ts | 58 +++++++++++++++ .../ecs_non_compliant/mappings.json | 18 +++++ 8 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.test.ts create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.ts diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.test.ts index 5aac1418cf45d..1a5733cbd7760 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.test.ts @@ -1327,6 +1327,35 @@ describe('merge_all_fields_with_source', () => { }); }); + test('does not add multi field values such as "process.command_line.text" to nested source when "process.command_line" has value', () => { + const _source: SignalSourceHit['_source'] = { + process: { + command_line: 'string longer than 10 characters', + }, + }; + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeAllFieldsWithSource({ doc, ignoreFields: [] })._source; + expect(merged).toEqual(_source); + }); + + test('does not add multi field values such as "process.command_line.text" to nested source when "process.command_line" has array value', () => { + const _source: SignalSourceHit['_source'] = { + process: { + command_line: ['string longer than 10 characters'], + }, + }; + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeAllFieldsWithSource({ doc, ignoreFields: [] })._source; + + expect(merged).toEqual(_source); + }); + test('multi-field values mixed with regular values will not be merged accidentally"', () => { const _source: SignalSourceHit['_source'] = {}; const fields: SignalSourceHit['fields'] = { @@ -1393,6 +1422,32 @@ describe('merge_all_fields_with_source', () => { foo: 'other_value_1', }); }); + + test('does not add multi field values such as "process.command_line.text" to flattened source when "process.command_line" has value', () => { + const _source: SignalSourceHit['_source'] = { + 'process.command_line': 'string longer than 10 characters', + }; + + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeAllFieldsWithSource({ doc, ignoreFields: [] })._source; + expect(merged).toEqual(_source); + }); + + test('does not add multi field values such as "process.command_line.text" to flattened source when "process.command_line" has array value', () => { + const _source: SignalSourceHit['_source'] = { + 'process.command_line': ['string longer than 10 characters'], + }; + + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeAllFieldsWithSource({ doc, ignoreFields: [] })._source; + expect(merged).toEqual(_source); + }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.ts index b9193f952fd18..ab9cc86fa1049 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_all_fields_with_source.ts @@ -15,8 +15,8 @@ import { isNestedObject } from '../utils/is_nested_object'; import { recursiveUnboxingFields } from '../utils/recursive_unboxing_fields'; import { isPrimitive } from '../utils/is_primitive'; import { isArrayOfPrimitives } from '../utils/is_array_of_primitives'; -import { arrayInPathExists } from '../utils/array_in_path_exists'; import { isTypeObject } from '../utils/is_type_object'; +import { isPathValid } from '../utils/is_path_valid'; /** * Merges all of "doc._source" with its "doc.fields" on a "best effort" basis. See ../README.md for more information @@ -107,7 +107,7 @@ const hasEarlyReturnConditions = ({ const valueInMergedDocument = get(fieldsKey, merged); return ( fieldsValue.length === 0 || - (valueInMergedDocument === undefined && arrayInPathExists(fieldsKey, merged)) || + (valueInMergedDocument === undefined && !isPathValid(fieldsKey, merged)) || (isObjectLikeOrArrayOfObjectLikes(valueInMergedDocument) && !isNestedObject(fieldsValue) && !isTypeObject(fieldsValue)) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts index 911df7400ec63..7e997ceb0ee65 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.test.ts @@ -1283,6 +1283,38 @@ describe('merge_missing_fields_with_source', () => { foo: 'other_value_1', }); }); + + test('does not add multi field values such as "process.command_line.text" to nested source when "process.command_line" has value', () => { + const _source: SignalSourceHit['_source'] = { + '@timestamp': '2023-02-10T10:15:50Z', + process: { + command_line: 'string longer than 10 characters', + }, + }; + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + '@timestamp': ['2023-02-10T10:15:50.000Z'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source; + expect(merged).toEqual(_source); + }); + + test('does not add multi field values such as "process.command_line.text" to nested source when "process.command_line" has array value', () => { + const _source: SignalSourceHit['_source'] = { + '@timestamp': '2023-02-10T10:15:50Z', + process: { + command_line: ['string longer than 10 characters'], + }, + }; + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + '@timestamp': ['2023-02-10T10:15:50.000Z'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source; + expect(merged).toEqual(_source); + }); }); describe('flattened keys for the _source', () => { @@ -1331,6 +1363,36 @@ describe('merge_missing_fields_with_source', () => { foo: 'other_value_1', }); }); + + test('does not add multi field values such as "process.command_line.text" to flattened source when "process.command_line" has value', () => { + const _source: SignalSourceHit['_source'] = { + '@timestamp': '2023-02-10T10:15:50Z', + 'process.command_line': 'string longer than 10 characters', + }; + + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + '@timestamp': ['2023-02-10T10:15:50.000Z'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source; + expect(merged).toEqual(_source); + }); + + test('does not add multi field values such as "process.command_line.text" to flattened source when "process.command_line" has array value', () => { + const _source: SignalSourceHit['_source'] = { + '@timestamp': '2023-02-10T10:15:50Z', + 'process.command_line': ['string longer than 10 characters'], + }; + + const fields: SignalSourceHit['fields'] = { + 'process.command_line.text': ['string longer than 10 characters'], + '@timestamp': ['2023-02-10T10:15:50.000Z'], + }; + const doc: SignalSourceHit = { ...emptyEsResult(), _source, fields }; + const merged = mergeMissingFieldsWithSource({ doc, ignoreFields: [] })._source; + expect(merged).toEqual(_source); + }); }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.ts index 3efe1a7925d9b..e4bf563f4f055 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/strategies/merge_missing_fields_with_source.ts @@ -12,8 +12,8 @@ import { filterFieldEntries } from '../utils/filter_field_entries'; import type { FieldsType, MergeStrategyFunction } from '../types'; import { recursiveUnboxingFields } from '../utils/recursive_unboxing_fields'; import { isTypeObject } from '../utils/is_type_object'; -import { arrayInPathExists } from '../utils/array_in_path_exists'; import { isNestedObject } from '../utils/is_nested_object'; +import { isPathValid } from '../utils/is_path_valid'; /** * Merges only missing sections of "doc._source" with its "doc.fields" on a "best effort" basis. See ../README.md for more information @@ -79,7 +79,7 @@ const hasEarlyReturnConditions = ({ return ( fieldsValue.length === 0 || valueInMergedDocument !== undefined || - arrayInPathExists(fieldsKey, merged) || + !isPathValid(fieldsKey, merged) || isNestedObject(fieldsValue) || isTypeObject(fieldsValue) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.test.ts new file mode 100644 index 0000000000000..e899142bb7352 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.test.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isPathValid } from './is_path_valid'; + +describe('isPathValid', () => { + test('not valid when empty string and empty object', () => { + expect(isPathValid('', {})).toEqual(false); + }); + + test('valid when a path and empty object', () => { + expect(isPathValid('a.b.c', {})).toEqual(true); + }); + + test('not valid when a path and an array exists', () => { + expect(isPathValid('a', { a: [] })).toEqual(false); + }); + + test('not valid when a path and primitive value exists', () => { + expect(isPathValid('a', { a: 'test' })).toEqual(false); + expect(isPathValid('a', { a: 1 })).toEqual(false); + expect(isPathValid('a', { a: true })).toEqual(false); + }); + + test('valid when a path and object value exists', () => { + expect(isPathValid('a', { a: {} })).toEqual(true); + }); + + test('not valid when a path and an array exists within the parent path at level 1', () => { + expect(isPathValid('a.b', { a: [] })).toEqual(false); + }); + + test('not valid when a path and primitive value exists within the parent path at level 1', () => { + expect(isPathValid('a.b', { a: 'test' })).toEqual(false); + expect(isPathValid('a.b', { a: 1 })).toEqual(false); + expect(isPathValid('a.b', { a: true })).toEqual(false); + }); + + test('valid when a path and object value exists within the parent path at level 1', () => { + expect(isPathValid('a.b', { a: {} })).toEqual(true); + }); + + test('not valid when a path and an array exists within the parent path at level 2', () => { + expect(isPathValid('a.b.c', { a: { b: [] } })).toEqual(false); + }); + + test('not valid when a path and primitive value exists within the parent path at level 2', () => { + expect(isPathValid('a.b', { a: { b: 'test' } })).toEqual(false); + expect(isPathValid('a.b', { a: { b: 1 } })).toEqual(false); + expect(isPathValid('a.b', { a: { b: true } })).toEqual(false); + }); + + test('valid when a path and object value exists within the parent path at level 2', () => { + expect(isPathValid('a.b', { a: { b: {} } })).toEqual(true); + }); + + test('not valid when a path and an array exists within the parent path at level 3', () => { + expect(isPathValid('a.b.c', { a: { b: { c: [] } } })).toEqual(false); + }); + + test('not valid when a path and primitive value exists within the parent path at level 3', () => { + expect(isPathValid('a.b.c', { a: { b: { c: 'test' } } })).toEqual(false); + expect(isPathValid('a.b.c', { a: { b: { c: 1 } } })).toEqual(false); + expect(isPathValid('a.b.c', { a: { b: { c: true } } })).toEqual(false); + }); + + test('valid when a path and object value exists within the parent path at level 3', () => { + expect(isPathValid('a.b.c', { a: { b: { c: {} } } })).toEqual(true); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.ts new file mode 100644 index 0000000000000..c5038531baa2a --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/utils/source_fields_merging/utils/is_path_valid.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { get, isPlainObject } from 'lodash/fp'; +import type { SignalSource } from '../../../types'; + +/** + * Returns true if path in SignalSource object is valid + * Path is valid if each field in hierarchy is object or undefined + * Path is not valid if ANY of field in hierarchy is not object or undefined + * @param path in source to check within source + * @param source The source document + * @returns boolean + */ +export const isPathValid = (path: string, source: SignalSource): boolean => { + if (!path) { + return false; + } + const splitPath = path.split('.'); + + return splitPath.every((_, index, array) => { + const newPath = [...array].splice(0, index + 1).join('.'); + const valueToCheck = get(newPath, source); + return valueToCheck === undefined || isPlainObject(valueToCheck); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/non_ecs_fields.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/non_ecs_fields.ts index 3c5368b7a23ad..0bcb05b5e1c40 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/non_ecs_fields.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/non_ecs_fields.ts @@ -323,5 +323,63 @@ export default ({ getService }: FtrProviderContext) => { // invalid ECS field is getting removed expect(alertSource).not.toHaveProperty('dll.code_signature.valid'); }); + + describe('multi-fields', () => { + it('should not add multi field .text to ecs compliant nested source', async () => { + const document = { + process: { + command_line: 'string longer than 10 characters', + }, + }; + + const { errors, alertSource } = await indexAndCreatePreviewAlert(document); + + expect(errors).toEqual([]); + + expect(alertSource).toHaveProperty('process', document.process); + expect(alertSource).not.toHaveProperty('process.command_line.text'); + }); + + it('should not add multi field .text to ecs compliant flattened source', async () => { + const document = { + 'process.command_line': 'string longer than 10 characters', + }; + + const { errors, alertSource } = await indexAndCreatePreviewAlert(document); + + expect(errors).toEqual([]); + + expect(alertSource?.['process.command_line']).toEqual(document['process.command_line']); + expect(alertSource).not.toHaveProperty('process.command_line.text'); + }); + + it('should not add multi field .text to ecs non compliant nested source', async () => { + const document = { + nonEcs: { + command_line: 'string longer than 10 characters', + }, + }; + + const { errors, alertSource } = await indexAndCreatePreviewAlert(document); + + expect(errors).toEqual([]); + + expect(alertSource).toHaveProperty('nonEcs', document.nonEcs); + expect(alertSource).not.toHaveProperty('nonEcs.command_line.text'); + }); + + it('should not add multi field .text to ecs non compliant flattened source', async () => { + const document = { + 'nonEcs.command_line': 'string longer than 10 characters', + }; + + const { errors, alertSource } = await indexAndCreatePreviewAlert(document); + + expect(errors).toEqual([]); + + expect(alertSource?.['nonEcs.command_line']).toEqual(document['nonEcs.command_line']); + expect(alertSource).not.toHaveProperty('nonEcs.command_line.text'); + }); + }); }); }; diff --git a/x-pack/test/functional/es_archives/security_solution/ecs_non_compliant/mappings.json b/x-pack/test/functional/es_archives/security_solution/ecs_non_compliant/mappings.json index 42d23e794ba23..40408d65b6d89 100644 --- a/x-pack/test/functional/es_archives/security_solution/ecs_non_compliant/mappings.json +++ b/x-pack/test/functional/es_archives/security_solution/ecs_non_compliant/mappings.json @@ -55,6 +55,24 @@ } } } + }, + "process.command_line": { + "type": "keyword", + "ignore_above": 10, + "fields": { + "text": { + "type": "text" + } + } + }, + "nonEcs.command_line": { + "type": "keyword", + "ignore_above": 10, + "fields": { + "text": { + "type": "text" + } + } } } }, From a0392f8fc0e37647c580e54694a21731d1a154be Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Wed, 1 Mar 2023 07:49:41 -0500 Subject: [PATCH 080/131] [Fleet] Add OpenAPI tags to help group Fleet API requests (#152386) ## Summary Ref https://github.com/elastic/observability-docs/pull/2715 Adds relevant `tags` to all operations in order to help group them more effectively in the generated docs. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../plugins/fleet/common/openapi/bundled.json | 798 +++++++++++------- .../plugins/fleet/common/openapi/bundled.yaml | 607 +++++++------ .../fleet/common/openapi/entrypoint.yaml | 25 +- .../openapi/paths/agent_download_sources.yaml | 11 +- .../agent_download_sources@{source_id}.yaml | 13 +- .../common/openapi/paths/agent_policies.yaml | 10 +- .../paths/agent_policies@_bulk_get.yaml | 5 +- .../openapi/paths/agent_policies@delete.yaml | 4 +- .../agent_policies@{agent_policy_id}.yaml | 10 +- ...agent_policies@{agent_policy_id}@copy.yaml | 5 +- ...t_policies@{agent_policy_id}@download.yaml | 5 +- ...agent_policies@{agent_policy_id}@full.yaml | 5 +- .../common/openapi/paths/agent_status.yaml | 7 +- .../openapi/paths/agent_status@data.yaml | 5 +- .../paths/agent_status_deprecated.yaml | 5 +- .../common/openapi/paths/agent_tags.yaml | 5 +- .../fleet/common/openapi/paths/agents.yaml | 5 +- .../openapi/paths/agents@action_status.yaml | 14 +- .../openapi/paths/agents@bulk_reassign.yaml | 23 +- .../agents@bulk_request_diagnostics.yaml | 7 +- .../openapi/paths/agents@bulk_unenroll.yaml | 21 +- .../paths/agents@bulk_update_tags.yaml | 25 +- .../openapi/paths/agents@bulk_upgrade.yaml | 13 +- .../paths/agents@current_upgrades.yaml | 5 +- .../agents@files@{file_id}@{file_name}.yaml | 5 +- .../common/openapi/paths/agents@setup.yaml | 9 +- .../openapi/paths/agents@{agent_id}.yaml | 15 +- .../paths/agents@{agent_id}@actions.yaml | 9 +- ...{agent_id}@actions@{action_id}@cancel.yaml | 5 +- .../paths/agents@{agent_id}@reassign.yaml | 11 +- ...agents@{agent_id}@request_diagnostics.yaml | 6 +- .../paths/agents@{agent_id}@unenroll.yaml | 43 +- .../paths/agents@{agent_id}@upgrade.yaml | 5 +- .../paths/agents@{agent_id}@uploads.yaml | 3 +- .../common/openapi/paths/data_streams.yaml | 5 +- .../openapi/paths/enrollment_api_keys.yaml | 10 +- .../paths/enrollment_api_keys@{key_id}.yaml | 10 +- ...rollment_api_keys@{key_id}_deprecated.yaml | 10 +- .../paths/enrollment_api_keys_deprecated.yaml | 10 +- .../common/openapi/paths/epm@categories.yaml | 15 +- .../common/openapi/paths/epm@get_file.yaml | 5 +- .../openapi/paths/epm@limited_list.yaml | 5 +- .../common/openapi/paths/epm@packages.yaml | 20 +- .../paths/epm@packages@{pkg_name}@stats.yaml | 5 +- ...epm@packages@{pkg_name}@{pkg_version}.yaml | 24 +- .../epm@packages@{pkgkey}_deprecated.yaml | 19 +- .../openapi/paths/epm@packages_bulk.yaml | 12 +- .../paths/epm@verification_key_id.yaml | 22 +- .../openapi/paths/fleet_server_hosts.yaml | 12 +- .../paths/fleet_server_hosts@{item_id}.yaml | 13 +- .../common/openapi/paths/health_check.yaml | 5 +- .../common/openapi/paths/kubernetes.yaml | 35 +- .../openapi/paths/logstash_api_keys.yaml | 3 +- .../fleet/common/openapi/paths/outputs.yaml | 13 +- .../openapi/paths/outputs@{output_id}.yaml | 19 +- .../openapi/paths/package_policies.yaml | 9 +- .../paths/package_policies@_bulk_get.yaml | 5 +- .../paths/package_policies@delete.yaml | 4 +- .../paths/package_policies@upgrade.yaml | 4 +- .../package_policies@upgrade_dryrun.yaml | 4 +- .../package_policies@{package_policy_id}.yaml | 14 +- .../fleet/common/openapi/paths/proxies.yaml | 12 +- .../openapi/paths/proxies@{item_id}.yaml | 13 +- .../common/openapi/paths/service_tokens.yaml | 5 +- .../paths/service_tokens_deprecated.yaml | 5 +- .../fleet/common/openapi/paths/settings.yaml | 10 +- .../fleet/common/openapi/paths/setup.yaml | 5 +- 67 files changed, 1238 insertions(+), 868 deletions(-) diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index eb7dcf0cad55c..4ff0b522325ca 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -20,10 +20,67 @@ } ], "paths": { + "/health_check": { + "post": { + "summary": "Fleet Server health check", + "tags": [ + "Fleet internals" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "host": { + "type": "string" + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/error" + } + }, + "operationId": "fleet-server-health-check", + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "host": { + "type": "string" + } + } + } + } + } + } + } + }, "/setup": { "post": { - "summary": "Setup", - "tags": [], + "summary": "Initiate Fleet setup", + "tags": [ + "Fleet internals" + ], "responses": { "200": { "description": "OK", @@ -64,8 +121,10 @@ }, "/settings": { "get": { - "summary": "Settings", - "tags": [], + "summary": "Get settings", + "tags": [ + "Fleet internals" + ], "responses": { "200": { "description": "OK", @@ -84,8 +143,10 @@ "operationId": "get-settings" }, "put": { - "summary": "Settings - Update", - "tags": [], + "summary": "Update settings", + "tags": [ + "Fleet internals" + ], "requestBody": { "content": { "application/json": { @@ -128,63 +189,12 @@ "operationId": "update-settings" } }, - "/health_check": { - "post": { - "summary": "Fleet Server Health Check", - "tags": [], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "status": { - "type": "string" - }, - "host": { - "type": "string" - } - } - } - } - } - }, - "400": { - "$ref": "#/components/responses/error" - } - }, - "operationId": "fleet-server-health-check", - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "host": { - "type": "string" - } - } - } - } - } - } - } - }, "/service-tokens": { "post": { - "summary": "Generate service tokens", - "tags": [], + "summary": "Create service token", + "tags": [ + "Service tokens" + ], "responses": { "200": { "description": "OK", @@ -219,8 +229,10 @@ }, "/service_tokens": { "post": { - "summary": "Generate service tokens", - "tags": [], + "summary": "Create service token", + "tags": [ + "Service tokens" + ], "responses": { "200": { "description": "OK", @@ -255,7 +267,9 @@ "/epm/verification_key_id": { "get": { "summary": "Get package signature verification key ID", - "tags": [], + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -291,37 +305,14 @@ }, "operationId": "packages-get-verification-key-id" }, - "parameters": [ - { - "schema": { - "type": "string" - }, - "name": "pkgName", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "pkgVersion", - "in": "path", - "required": true - }, - { - "schema": { - "type": "string" - }, - "name": "filePath", - "in": "path", - "required": true - } - ] + "parameters": [] }, "/epm/categories": { "get": { - "summary": "Package categories", - "tags": [], + "summary": "List package categories", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -347,7 +338,7 @@ "type": "boolean", "default": false }, - "description": "Whether to include prerelease packages in categories count (e.g. beta, rc, preview) " + "description": "Whether to include prerelease packages in categories count (e.g. beta, rc, preview)" }, { "in": "query", @@ -370,8 +361,10 @@ }, "/epm/packages/limited": { "get": { - "summary": "Packages - Get limited list", - "tags": [], + "summary": "Get limited package list", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -401,8 +394,10 @@ }, "/epm/packages": { "get": { - "summary": "Packages - List", - "tags": [], + "summary": "List packages", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -436,7 +431,7 @@ "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", @@ -457,8 +452,10 @@ ] }, "post": { - "summary": "Packages - Install by upload", - "tags": [], + "summary": "Install by package by direct upload", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -544,8 +541,10 @@ }, "/epm/packages/_bulk": { "post": { - "summary": "Packages - Bulk install", - "tags": [], + "summary": "Bulk install packages", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -570,7 +569,7 @@ "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)" } ], "requestBody": { @@ -602,8 +601,10 @@ }, "/epm/packages/{pkgkey}": { "get": { - "summary": "Packages - Info", - "tags": [], + "summary": "Get package", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -670,14 +671,16 @@ "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)" } ], "deprecated": true }, "post": { - "summary": "Packages - Install", - "tags": [], + "summary": "Install package", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -755,8 +758,10 @@ "deprecated": true }, "delete": { - "summary": "Packages - Delete", - "tags": [], + "summary": "Delete ackage", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -835,8 +840,10 @@ }, "/epm/packages/{pkgName}/{pkgVersion}": { "get": { - "summary": "Packages - Info", - "tags": [], + "summary": "Get package", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -940,12 +947,14 @@ "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)" } ], "post": { - "summary": "Packages - Install", - "tags": [], + "summary": "Install package", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -1030,8 +1039,10 @@ } }, "put": { - "summary": "Packages - Update", - "tags": [], + "summary": "Update package settings", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -1095,8 +1106,10 @@ } }, "delete": { - "summary": "Packages - Delete", - "tags": [], + "summary": "Delete package", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -1166,8 +1179,10 @@ }, "/epm/packages/{pkgName}/{pkgVersion}/{filePath}": { "get": { - "summary": "Packages - Get file from registry", - "tags": [], + "summary": "Get package file", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -1225,8 +1240,10 @@ }, "/epm/packages/{pkgName}/stats": { "get": { - "summary": "Get stats for a package", - "tags": [], + "summary": "Get package stats", + "tags": [ + "Elastic Package Manager (EPM)" + ], "responses": { "200": { "description": "OK", @@ -1270,8 +1287,10 @@ }, "/agents/setup": { "get": { - "summary": "Agents setup - Info", - "tags": [], + "summary": "Get agent setup info", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -1295,7 +1314,10 @@ ] }, "post": { - "summary": "Agents setup - Create", + "summary": "Initiate agent setup", + "tags": [ + "Agents" + ], "operationId": "setup-agents", "responses": { "200": { @@ -1342,8 +1364,10 @@ }, "/agent-status": { "get": { - "summary": "Agents - Summary stats", - "tags": [], + "summary": "Get agent status summary", + "tags": [ + "Agent status" + ], "responses": { "200": { "description": "OK", @@ -1411,8 +1435,10 @@ }, "/agent_status": { "get": { - "summary": "Agents - Summary stats", - "tags": [], + "summary": "Get agent status summary", + "tags": [ + "Agent status" + ], "responses": { "200": { "description": "OK", @@ -1499,8 +1525,10 @@ }, "/agent_status/data": { "get": { - "summary": "Agents - Get incoming data", - "tags": [], + "summary": "Get incoming agent data", + "tags": [ + "Agent status" + ], "responses": { "200": { "description": "OK", @@ -1550,8 +1578,10 @@ }, "/agents": { "get": { - "summary": "Agents - List", - "tags": [], + "summary": "List agents", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -1611,8 +1641,10 @@ }, "/agents/bulk_upgrade": { "post": { - "summary": "Agents - Bulk Upgrade", - "tags": [], + "summary": "Bulk upgrade agents", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -1663,7 +1695,10 @@ }, "/agents/action_status": { "get": { - "summary": "Agents - Action status", + "summary": "Get agent action status", + "tags": [ + "Agent actions" + ], "parameters": [ { "$ref": "#/components/parameters/page_size" @@ -1774,8 +1809,10 @@ } ], "get": { - "summary": "Agent - Info", - "tags": [], + "summary": "Get agent by ID", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -1807,8 +1844,10 @@ ] }, "put": { - "summary": "Agent - Update", - "tags": [], + "summary": "Update agent by ID", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -1861,8 +1900,10 @@ } }, "delete": { - "summary": "Agent - Delete", - "tags": [], + "summary": "Delete agent by ID", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -1909,8 +1950,10 @@ } ], "post": { - "summary": "Agent - Actions", - "tags": [], + "summary": "Create agent action", + "tags": [ + "Agent actions" + ], "responses": { "200": { "description": "OK", @@ -1983,8 +2026,10 @@ } ], "post": { - "summary": "Agent - Cancel Action", - "tags": [], + "summary": "Cancel agent action", + "tags": [ + "Agent actions" + ], "responses": { "200": { "description": "OK", @@ -2033,8 +2078,10 @@ } ], "get": { - "summary": "Get agent upload file", - "tags": [], + "summary": "Get file uploaded by agent", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2079,8 +2126,10 @@ } ], "post": { - "summary": "Agent - Reassign", - "tags": [], + "summary": "Reassign agent", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2122,8 +2171,10 @@ } }, "put": { - "summary": "Agent - Reassign", - "tags": [], + "summary": "Reassign agent", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2178,8 +2229,10 @@ } ], "post": { - "summary": "Agent - Unenroll", - "tags": [], + "summary": "Unenroll agent", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2253,8 +2306,10 @@ } ], "post": { - "summary": "Agent - Upgrade", - "tags": [], + "summary": "Upgrade agent", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2301,7 +2356,9 @@ ], "get": { "summary": "List agent uploads", - "tags": [], + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2335,8 +2392,10 @@ }, "/agents/bulk_reassign": { "post": { - "summary": "Agents - Bulk reassign", - "tags": [], + "summary": "Bulk reassign agents", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2405,8 +2464,10 @@ }, "/agents/bulk_unenroll": { "post": { - "summary": "Agents - Bulk unenroll", - "tags": [], + "summary": "Bulk unenroll agents", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2482,8 +2543,10 @@ }, "/agents/bulk_update_agent_tags": { "post": { - "summary": "Agents - Bulk update tags", - "tags": [], + "summary": "Bulk update agent tags", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2570,8 +2633,10 @@ }, "/agents/tags": { "get": { - "summary": "Agent Tags - List", - "description": "List all agent tags", + "summary": "List agent tags", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2602,8 +2667,10 @@ } ], "post": { - "summary": "Agent - Request Diagnostics", - "tags": [], + "summary": "Request agent diagnostics", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2634,8 +2701,10 @@ }, "/agents/bulk_request_diagnostics": { "post": { - "summary": "Agent - Bulk Request Diagnostics", - "tags": [], + "summary": "Bulk request diagnostics from agents", + "tags": [ + "Agents" + ], "responses": { "200": { "description": "OK", @@ -2701,8 +2770,10 @@ }, "/agent_policies": { "get": { - "summary": "Agent policies - List", - "tags": [], + "summary": "List agent policies", + "tags": [ + "Agent policies" + ], "responses": { "200": { "description": "OK", @@ -2772,8 +2843,10 @@ "description": "" }, "post": { - "summary": "Agent policy - Create", - "tags": [], + "summary": "Create agent policy", + "tags": [ + "Agent policies" + ], "responses": { "200": { "description": "OK", @@ -2824,8 +2897,10 @@ } ], "get": { - "summary": "Agent policy - Info", - "tags": [], + "summary": "Get agent policy by ID", + "tags": [ + "Agent policies" + ], "responses": { "200": { "description": "OK", @@ -2854,8 +2929,10 @@ "parameters": [] }, "put": { - "summary": "Agent policy - Update", - "tags": [], + "summary": "Update agent policy by ID", + "tags": [ + "Agent policies" + ], "responses": { "200": { "description": "OK", @@ -2908,7 +2985,10 @@ } ], "post": { - "summary": "Agent policy - copy one policy", + "summary": "Copy agent policy by ID", + "tags": [ + "Agent policies" + ], "operationId": "agent-policy-copy", "parameters": [ { @@ -2963,7 +3043,10 @@ }, "/agent_policies/{agentPolicyId}/full": { "get": { - "summary": "Agent policy - Get full policy", + "summary": "Get full agent policy by ID", + "tags": [ + "Agent policies" + ], "operationId": "agent-policy-full", "responses": { "200": { @@ -3030,7 +3113,10 @@ }, "/agent_policies/{agentPolicyId}/download": { "get": { - "summary": "Agent policy - Download", + "summary": "Download agent policy by ID", + "tags": [ + "Agent policies" + ], "operationId": "agent-policy-download", "responses": { "200": { @@ -3090,8 +3176,10 @@ }, "/agent_policies/_bulk_get": { "post": { - "summary": "Agent policies - Bulk Get", - "tags": [], + "summary": "Bulk get agent policies", + "tags": [ + "Agent policies" + ], "requestBody": { "content": { "application/json": { @@ -3153,7 +3241,10 @@ }, "/agent_policies/delete": { "post": { - "summary": "Agent policy - Delete", + "summary": "Delete agent policy by ID", + "tags": [ + "Agent policies" + ], "operationId": "delete-agent-policy", "responses": { "200": { @@ -3209,8 +3300,10 @@ }, "/data_streams": { "get": { - "summary": "Data streams - List", - "tags": [], + "summary": "List data streams", + "tags": [ + "Data streams" + ], "responses": { "200": { "description": "OK", @@ -3240,8 +3333,10 @@ }, "/enrollment-api-keys": { "get": { - "summary": "Enrollment API Keys - List", - "tags": [], + "summary": "List enrollment API keys", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3292,8 +3387,10 @@ "deprecated": true }, "post": { - "summary": "Enrollment API Key - Create", - "tags": [], + "summary": "Create enrollment API key", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3341,8 +3438,10 @@ } ], "get": { - "summary": "Enrollment API Key - Info", - "tags": [], + "summary": "Get enrollment API key by ID", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3370,8 +3469,10 @@ "deprecated": true }, "delete": { - "summary": "Enrollment API Key - Delete", - "tags": [], + "summary": "Delete enrollment API key by ID", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3409,8 +3510,10 @@ }, "/enrollment_api_keys": { "get": { - "summary": "Enrollment API Keys - List", - "tags": [], + "summary": "List enrollment API keys", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3460,8 +3563,10 @@ "parameters": [] }, "post": { - "summary": "Enrollment API Key - Create", - "tags": [], + "summary": "Create enrollment API key", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3508,8 +3613,10 @@ } ], "get": { - "summary": "Enrollment API Key - Info", - "tags": [], + "summary": "Get enrollment API key by ID", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3536,8 +3643,10 @@ "operationId": "get-enrollment-api-key" }, "delete": { - "summary": "Enrollment API Key - Delete", - "tags": [], + "summary": "Delete enrollment API key by ID", + "tags": [ + "Enrollment API keys" + ], "responses": { "200": { "description": "OK", @@ -3574,8 +3683,10 @@ }, "/package_policies": { "get": { - "summary": "Package policies - List", - "tags": [], + "summary": "List package policies", + "tags": [ + "Package policies" + ], "responses": { "200": { "description": "OK", @@ -3617,7 +3728,10 @@ }, "parameters": [], "post": { - "summary": "Package policy - Create", + "summary": "Create package policy", + "tags": [ + "Package policies" + ], "operationId": "create-package-policy", "responses": { "200": { @@ -3661,8 +3775,10 @@ }, "/package_policies/_bulk_get": { "post": { - "summary": "Package policies - Bulk Get", - "tags": [], + "summary": "Bulk get package policies", + "tags": [ + "Package policies" + ], "requestBody": { "content": { "application/json": { @@ -3720,7 +3836,10 @@ }, "/package_policies/delete": { "post": { - "summary": "Package policy - Delete", + "summary": "Delete package policy", + "tags": [ + "Package policies" + ], "operationId": "post-delete-package-policy", "requestBody": { "content": { @@ -3787,7 +3906,10 @@ }, "/package_policies/upgrade": { "post": { - "summary": "Package policy - Upgrade", + "summary": "Upgrade package policy to a newer package version", + "tags": [ + "Package policies" + ], "operationId": "upgrade-package-policy", "requestBody": { "content": { @@ -3846,7 +3968,10 @@ }, "/package_policies/upgrade/dryrun": { "post": { - "summary": "Package policy - Upgrade Dry run", + "summary": "Dry run package policy upgrade", + "tags": [ + "Package policies" + ], "operationId": "upgrade-package-policy-dry-run", "requestBody": { "content": { @@ -3907,8 +4032,10 @@ }, "/package_policies/{packagePolicyId}": { "get": { - "summary": "Package policy - Info", - "tags": [], + "summary": "Get package policy by ID", + "tags": [ + "Package policies" + ], "responses": { "200": { "description": "OK", @@ -3945,7 +4072,10 @@ } ], "put": { - "summary": "Package policy - Update", + "summary": "Update package policy by ID", + "tags": [ + "Package policies" + ], "operationId": "update-package-policy", "requestBody": { "content": { @@ -3990,8 +4120,10 @@ ] }, "delete": { - "summary": "Package policy - Delete", - "tags": [], + "summary": "Delete package policy by ID", + "tags": [ + "Package policies" + ], "operationId": "delete-package-policy", "responses": { "200": { @@ -4029,8 +4161,10 @@ }, "/outputs": { "get": { - "summary": "Outputs", - "tags": [], + "summary": "List outputs", + "tags": [ + "Outputs" + ], "responses": { "200": { "description": "OK", @@ -4066,9 +4200,10 @@ "operationId": "get-outputs" }, "post": { - "summary": "Outputs", - "description": "Create a new output", - "tags": [], + "summary": "Create output", + "tags": [ + "Outputs" + ], "responses": { "200": { "description": "OK", @@ -4139,8 +4274,10 @@ }, "/outputs/{outputId}": { "get": { - "summary": "Output - Info", - "tags": [], + "summary": "Get output by ID", + "tags": [ + "Outputs" + ], "responses": { "200": { "description": "OK", @@ -4177,7 +4314,10 @@ } ], "delete": { - "summary": "Output - Delete", + "summary": "Delete output by ID", + "tags": [ + "Outputs" + ], "operationId": "delete-output", "responses": { "200": { @@ -4209,7 +4349,10 @@ ] }, "put": { - "summary": "Output - Update", + "summary": "Update output by ID", + "tags": [ + "Outputs" + ], "operationId": "update-output", "requestBody": { "content": { @@ -4286,10 +4429,46 @@ ] } }, + "/logstash_api_keys": { + "post": { + "summary": "Generate Logstash API key", + "tags": [ + "Outputs" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "api_key": { + "type": "string" + } + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/error" + } + }, + "operationId": "generate-logstash-api-key", + "parameters": [ + { + "$ref": "#/components/parameters/kbn_xsrf" + } + ] + } + }, "/agent_download_sources": { "get": { - "summary": "Agent Download Sources", - "tags": [], + "summary": "List agent binary download sources", + "tags": [ + "Agent binary download sources" + ], "responses": { "200": { "description": "OK", @@ -4325,9 +4504,10 @@ "operationId": "get-download-sources" }, "post": { - "summary": "Agent Download Sources", - "description": "Create a new agent download source", - "tags": [], + "summary": "Create agent binary download source", + "tags": [ + "Agent binary download sources" + ], "responses": { "200": { "description": "OK", @@ -4381,8 +4561,10 @@ }, "/agent_download_sources/{sourceId}": { "get": { - "summary": "Agent Download Sources - Info", - "tags": [], + "summary": "Get agent binary download source by ID", + "tags": [ + "Agent binary download sources" + ], "responses": { "200": { "description": "OK", @@ -4419,7 +4601,10 @@ } ], "delete": { - "summary": "Agent Download Sources - Delete", + "summary": "Delete agent binary download source by ID", + "tags": [ + "Agent binary download sources" + ], "operationId": "delete-download-source", "responses": { "200": { @@ -4451,7 +4636,10 @@ ] }, "put": { - "summary": "Agent Download Sources - Update", + "summary": "Update agent binary download source by ID", + "tags": [ + "Agent binary download sources" + ], "operationId": "update-download-source", "requestBody": { "content": { @@ -4508,43 +4696,12 @@ ] } }, - "/logstash_api_keys": { - "post": { - "summary": "Generate Logstash API key", - "tags": [], - "responses": { - "200": { - "description": "OK", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "api_key": { - "type": "string" - } - } - } - } - } - }, - "400": { - "$ref": "#/components/responses/error" - } - }, - "operationId": "generate-logstash-api-key", - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - } - ] - } - }, "/fleet_server_hosts": { "get": { - "summary": "Fleet Server Hosts - List", - "description": "Return a list of Fleet server hosts", - "tags": [], + "summary": "List Fleet Server hosts", + "tags": [ + "Fleet Server hosts" + ], "responses": { "200": { "description": "OK", @@ -4580,9 +4737,10 @@ "operationId": "get-fleet-server-hosts" }, "post": { - "summary": "Fleet Server Hosts - Create", - "description": "Create a new Fleet Server Host", - "tags": [], + "summary": "Create Fleet Server host", + "tags": [ + "Fleet Server hosts" + ], "responses": { "200": { "description": "OK", @@ -4638,8 +4796,10 @@ }, "/fleet_server_hosts/{itemId}": { "get": { - "summary": "Fleet Server Hosts - Info", - "tags": [], + "summary": "Get Fleet Server host by ID", + "tags": [ + "Fleet Server hosts" + ], "responses": { "200": { "description": "OK", @@ -4676,7 +4836,10 @@ } ], "delete": { - "summary": "Fleet Server Hosts - Delete", + "summary": "Delete Fleet Server host by ID", + "tags": [ + "Fleet Server hosts" + ], "operationId": "delete-fleet-server-hosts", "responses": { "200": { @@ -4708,7 +4871,10 @@ ] }, "put": { - "summary": "Fleet Server Hosts - Update", + "summary": "Update Fleet Server host by ID", + "tags": [ + "Fleet Server hosts" + ], "operationId": "update-fleet-server-hosts", "requestBody": { "content": { @@ -4765,9 +4931,10 @@ }, "/proxies": { "get": { - "summary": "Fleet Proxies - List", - "description": "Return a list of Proxies", - "tags": [], + "summary": "List proxies", + "tags": [ + "Proxies" + ], "responses": { "200": { "description": "OK", @@ -4803,9 +4970,10 @@ "operationId": "get-fleet-proxies" }, "post": { - "summary": "Fleet Proxies - Create", - "description": "Create a new Fleet Server Host", - "tags": [], + "summary": "Create proxy", + "tags": [ + "Proxies" + ], "responses": { "200": { "description": "OK", @@ -4867,8 +5035,10 @@ }, "/proxies/{itemId}": { "get": { - "summary": "Fleet Proxies - Info", - "tags": [], + "summary": "Get proxy by ID", + "tags": [ + "Proxies" + ], "responses": { "200": { "description": "OK", @@ -4905,7 +5075,10 @@ } ], "delete": { - "summary": "Fleet Proxies - Delete", + "summary": "Delete proxy by ID", + "tags": [ + "Proxies" + ], "operationId": "delete-fleet-proxies", "responses": { "200": { @@ -4937,7 +5110,10 @@ ] }, "put": { - "summary": "Fleet Proxies - Update", + "summary": "Update proxy by ID", + "tags": [ + "Proxies" + ], "operationId": "update-fleet-proxies", "requestBody": { "content": { @@ -5000,8 +5176,10 @@ }, "/kubernetes": { "get": { - "summary": "Get K8s Full Agent Manifest", - "tags": [], + "summary": "Get full K8s agent manifest", + "tags": [ + "Kubernetes" + ], "responses": { "200": { "description": "OK", @@ -5154,6 +5332,29 @@ } } }, + "responses": { + "error": { + "description": "Generic Error", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "statusCode": { + "type": "number" + }, + "error": { + "type": "string" + }, + "message": { + "type": "string" + } + } + } + } + } + } + }, "schemas": { "fleet_setup_response": { "title": "Fleet Setup response", @@ -7151,29 +7352,6 @@ "url" ] } - }, - "responses": { - "error": { - "description": "Generic Error", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "statusCode": { - "type": "number" - }, - "error": { - "type": "string" - }, - "message": { - "type": "string" - } - } - } - } - } - } } }, "security": [ diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 5f67c8630b0dc..9d6ae17a04a41 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -13,10 +13,44 @@ servers: - url: http://localhost:5601/api/fleet description: local paths: + /health_check: + post: + summary: Fleet Server health check + tags: + - Fleet internals + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + name: + type: string + status: + type: string + host: + type: string + '400': + $ref: '#/components/responses/error' + operationId: fleet-server-health-check + parameters: + - $ref: '#/components/parameters/kbn_xsrf' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + host: + type: string /setup: post: - summary: Setup - tags: [] + summary: Initiate Fleet setup + tags: + - Fleet internals responses: '200': description: OK @@ -40,8 +74,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /settings: get: - summary: Settings - tags: [] + summary: Get settings + tags: + - Fleet internals responses: '200': description: OK @@ -53,8 +88,9 @@ paths: $ref: '#/components/responses/error' operationId: get-settings put: - summary: Settings - Update - tags: [] + summary: Update settings + tags: + - Fleet internals requestBody: content: application/json: @@ -80,42 +116,11 @@ paths: '400': $ref: '#/components/responses/error' operationId: update-settings - /health_check: - post: - summary: Fleet Server Health Check - tags: [] - responses: - '200': - description: OK - content: - application/json: - schema: - type: object - properties: - name: - type: string - status: - type: string - host: - type: string - '400': - $ref: '#/components/responses/error' - operationId: fleet-server-health-check - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - host: - type: string /service-tokens: post: - summary: Generate service tokens - tags: [] + summary: Create service token + tags: + - Service tokens responses: '200': description: OK @@ -136,8 +141,9 @@ paths: deprecated: true /service_tokens: post: - summary: Generate service tokens - tags: [] + summary: Create service token + tags: + - Service tokens responses: '200': description: OK @@ -158,7 +164,8 @@ paths: /epm/verification_key_id: get: summary: Get package signature verification key ID - tags: [] + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -183,26 +190,12 @@ paths: '400': $ref: '#/components/responses/error' operationId: packages-get-verification-key-id - parameters: - - schema: - type: string - name: pkgName - in: path - required: true - - schema: - type: string - name: pkgVersion - in: path - required: true - - schema: - type: string - name: filePath - in: path - required: true + parameters: [] /epm/categories: get: - summary: Package categories - tags: [] + summary: List package categories + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -221,7 +214,7 @@ paths: default: false description: >- Whether to include prerelease packages in categories count (e.g. beta, - rc, preview) + rc, preview) - in: query name: experimental deprecated: true @@ -235,8 +228,9 @@ paths: default: false /epm/packages/limited: get: - summary: Packages - Get limited list - tags: [] + summary: Get limited package list + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -255,8 +249,9 @@ paths: parameters: [] /epm/packages: get: - summary: Packages - List - tags: [] + summary: List packages + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -286,7 +281,7 @@ paths: default: false description: >- Whether to return prerelease versions of packages (e.g. beta, rc, - preview) + preview) - in: query name: experimental deprecated: true @@ -298,8 +293,9 @@ paths: schema: type: string post: - summary: Packages - Install by upload - tags: [] + summary: Install by package by direct upload + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -351,8 +347,9 @@ paths: format: binary /epm/packages/_bulk: post: - summary: Packages - Bulk install - tags: [] + summary: Bulk install packages + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -371,7 +368,7 @@ paths: default: false description: >- Whether to return prerelease versions of packages (e.g. beta, rc, - preview) + preview) requestBody: content: application/json: @@ -390,8 +387,9 @@ paths: - packages /epm/packages/{pkgkey}: get: - summary: Packages - Info - tags: [] + summary: Get package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -434,11 +432,12 @@ paths: default: false description: >- Whether to return prerelease versions of packages (e.g. beta, rc, - preview) + preview) deprecated: true post: - summary: Packages - Install - tags: [] + summary: Install package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -484,8 +483,9 @@ paths: type: boolean deprecated: true delete: - summary: Packages - Delete - tags: [] + summary: Delete ackage + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -531,8 +531,9 @@ paths: deprecated: true /epm/packages/{pkgName}/{pkgVersion}: get: - summary: Packages - Info - tags: [] + summary: Get package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -600,10 +601,11 @@ paths: default: false description: >- Whether to return prerelease versions of packages (e.g. beta, rc, - preview) + preview) post: - summary: Packages - Install - tags: [] + summary: Install package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -654,8 +656,9 @@ paths: ignore_constraints: type: boolean put: - summary: Packages - Update - tags: [] + summary: Update package settings + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -693,8 +696,9 @@ paths: keepPoliciesUpToDate: type: boolean delete: - summary: Packages - Delete - tags: [] + summary: Delete package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -734,8 +738,9 @@ paths: type: boolean /epm/packages/{pkgName}/{pkgVersion}/{filePath}: get: - summary: Packages - Get file from registry - tags: [] + summary: Get package file + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -771,8 +776,9 @@ paths: required: true /epm/packages/{pkgName}/stats: get: - summary: Get stats for a package - tags: [] + summary: Get package stats + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -798,8 +804,9 @@ paths: required: true /agents/setup: get: - summary: Agents setup - Info - tags: [] + summary: Get agent setup info + tags: + - Agents responses: '200': description: OK @@ -813,7 +820,9 @@ paths: security: - basicAuth: [] post: - summary: Agents setup - Create + summary: Initiate agent setup + tags: + - Agents operationId: setup-agents responses: '200': @@ -841,8 +850,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /agent-status: get: - summary: Agents - Summary stats - tags: [] + summary: Get agent status summary + tags: + - Agent status responses: '200': description: OK @@ -888,8 +898,9 @@ paths: deprecated: true /agent_status: get: - summary: Agents - Summary stats - tags: [] + summary: Get agent status summary + tags: + - Agent status responses: '200': description: OK @@ -948,8 +959,9 @@ paths: required: false /agent_status/data: get: - summary: Agents - Get incoming data - tags: [] + summary: Get incoming agent data + tags: + - Agent status responses: '200': description: OK @@ -980,8 +992,9 @@ paths: required: true /agents: get: - summary: Agents - List - tags: [] + summary: List agents + tags: + - Agents responses: '200': description: OK @@ -1010,8 +1023,9 @@ paths: - basicAuth: [] /agents/bulk_upgrade: post: - summary: Agents - Bulk Upgrade - tags: [] + summary: Bulk upgrade agents + tags: + - Agents responses: '200': description: OK @@ -1043,7 +1057,9 @@ paths: start_time: '2022-08-03T14:00:00.000Z' /agents/action_status: get: - summary: Agents - Action status + summary: Get agent action status + tags: + - Agent actions parameters: - $ref: '#/components/parameters/page_size' - $ref: '#/components/parameters/page_index' @@ -1116,8 +1132,9 @@ paths: in: path required: true get: - summary: Agent - Info - tags: [] + summary: Get agent by ID + tags: + - Agents responses: '200': description: OK @@ -1136,8 +1153,9 @@ paths: parameters: - $ref: '#/components/parameters/with_metrics' put: - summary: Agent - Update - tags: [] + summary: Update agent by ID + tags: + - Agents responses: '200': description: OK @@ -1169,8 +1187,9 @@ paths: items: type: string delete: - summary: Agent - Delete - tags: [] + summary: Delete agent by ID + tags: + - Agents responses: '200': description: OK @@ -1198,8 +1217,9 @@ paths: in: path required: true post: - summary: Agent - Actions - tags: [] + summary: Create agent action + tags: + - Agent actions responses: '200': description: OK @@ -1243,8 +1263,9 @@ paths: in: path required: true post: - summary: Agent - Cancel Action - tags: [] + summary: Cancel agent action + tags: + - Agent actions responses: '200': description: OK @@ -1273,8 +1294,9 @@ paths: in: path required: true get: - summary: Get agent upload file - tags: [] + summary: Get file uploaded by agent + tags: + - Agents responses: '200': description: OK @@ -1302,8 +1324,9 @@ paths: in: path required: true post: - summary: Agent - Reassign - tags: [] + summary: Reassign agent + tags: + - Agents responses: '200': description: OK @@ -1328,8 +1351,9 @@ paths: required: - policy_id put: - summary: Agent - Reassign - tags: [] + summary: Reassign agent + tags: + - Agents responses: '200': description: OK @@ -1362,8 +1386,9 @@ paths: in: path required: true post: - summary: Agent - Unenroll - tags: [] + summary: Unenroll agent + tags: + - Agents responses: '200': description: OK @@ -1407,8 +1432,9 @@ paths: in: path required: true post: - summary: Agent - Upgrade - tags: [] + summary: Upgrade agent + tags: + - Agents responses: '200': description: OK @@ -1436,7 +1462,8 @@ paths: required: true get: summary: List agent uploads - tags: [] + tags: + - Agents responses: '200': description: OK @@ -1457,8 +1484,9 @@ paths: operationId: list-agent-uploads /agents/bulk_reassign: post: - summary: Agents - Bulk reassign - tags: [] + summary: Bulk reassign agents + tags: + - Agents responses: '200': description: OK @@ -1499,8 +1527,9 @@ paths: agents: 'fleet-agents.policy_id : ("policy1" or "policy2")' /agents/bulk_unenroll: post: - summary: Agents - Bulk unenroll - tags: [] + summary: Bulk unenroll agents + tags: + - Agents responses: '200': description: OK @@ -1546,8 +1575,9 @@ paths: - agent2 /agents/bulk_update_agent_tags: post: - summary: Agents - Bulk update tags - tags: [] + summary: Bulk update agent tags + tags: + - Agents responses: '200': description: OK @@ -1599,8 +1629,9 @@ paths: - existingTag /agents/tags: get: - summary: Agent Tags - List - description: List all agent tags + summary: List agent tags + tags: + - Agents responses: '200': description: OK @@ -1619,8 +1650,9 @@ paths: in: path required: true post: - summary: Agent - Request Diagnostics - tags: [] + summary: Request agent diagnostics + tags: + - Agents responses: '200': description: OK @@ -1638,8 +1670,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /agents/bulk_request_diagnostics: post: - summary: Agent - Bulk Request Diagnostics - tags: [] + summary: Bulk request diagnostics from agents + tags: + - Agents responses: '200': description: OK @@ -1677,8 +1710,9 @@ paths: agents: 'fleet-agents.policy_id : ("policy1" or "policy2")' /agent_policies: get: - summary: Agent policies - List - tags: [] + summary: List agent policies + tags: + - Agent policies responses: '200': description: OK @@ -1727,8 +1761,9 @@ paths: 0 if set to true. description: '' post: - summary: Agent policy - Create - tags: [] + summary: Create agent policy + tags: + - Agent policies responses: '200': description: OK @@ -1758,8 +1793,9 @@ paths: in: path required: true get: - summary: Agent policy - Info - tags: [] + summary: Get agent policy by ID + tags: + - Agent policies responses: '200': description: OK @@ -1778,8 +1814,9 @@ paths: description: Get one agent policy parameters: [] put: - summary: Agent policy - Update - tags: [] + summary: Update agent policy by ID + tags: + - Agent policies responses: '200': description: OK @@ -1810,7 +1847,9 @@ paths: in: path required: true post: - summary: Agent policy - copy one policy + summary: Copy agent policy by ID + tags: + - Agent policies operationId: agent-policy-copy parameters: - $ref: '#/components/parameters/kbn_xsrf' @@ -1843,7 +1882,9 @@ paths: description: '' /agent_policies/{agentPolicyId}/full: get: - summary: Agent policy - Get full policy + summary: Get full agent policy by ID + tags: + - Agent policies operationId: agent-policy-full responses: '200': @@ -1882,7 +1923,9 @@ paths: required: false /agent_policies/{agentPolicyId}/download: get: - summary: Agent policy - Download + summary: Download agent policy by ID + tags: + - Agent policies operationId: agent-policy-download responses: '200': @@ -1919,8 +1962,9 @@ paths: required: false /agent_policies/_bulk_get: post: - summary: Agent policies - Bulk Get - tags: [] + summary: Bulk get agent policies + tags: + - Agent policies requestBody: content: application/json: @@ -1960,7 +2004,9 @@ paths: parameters: [] /agent_policies/delete: post: - summary: Agent policy - Delete + summary: Delete agent policy by ID + tags: + - Agent policies operationId: delete-agent-policy responses: '200': @@ -1994,8 +2040,9 @@ paths: parameters: [] /data_streams: get: - summary: Data streams - List - tags: [] + summary: List data streams + tags: + - Data streams responses: '200': description: OK @@ -2014,8 +2061,9 @@ paths: parameters: [] /enrollment-api-keys: get: - summary: Enrollment API Keys - List - tags: [] + summary: List enrollment API keys + tags: + - Enrollment API keys responses: '200': description: OK @@ -2050,8 +2098,9 @@ paths: parameters: [] deprecated: true post: - summary: Enrollment API Key - Create - tags: [] + summary: Create enrollment API key + tags: + - Enrollment API keys responses: '200': description: OK @@ -2080,8 +2129,9 @@ paths: in: path required: true get: - summary: Enrollment API Key - Info - tags: [] + summary: Get enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK @@ -2099,8 +2149,9 @@ paths: operationId: get-enrollment-api-key-deprecated deprecated: true delete: - summary: Enrollment API Key - Delete - tags: [] + summary: Delete enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK @@ -2123,8 +2174,9 @@ paths: deprecated: true /enrollment_api_keys: get: - summary: Enrollment API Keys - List - tags: [] + summary: List enrollment API keys + tags: + - Enrollment API keys responses: '200': description: OK @@ -2158,8 +2210,9 @@ paths: operationId: get-enrollment-api-keys parameters: [] post: - summary: Enrollment API Key - Create - tags: [] + summary: Create enrollment API key + tags: + - Enrollment API keys responses: '200': description: OK @@ -2187,8 +2240,9 @@ paths: in: path required: true get: - summary: Enrollment API Key - Info - tags: [] + summary: Get enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK @@ -2205,8 +2259,9 @@ paths: $ref: '#/components/responses/error' operationId: get-enrollment-api-key delete: - summary: Enrollment API Key - Delete - tags: [] + summary: Delete enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK @@ -2228,8 +2283,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /package_policies: get: - summary: Package policies - List - tags: [] + summary: List package policies + tags: + - Package policies responses: '200': description: OK @@ -2257,7 +2313,9 @@ paths: parameters: [] parameters: [] post: - summary: Package policy - Create + summary: Create package policy + tags: + - Package policies operationId: create-package-policy responses: '200': @@ -2285,8 +2343,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /package_policies/_bulk_get: post: - summary: Package policies - Bulk Get - tags: [] + summary: Bulk get package policies + tags: + - Package policies requestBody: content: application/json: @@ -2323,7 +2382,9 @@ paths: parameters: [] /package_policies/delete: post: - summary: Package policy - Delete + summary: Delete package policy + tags: + - Package policies operationId: post-delete-package-policy requestBody: content: @@ -2364,7 +2425,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /package_policies/upgrade: post: - summary: Package policy - Upgrade + summary: Upgrade package policy to a newer package version + tags: + - Package policies operationId: upgrade-package-policy requestBody: content: @@ -2401,7 +2464,9 @@ paths: $ref: '#/components/responses/error' /package_policies/upgrade/dryrun: post: - summary: Package policy - Upgrade Dry run + summary: Dry run package policy upgrade + tags: + - Package policies operationId: upgrade-package-policy-dry-run requestBody: content: @@ -2439,8 +2504,9 @@ paths: $ref: '#/components/responses/error' /package_policies/{packagePolicyId}: get: - summary: Package policy - Info - tags: [] + summary: Get package policy by ID + tags: + - Package policies responses: '200': description: OK @@ -2463,7 +2529,9 @@ paths: in: path required: true put: - summary: Package policy - Update + summary: Update package policy by ID + tags: + - Package policies operationId: update-package-policy requestBody: content: @@ -2490,8 +2558,9 @@ paths: parameters: - $ref: '#/components/parameters/kbn_xsrf' delete: - summary: Package policy - Delete - tags: [] + summary: Delete package policy by ID + tags: + - Package policies operationId: delete-package-policy responses: '200': @@ -2514,8 +2583,9 @@ paths: in: query /outputs: get: - summary: Outputs - tags: [] + summary: List outputs + tags: + - Outputs responses: '200': description: OK @@ -2538,9 +2608,9 @@ paths: $ref: '#/components/responses/error' operationId: get-outputs post: - summary: Outputs - description: Create a new output - tags: [] + summary: Create output + tags: + - Outputs responses: '200': description: OK @@ -2585,8 +2655,9 @@ paths: operationId: post-outputs /outputs/{outputId}: get: - summary: Output - Info - tags: [] + summary: Get output by ID + tags: + - Outputs responses: '200': description: OK @@ -2609,7 +2680,9 @@ paths: in: path required: true delete: - summary: Output - Delete + summary: Delete output by ID + tags: + - Outputs operationId: delete-output responses: '200': @@ -2628,7 +2701,9 @@ paths: parameters: - $ref: '#/components/parameters/kbn_xsrf' put: - summary: Output - Update + summary: Update output by ID + tags: + - Outputs operationId: update-output requestBody: content: @@ -2675,10 +2750,31 @@ paths: $ref: '#/components/responses/error' parameters: - $ref: '#/components/parameters/kbn_xsrf' + /logstash_api_keys: + post: + summary: Generate Logstash API key + tags: + - Outputs + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + api_key: + type: string + '400': + $ref: '#/components/responses/error' + operationId: generate-logstash-api-key + parameters: + - $ref: '#/components/parameters/kbn_xsrf' /agent_download_sources: get: - summary: Agent Download Sources - tags: [] + summary: List agent binary download sources + tags: + - Agent binary download sources responses: '200': description: OK @@ -2701,9 +2797,9 @@ paths: $ref: '#/components/responses/error' operationId: get-download-sources post: - summary: Agent Download Sources - description: Create a new agent download source - tags: [] + summary: Create agent binary download source + tags: + - Agent binary download sources responses: '200': description: OK @@ -2737,8 +2833,9 @@ paths: operationId: post-download-sources /agent_download_sources/{sourceId}: get: - summary: Agent Download Sources - Info - tags: [] + summary: Get agent binary download source by ID + tags: + - Agent binary download sources responses: '200': description: OK @@ -2761,7 +2858,9 @@ paths: in: path required: true delete: - summary: Agent Download Sources - Delete + summary: Delete agent binary download source by ID + tags: + - Agent binary download sources operationId: delete-download-source responses: '200': @@ -2780,7 +2879,9 @@ paths: parameters: - $ref: '#/components/parameters/kbn_xsrf' put: - summary: Agent Download Sources - Update + summary: Update agent binary download source by ID + tags: + - Agent binary download sources operationId: update-download-source requestBody: content: @@ -2814,30 +2915,11 @@ paths: $ref: '#/components/responses/error' parameters: - $ref: '#/components/parameters/kbn_xsrf' - /logstash_api_keys: - post: - summary: Generate Logstash API key - tags: [] - responses: - '200': - description: OK - content: - application/json: - schema: - type: object - properties: - api_key: - type: string - '400': - $ref: '#/components/responses/error' - operationId: generate-logstash-api-key - parameters: - - $ref: '#/components/parameters/kbn_xsrf' /fleet_server_hosts: get: - summary: Fleet Server Hosts - List - description: Return a list of Fleet server hosts - tags: [] + summary: List Fleet Server hosts + tags: + - Fleet Server hosts responses: '200': description: OK @@ -2860,9 +2942,9 @@ paths: $ref: '#/components/responses/error' operationId: get-fleet-server-hosts post: - summary: Fleet Server Hosts - Create - description: Create a new Fleet Server Host - tags: [] + summary: Create Fleet Server host + tags: + - Fleet Server hosts responses: '200': description: OK @@ -2897,8 +2979,9 @@ paths: operationId: post-fleet-server-hosts /fleet_server_hosts/{itemId}: get: - summary: Fleet Server Hosts - Info - tags: [] + summary: Get Fleet Server host by ID + tags: + - Fleet Server hosts responses: '200': description: OK @@ -2921,7 +3004,9 @@ paths: in: path required: true delete: - summary: Fleet Server Hosts - Delete + summary: Delete Fleet Server host by ID + tags: + - Fleet Server hosts operationId: delete-fleet-server-hosts responses: '200': @@ -2940,7 +3025,9 @@ paths: parameters: - $ref: '#/components/parameters/kbn_xsrf' put: - summary: Fleet Server Hosts - Update + summary: Update Fleet Server host by ID + tags: + - Fleet Server hosts operationId: update-fleet-server-hosts requestBody: content: @@ -2974,9 +3061,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /proxies: get: - summary: Fleet Proxies - List - description: Return a list of Proxies - tags: [] + summary: List proxies + tags: + - Proxies responses: '200': description: OK @@ -2999,9 +3086,9 @@ paths: $ref: '#/components/responses/error' operationId: get-fleet-proxies post: - summary: Fleet Proxies - Create - description: Create a new Fleet Server Host - tags: [] + summary: Create proxy + tags: + - Proxies responses: '200': description: OK @@ -3040,8 +3127,9 @@ paths: operationId: post-fleet-proxies /proxies/{itemId}: get: - summary: Fleet Proxies - Info - tags: [] + summary: Get proxy by ID + tags: + - Proxies responses: '200': description: OK @@ -3064,7 +3152,9 @@ paths: in: path required: true delete: - summary: Fleet Proxies - Delete + summary: Delete proxy by ID + tags: + - Proxies operationId: delete-fleet-proxies responses: '200': @@ -3083,7 +3173,9 @@ paths: parameters: - $ref: '#/components/parameters/kbn_xsrf' put: - summary: Fleet Proxies - Update + summary: Update proxy by ID + tags: + - Proxies operationId: update-fleet-proxies requestBody: content: @@ -3121,8 +3213,9 @@ paths: - $ref: '#/components/parameters/kbn_xsrf' /kubernetes: get: - summary: Get K8s Full Agent Manifest - tags: [] + summary: Get full K8s agent manifest + tags: + - Kubernetes responses: '200': description: OK @@ -3230,6 +3323,20 @@ components: required: false schema: type: boolean + responses: + error: + description: Generic Error + content: + application/json: + schema: + type: object + properties: + statusCode: + type: number + error: + type: string + message: + type: string schemas: fleet_setup_response: title: Fleet Setup response @@ -4612,19 +4719,5 @@ components: required: - name - url - responses: - error: - description: Generic Error - content: - application/json: - schema: - type: object - properties: - statusCode: - type: number - error: - type: string - message: - type: string security: - basicAuth: [] diff --git a/x-pack/plugins/fleet/common/openapi/entrypoint.yaml b/x-pack/plugins/fleet/common/openapi/entrypoint.yaml index 37c33c28b1053..ca9d1cd3c8e19 100644 --- a/x-pack/plugins/fleet/common/openapi/entrypoint.yaml +++ b/x-pack/plugins/fleet/common/openapi/entrypoint.yaml @@ -13,18 +13,18 @@ servers: - url: 'http://localhost:5601/api/fleet' description: local paths: - # plugin-wide endpoint(s) + # Fleet internals + /health_check: + $ref: paths/health_check.yaml /setup: $ref: paths/setup.yaml /settings: $ref: paths/settings.yaml - # App endpoints - /health_check: - $ref: paths/health_check.yaml /service-tokens: $ref: paths/service_tokens_deprecated.yaml /service_tokens: $ref: paths/service_tokens.yaml + # EPM / integrations endpoints /epm/verification_key_id: $ref: paths/epm@verification_key_id.yaml @@ -44,7 +44,8 @@ paths: $ref: paths/epm@get_file.yaml '/epm/packages/{pkgName}/stats': $ref: 'paths/epm@packages@{pkg_name}@stats.yaml' - # Agent-related endpoints + + # Agent endpoints /agents/setup: $ref: paths/agents@setup.yaml /agent-status: @@ -87,6 +88,7 @@ paths: $ref: 'paths/agents@{agent_id}@request_diagnostics.yaml' /agents/bulk_request_diagnostics: $ref: 'paths/agents@bulk_request_diagnostics.yaml' + # Agent policies endpoints /agent_policies: $ref: paths/agent_policies.yaml @@ -102,9 +104,11 @@ paths: $ref: paths/agent_policies@_bulk_get.yaml /agent_policies/delete: $ref: paths/agent_policies@delete.yaml + # Data streams endpoints /data_streams: $ref: paths/data_streams.yaml + # Enrollment endpoints /enrollment-api-keys: $ref: paths/enrollment_api_keys_deprecated.yaml @@ -114,6 +118,7 @@ paths: $ref: paths/enrollment_api_keys.yaml '/enrollment_api_keys/{keyId}': $ref: 'paths/enrollment_api_keys@{key_id}.yaml' + # Package policies endpoints /package_policies: $ref: paths/package_policies.yaml @@ -127,27 +132,33 @@ paths: $ref: paths/package_policies@upgrade_dryrun.yaml '/package_policies/{packagePolicyId}': $ref: 'paths/package_policies@{package_policy_id}.yaml' + # Outputs /outputs: $ref: paths/outputs.yaml /outputs/{outputId}: $ref: paths/outputs@{output_id}.yaml + /logstash_api_keys: + $ref: paths/logstash_api_keys.yaml + + # Agent binary download sources /agent_download_sources: $ref: paths/agent_download_sources.yaml /agent_download_sources/{sourceId}: $ref: paths/agent_download_sources@{source_id}.yaml - /logstash_api_keys: - $ref: paths/logstash_api_keys.yaml + # Fleet server hosts /fleet_server_hosts: $ref: paths/fleet_server_hosts.yaml /fleet_server_hosts/{itemId}: $ref: paths/fleet_server_hosts@{item_id}.yaml + # Fleet proxies /proxies: $ref: paths/proxies.yaml /proxies/{itemId}: $ref: paths/proxies@{item_id}.yaml + # K8s /kubernetes: $ref: paths/kubernetes.yaml diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources.yaml index 619b3c626ac66..89a69c9adfdaf 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources.yaml @@ -1,6 +1,7 @@ get: - summary: Agent Download Sources - tags: [] + summary: List agent binary download sources + tags: + - Agent binary download sources responses: '200': description: OK @@ -23,9 +24,9 @@ get: $ref: ../components/responses/error.yaml operationId: get-download-sources post: - summary: Agent Download Sources - description: 'Create a new agent download source' - tags: [] + summary: Create agent binary download source + tags: + - Agent binary download sources responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources@{source_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources@{source_id}.yaml index 364d292082c8b..afb7771283e59 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources@{source_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_download_sources@{source_id}.yaml @@ -1,6 +1,7 @@ get: - summary: Agent Download Sources - Info - tags: [] + summary: Get agent binary download source by ID + tags: + - Agent binary download sources responses: '200': description: OK @@ -23,7 +24,9 @@ parameters: in: path required: true delete: - summary: Agent Download Sources - Delete + summary: Delete agent binary download source by ID + tags: + - Agent binary download sources operationId: delete-download-source responses: '200': @@ -42,7 +45,9 @@ delete: parameters: - $ref: ../components/headers/kbn_xsrf.yaml put: - summary: Agent Download Sources - Update + summary: Update agent binary download source by ID + tags: + - Agent binary download sources operationId: update-download-source requestBody: content: 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 33fd8a2348412..cbf29f3859519 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies.yaml @@ -1,6 +1,7 @@ get: - summary: Agent policies - List - tags: [] + summary: List agent policies + tags: + - Agent policies responses: '200': description: OK @@ -44,8 +45,9 @@ get: description: '' post: - summary: Agent policy - Create - tags: [] + summary: Create agent policy + tags: + - Agent policies responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@_bulk_get.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@_bulk_get.yaml index 75267e2a262a9..ace09ef721677 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@_bulk_get.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@_bulk_get.yaml @@ -1,6 +1,7 @@ post: - summary: Agent policies - Bulk Get - tags: [] + summary: Bulk get agent policies + tags: + - Agent policies requestBody: content: application/json: diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@delete.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@delete.yaml index 51967a697cf0e..966d8abc1e328 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@delete.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@delete.yaml @@ -1,5 +1,7 @@ post: - summary: Agent policy - Delete + summary: Delete agent policy by ID + tags: + - Agent policies operationId: delete-agent-policy responses: '200': diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml index 4a7e88abcbab8..55d644ab0aab2 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true get: - summary: Agent policy - Info - tags: [] + summary: Get agent policy by ID + tags: + - Agent policies responses: '200': description: OK @@ -25,8 +26,9 @@ get: description: Get one agent policy parameters: [] put: - summary: Agent policy - Update - tags: [] + summary: Update agent policy by ID + tags: + - Agent policies responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml index 21d4a1d493b01..dab79eef58dff 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@copy.yaml @@ -5,7 +5,9 @@ parameters: in: path required: true post: - summary: Agent policy - copy one policy + summary: Copy agent policy by ID + tags: + - Agent policies operationId: agent-policy-copy parameters: - $ref: ../components/headers/kbn_xsrf.yaml @@ -36,4 +38,3 @@ post: required: - name description: '' - diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@download.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@download.yaml index 5c7887d6f1bb2..1748950fdaf09 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@download.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@download.yaml @@ -1,6 +1,7 @@ - get: - summary: Agent policy - Download + summary: Download agent policy by ID + tags: + - Agent policies operationId: agent-policy-download responses: '200': diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@full.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@full.yaml index 1a79266e27732..dc5a1b996b2e4 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@full.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_policies@{agent_policy_id}@full.yaml @@ -1,6 +1,7 @@ - get: - summary: Agent policy - Get full policy + summary: Get full agent policy by ID + tags: + - Agent policies operationId: agent-policy-full responses: '200': diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_status.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_status.yaml index 46d8ac2f32ff9..6d4b1c77d991a 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_status.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_status.yaml @@ -1,6 +1,7 @@ get: - summary: Agents - Summary stats - tags: [] + summary: Get agent status summary + tags: + - Agent status responses: '200': description: OK @@ -29,7 +30,7 @@ get: updating: type: integer all: - type: integer + type: integer active: type: integer required: 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 a16fa2f71f8a8..7e90097c3b4dd 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 @@ -1,6 +1,7 @@ get: - summary: Agents - Get incoming data - tags: [] + summary: Get incoming agent data + tags: + - Agent status responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_status_deprecated.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_status_deprecated.yaml index 874cd38632ed3..fe44311fa9801 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_status_deprecated.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_status_deprecated.yaml @@ -1,6 +1,7 @@ get: - summary: Agents - Summary stats - tags: [] + summary: Get agent status summary + tags: + - Agent status responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agent_tags.yaml b/x-pack/plugins/fleet/common/openapi/paths/agent_tags.yaml index f01584ef4665a..85a6f6c7ab30a 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agent_tags.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agent_tags.yaml @@ -1,6 +1,7 @@ get: - summary: Agent Tags - List - description: List all agent tags + summary: List agent tags + tags: + - Agents responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents.yaml index b9b62f23552e1..cd74ff0a56636 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents.yaml @@ -1,6 +1,7 @@ get: - summary: Agents - List - tags: [] + summary: List agents + tags: + - Agents responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@action_status.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@action_status.yaml index 50494a29f4096..1c2d013457d6f 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@action_status.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@action_status.yaml @@ -1,8 +1,10 @@ get: - summary: Agents - Action status + summary: Get agent action status + tags: + - Agent actions parameters: - - $ref: ../components/parameters/page_size.yaml - - $ref: ../components/parameters/page_index.yaml + - $ref: ../components/parameters/page_size.yaml + - $ref: ../components/parameters/page_index.yaml responses: '200': description: OK @@ -33,7 +35,7 @@ get: nbAgentsAck: type: number nbAgentsFailed: - type: number + type: number version: type: string startTime: @@ -49,7 +51,7 @@ get: newPolicyId: type: string creationTime: - type: string + type: string required: - actionId - complete @@ -63,4 +65,4 @@ get: - items '400': $ref: ../components/responses/error.yaml - operationId: agents-action-status \ No newline at end of file + operationId: agents-action-status diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_reassign.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_reassign.yaml index 625aee38eafc4..b93b2bd6b9a08 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_reassign.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_reassign.yaml @@ -1,16 +1,17 @@ post: - summary: Agents - Bulk reassign - tags: [] + summary: Bulk reassign agents + tags: + - Agents responses: '200': - description: OK - content: - application/json: - schema: - type: object - properties: - actionId: - type: string + description: OK + content: + application/json: + schema: + type: object + properties: + actionId: + type: string '400': $ref: ../components/responses/error.yaml operationId: bulk-reassign-agents @@ -38,4 +39,4 @@ post: - agents example: policy_id: policy_id - agents: "fleet-agents.policy_id : (\"policy1\" or \"policy2\")" + agents: 'fleet-agents.policy_id : ("policy1" or "policy2")' diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_request_diagnostics.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_request_diagnostics.yaml index e2952e7ae51e0..3f0733ed8f258 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_request_diagnostics.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_request_diagnostics.yaml @@ -1,6 +1,7 @@ post: - summary: Agent - Bulk Request Diagnostics - tags: [] + summary: Bulk request diagnostics from agents + tags: + - Agents responses: '200': description: OK @@ -35,4 +36,4 @@ post: required: - agents example: - agents: "fleet-agents.policy_id : (\"policy1\" or \"policy2\")" + agents: 'fleet-agents.policy_id : ("policy1" or "policy2")' diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_unenroll.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_unenroll.yaml index 7527558a4cc10..1ab9e4038b978 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_unenroll.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_unenroll.yaml @@ -1,16 +1,17 @@ post: - summary: Agents - Bulk unenroll - tags: [] + summary: Bulk unenroll agents + tags: + - Agents responses: '200': - description: OK - content: - application/json: - schema: - type: object - properties: - actionId: - type: string + description: OK + content: + application/json: + schema: + type: object + properties: + actionId: + type: string '400': $ref: ../components/responses/error.yaml operationId: bulk-unenroll-agents diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_update_tags.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_update_tags.yaml index 77c0c0d4cfa7c..ff4c6597b6be0 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_update_tags.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_update_tags.yaml @@ -1,16 +1,17 @@ post: - summary: Agents - Bulk update tags - tags: [] + summary: Bulk update agent tags + tags: + - Agents responses: '200': - description: OK - content: - application/json: - schema: - type: object - properties: - actionId: - type: string + description: OK + content: + application/json: + schema: + type: object + properties: + actionId: + type: string '400': $ref: ../components/responses/error.yaml operationId: bulk-update-agent-tags @@ -39,10 +40,10 @@ post: items: type: string batchSize: - type: number + type: number required: - agents example: agents: [agent1, agent2] tagsToAdd: [newTag] - tagsToRemove: [existingTag] + tagsToRemove: [existingTag] diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_upgrade.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_upgrade.yaml index b8863eaf271fd..ccb55c7c62b17 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_upgrade.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@bulk_upgrade.yaml @@ -1,16 +1,17 @@ post: - summary: Agents - Bulk Upgrade - tags: [] + summary: Bulk upgrade agents + tags: + - Agents responses: '200': description: OK content: application/json: schema: - type: object - properties: - actionId: - type: string + type: object + properties: + actionId: + type: string '400': $ref: ../components/responses/error.yaml operationId: bulk-upgrade-agents diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@current_upgrades.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@current_upgrades.yaml index 162c9e4cb5bc3..36ae723527f9b 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@current_upgrades.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@current_upgrades.yaml @@ -1,6 +1,7 @@ get: - summary: Agents - Current Bulk Upgrades - tags: [] + summary: List current bulk upgrade operations + tags: + - Agents responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@files@{file_id}@{file_name}.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@files@{file_id}@{file_name}.yaml index 82192ade7856b..15f6dd8a421d1 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@files@{file_id}@{file_name}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@files@{file_id}@{file_name}.yaml @@ -10,8 +10,9 @@ parameters: in: path required: true get: - summary: Get agent upload file - tags: [] + summary: Get file uploaded by agent + tags: + - Agents responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@setup.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@setup.yaml index 104ae1ba084da..214f3a8e68240 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@setup.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@setup.yaml @@ -1,6 +1,7 @@ get: - summary: Agents setup - Info - tags: [] + summary: Get agent setup info + tags: + - Agents responses: '200': description: OK @@ -14,7 +15,9 @@ get: security: - basicAuth: [] post: - summary: Agents setup - Create + summary: Initiate agent setup + tags: + - Agents operationId: setup-agents responses: '200': diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}.yaml index 7bf3a7d73f31b..93242e5912a17 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true get: - summary: Agent - Info - tags: [] + summary: Get agent by ID + tags: + - Agents responses: '200': description: OK @@ -25,8 +26,9 @@ get: parameters: - $ref: ../components/parameters/with_metrics.yaml put: - summary: Agent - Update - tags: [] + summary: Update agent by ID + tags: + - Agents responses: '200': description: OK @@ -58,8 +60,9 @@ put: items: type: string delete: - summary: Agent - Delete - tags: [] + summary: Delete agent by ID + tags: + - Agents responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions.yaml index 38cce1ea54db3..cd327e453b9a7 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@actions.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true post: - summary: Agent - Actions - tags: [] + summary: Create agent action + tags: + - Agent actions responses: '200': description: OK @@ -35,5 +36,5 @@ post: schema: type: object properties: - action: - $ref: ../components/schemas/agent_action.yaml + action: + $ref: ../components/schemas/agent_action.yaml 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 c9bf661d88a85..f91acd133355d 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 @@ -10,8 +10,9 @@ parameters: in: path required: true post: - summary: Agent - Cancel Action - tags: [] + summary: Cancel agent action + tags: + - Agent actions responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml index af00d1563854e..c210cee12d424 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@reassign.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true post: - summary: Agent - Reassign - tags: [] + summary: Reassign agent + tags: + - Agents responses: '200': description: OK @@ -31,8 +32,9 @@ post: required: - policy_id put: - summary: Agent - Reassign - tags: [] + summary: Reassign agent + tags: + - Agents responses: '200': description: OK @@ -57,4 +59,3 @@ put: required: - policy_id deprecated: true - diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@request_diagnostics.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@request_diagnostics.yaml index 13b335ffe2300..37aed12d5f4f1 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@request_diagnostics.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@request_diagnostics.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true post: - summary: Agent - Request Diagnostics - tags: [] + summary: Request agent diagnostics + tags: + - Agents responses: '200': description: OK @@ -22,4 +23,3 @@ post: operationId: request-diagnostics-agent parameters: - $ref: ../components/headers/kbn_xsrf.yaml - diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@unenroll.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@unenroll.yaml index b9664ae650112..c30bebfad328a 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@unenroll.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@unenroll.yaml @@ -5,30 +5,31 @@ parameters: in: path required: true post: - summary: Agent - Unenroll - tags: [] + summary: Unenroll agent + tags: + - Agents responses: '200': - description: OK - content: - application/json: - schema: - type: object + description: OK + content: + application/json: + schema: + type: object '400': - description: BAD REQUEST - content: - application/json: - schema: - type: object - properties: - error: - type: string - message: - type: string - statusCode: - type: number - enum: - - 400 + description: BAD REQUEST + content: + application/json: + schema: + type: object + properties: + error: + type: string + message: + type: string + statusCode: + type: number + enum: + - 400 operationId: unenroll-agent parameters: - $ref: ../components/headers/kbn_xsrf.yaml diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@upgrade.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@upgrade.yaml index c6d66f6f52386..d824d4a54f985 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@upgrade.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@upgrade.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true post: - summary: Agent - Upgrade - tags: [] + summary: Upgrade agent + tags: + - Agents responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@uploads.yaml b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@uploads.yaml index de812b0e363e3..f92acc7fe5086 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@uploads.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/agents@{agent_id}@uploads.yaml @@ -6,7 +6,8 @@ parameters: required: true get: summary: List agent uploads - tags: [] + tags: + - Agents responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/data_streams.yaml b/x-pack/plugins/fleet/common/openapi/paths/data_streams.yaml index c9e9f1be897aa..bb8c667ba933e 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/data_streams.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/data_streams.yaml @@ -1,6 +1,7 @@ get: - summary: Data streams - List - tags: [] + summary: List data streams + tags: + - Data streams responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml index 5bc257606087f..3351b63026e57 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys.yaml @@ -1,6 +1,7 @@ get: - summary: Enrollment API Keys - List - tags: [] + summary: List enrollment API keys + tags: + - Enrollment API keys responses: '200': description: OK @@ -34,8 +35,9 @@ get: operationId: get-enrollment-api-keys parameters: [] post: - summary: Enrollment API Key - Create - tags: [] + summary: Create enrollment API key + tags: + - Enrollment API keys responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml index bdff9a7152e45..d64b1053f0dc4 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true get: - summary: Enrollment API Key - Info - tags: [] + summary: Get enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK @@ -23,8 +24,9 @@ get: $ref: ../components/responses/error.yaml operationId: get-enrollment-api-key delete: - summary: Enrollment API Key - Delete - tags: [] + summary: Delete enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}_deprecated.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}_deprecated.yaml index 36c0f7f3ef01f..c0f5be7521e8a 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}_deprecated.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys@{key_id}_deprecated.yaml @@ -5,8 +5,9 @@ parameters: in: path required: true get: - summary: Enrollment API Key - Info - tags: [] + summary: Get enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK @@ -24,8 +25,9 @@ get: operationId: get-enrollment-api-key-deprecated deprecated: true delete: - summary: Enrollment API Key - Delete - tags: [] + summary: Delete enrollment API key by ID + tags: + - Enrollment API keys responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys_deprecated.yaml b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys_deprecated.yaml index c5e378c563afc..19022a0b08223 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys_deprecated.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/enrollment_api_keys_deprecated.yaml @@ -1,6 +1,7 @@ get: - summary: Enrollment API Keys - List - tags: [] + summary: List enrollment API keys + tags: + - Enrollment API keys responses: '200': description: OK @@ -35,8 +36,9 @@ get: parameters: [] deprecated: true post: - summary: Enrollment API Key - Create - tags: [] + summary: Create enrollment API key + tags: + - Enrollment API keys responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@categories.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@categories.yaml index a97c06f66c629..e733f780abe04 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@categories.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@categories.yaml @@ -1,6 +1,7 @@ get: - summary: Package categories - tags: [] + summary: List package categories + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -12,21 +13,21 @@ get: $ref: ../components/responses/error.yaml operationId: get-package-categories parameters: - - in: query + - in: query name: prerelease schema: type: boolean default: false description: >- - Whether to include prerelease packages in categories count (e.g. beta, rc, preview) - - in: query + Whether to include prerelease packages in categories count (e.g. beta, rc, preview) + - in: query name: experimental deprecated: true schema: type: boolean default: false - - in: query + - in: query name: include_policy_templates schema: type: boolean - default: false \ No newline at end of file + default: false diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@get_file.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@get_file.yaml index 9c194ea6a8e97..b85b72938feda 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@get_file.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@get_file.yaml @@ -1,6 +1,7 @@ get: - summary: Packages - Get file from registry - tags: [] + summary: Get package file + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@limited_list.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@limited_list.yaml index ec44a20b61307..a54c45782d3ae 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@limited_list.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@limited_list.yaml @@ -1,6 +1,7 @@ get: - summary: Packages - Get limited list - tags: [] + summary: Get limited package list + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK 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 43819dff6d10e..7434fd2d324a5 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@packages.yaml @@ -1,6 +1,7 @@ get: - summary: Packages - List - tags: [] + summary: List packages + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -22,26 +23,27 @@ get: 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 + - in: query name: prerelease schema: type: boolean default: false description: >- - Whether to return prerelease versions of packages (e.g. beta, rc, preview) - - in: query + 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 + - in: query name: category schema: type: string post: - summary: Packages - Install by upload - tags: [] + summary: Install by package by direct upload + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -90,4 +92,4 @@ post: application/gzip: schema: type: string - format: binary \ No newline at end of file + format: binary diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@stats.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@stats.yaml index b27b4ef6729dc..f90a275cd19b6 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@stats.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@stats.yaml @@ -1,6 +1,7 @@ get: - summary: Get stats for a package - tags: [] + summary: Get package stats + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml index 4cc2e55e9d29e..4fff7f0b21504 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkg_name}@{pkg_version}.yaml @@ -1,6 +1,7 @@ get: - summary: Packages - Info - tags: [] + summary: Get package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -59,16 +60,17 @@ parameters: name: full description: 'Return all fields from the package manifest, not just those supported by the Elastic Package Registry' in: query - - in: query + - in: query name: prerelease schema: type: boolean default: false description: >- - Whether to return prerelease versions of packages (e.g. beta, rc, preview) + Whether to return prerelease versions of packages (e.g. beta, rc, preview) post: - summary: Packages - Install - tags: [] + summary: Install package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -119,8 +121,9 @@ post: ignore_constraints: type: boolean put: - summary: Packages - Update - tags: [] + summary: Update package settings + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -158,8 +161,9 @@ put: keepPoliciesUpToDate: type: boolean delete: - summary: Packages - Delete - tags: [] + summary: Delete package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkgkey}_deprecated.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkgkey}_deprecated.yaml index 2967238a467a2..035809782bc07 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkgkey}_deprecated.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@packages@{pkgkey}_deprecated.yaml @@ -1,6 +1,7 @@ get: - summary: Packages - Info - tags: [] + summary: Get package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -36,17 +37,18 @@ get: name: pkgkey in: path required: true - - in: query + - in: query name: prerelease schema: type: boolean default: false description: >- - Whether to return prerelease versions of packages (e.g. beta, rc, preview) + Whether to return prerelease versions of packages (e.g. beta, rc, preview) deprecated: true post: - summary: Packages - Install - tags: [] + summary: Install package + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -92,8 +94,9 @@ post: type: boolean deprecated: true delete: - summary: Packages - Delete - tags: [] + summary: Delete ackage + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@packages_bulk.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@packages_bulk.yaml index 7ede68f6b545f..a3775e69a7131 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@packages_bulk.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@packages_bulk.yaml @@ -1,6 +1,7 @@ post: - summary: Packages - Bulk install - tags: [] + summary: Bulk install packages + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -12,13 +13,13 @@ post: $ref: ../components/responses/error.yaml operationId: bulk-install-packages parameters: - - in: query + - in: query name: prerelease schema: type: boolean default: false description: >- - Whether to return prerelease versions of packages (e.g. beta, rc, preview) + Whether to return prerelease versions of packages (e.g. beta, rc, preview) requestBody: content: application/json: @@ -32,7 +33,6 @@ post: description: list of package names to install force: type: boolean - description: force install to ignore package verification errors + description: force install to ignore package verification errors required: - packages - diff --git a/x-pack/plugins/fleet/common/openapi/paths/epm@verification_key_id.yaml b/x-pack/plugins/fleet/common/openapi/paths/epm@verification_key_id.yaml index c9216b85cd78f..24de03ab52cd8 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/epm@verification_key_id.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/epm@verification_key_id.yaml @@ -1,6 +1,7 @@ get: summary: Get package signature verification key ID - tags: [] + tags: + - Elastic Package Manager (EPM) responses: '200': description: OK @@ -12,7 +13,7 @@ get: body: type: object properties: - id: + id: type: string nullable: true description: the key ID of the GPG key used to verify package signatures @@ -23,19 +24,4 @@ get: '400': $ref: ../components/responses/error.yaml operationId: packages-get-verification-key-id -parameters: - - schema: - type: string - name: pkgName - in: path - required: true - - schema: - type: string - name: pkgVersion - in: path - required: true - - schema: - type: string - name: filePath - in: path - required: true +parameters: [] diff --git a/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts.yaml b/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts.yaml index da599dddca1e3..d7668f3683b7b 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts.yaml @@ -1,7 +1,7 @@ get: - summary: Fleet Server Hosts - List - description: Return a list of Fleet server hosts - tags: [] + summary: List Fleet Server hosts + tags: + - Fleet Server hosts responses: '200': description: OK @@ -24,9 +24,9 @@ get: $ref: ../components/responses/error.yaml operationId: get-fleet-server-hosts post: - summary: Fleet Server Hosts - Create - description: 'Create a new Fleet Server Host' - tags: [] + summary: Create Fleet Server host + tags: + - Fleet Server hosts responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts@{item_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts@{item_id}.yaml index 968f81d8c6181..d46a8b86fb7f6 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts@{item_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/fleet_server_hosts@{item_id}.yaml @@ -1,6 +1,7 @@ get: - summary: Fleet Server Hosts - Info - tags: [] + summary: Get Fleet Server host by ID + tags: + - Fleet Server hosts responses: '200': description: OK @@ -23,7 +24,9 @@ parameters: in: path required: true delete: - summary: Fleet Server Hosts - Delete + summary: Delete Fleet Server host by ID + tags: + - Fleet Server hosts operationId: delete-fleet-server-hosts responses: '200': @@ -42,7 +45,9 @@ delete: parameters: - $ref: ../components/headers/kbn_xsrf.yaml put: - summary: Fleet Server Hosts - Update + summary: Update Fleet Server host by ID + tags: + - Fleet Server hosts operationId: update-fleet-server-hosts requestBody: content: diff --git a/x-pack/plugins/fleet/common/openapi/paths/health_check.yaml b/x-pack/plugins/fleet/common/openapi/paths/health_check.yaml index 84283ca80dbf0..ae87da3ff0e52 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/health_check.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/health_check.yaml @@ -1,6 +1,7 @@ post: - summary: Fleet Server Health Check - tags: [] + summary: Fleet Server health check + tags: + - Fleet internals responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/kubernetes.yaml b/x-pack/plugins/fleet/common/openapi/paths/kubernetes.yaml index d7852db70fccd..41110808cd62d 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/kubernetes.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/kubernetes.yaml @@ -1,6 +1,7 @@ get: - summary: Get K8s Full Agent Manifest - tags: [] + summary: Get full K8s agent manifest + tags: + - Kubernetes responses: '200': description: OK @@ -15,18 +16,18 @@ get: $ref: ../components/responses/error.yaml operationId: get-full-k8s-manifest parameters: - - schema: - type: boolean - name: download - in: query - required: false - - schema: - type: string - name: fleetServer - in: query - required: false - - schema: - type: string - name: enrolToken - in: query - required: false + - schema: + type: boolean + name: download + in: query + required: false + - schema: + type: string + name: fleetServer + in: query + required: false + - schema: + type: string + name: enrolToken + in: query + required: false diff --git a/x-pack/plugins/fleet/common/openapi/paths/logstash_api_keys.yaml b/x-pack/plugins/fleet/common/openapi/paths/logstash_api_keys.yaml index 495d792191798..74e3bdde4cac8 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/logstash_api_keys.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/logstash_api_keys.yaml @@ -1,6 +1,7 @@ post: summary: Generate Logstash API key - tags: [] + tags: + - Outputs responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml b/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml index 335d8ec570ca1..5ba06a5c36372 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/outputs.yaml @@ -1,6 +1,7 @@ get: - summary: Outputs - tags: [] + summary: List outputs + tags: + - Outputs responses: '200': description: OK @@ -23,9 +24,9 @@ get: $ref: ../components/responses/error.yaml operationId: get-outputs post: - summary: Outputs - description: 'Create a new output' - tags: [] + summary: Create output + tags: + - Outputs responses: '200': description: OK @@ -50,7 +51,7 @@ post: type: string type: type: string - enum: ["elasticsearch"] + enum: ['elasticsearch'] is_default: type: boolean is_default_monitoring: diff --git a/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml index ca01024288b95..8bd6ae2fc288c 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/outputs@{output_id}.yaml @@ -1,6 +1,7 @@ get: - summary: Output - Info - tags: [] + summary: Get output by ID + tags: + - Outputs responses: '200': description: OK @@ -23,7 +24,9 @@ parameters: in: path required: true delete: - summary: Output - Delete + summary: Delete output by ID + tags: + - Outputs operationId: delete-output responses: '200': @@ -33,7 +36,7 @@ delete: schema: type: object properties: - id: + id: type: string required: - id @@ -42,7 +45,9 @@ delete: parameters: - $ref: ../components/headers/kbn_xsrf.yaml put: - summary: Output - Update + summary: Update output by ID + tags: + - Outputs operationId: update-output requestBody: content: @@ -54,14 +59,14 @@ put: type: string type: type: string - enum: ["elasticsearch"] + enum: ['elasticsearch'] is_default: type: boolean is_default_monitoring: type: boolean hosts: type: array - items: + items: type: string ca_sha256: type: string diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml index 8959339426d05..0fe987e1727de 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies.yaml @@ -1,6 +1,7 @@ get: - summary: Package policies - List - tags: [] + summary: List package policies + tags: + - Package policies responses: '200': description: OK @@ -28,7 +29,9 @@ get: parameters: [] parameters: [] post: - summary: Package policy - Create + summary: Create package policy + tags: + - Package policies operationId: create-package-policy responses: '200': diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@_bulk_get.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@_bulk_get.yaml index 1ff515dc2de6a..eb22c7d997575 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies@_bulk_get.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@_bulk_get.yaml @@ -1,6 +1,7 @@ post: - summary: Package policies - Bulk Get - tags: [] + summary: Bulk get package policies + tags: + - Package policies requestBody: content: application/json: diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@delete.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@delete.yaml index 6061267b4b2b8..f21111c23757a 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies@delete.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@delete.yaml @@ -1,5 +1,7 @@ post: - summary: Package policy - Delete + summary: Delete package policy + tags: + - Package policies operationId: post-delete-package-policy requestBody: content: diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml index 09f2727ad678c..2b6e69d49c44e 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade.yaml @@ -1,5 +1,7 @@ post: - summary: Package policy - Upgrade + summary: Upgrade package policy to a newer package version + tags: + - Package policies operationId: upgrade-package-policy requestBody: content: diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml index 6f51bd6812d97..5019aba15898d 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@upgrade_dryrun.yaml @@ -1,5 +1,7 @@ post: - summary: Package policy - Upgrade Dry run + summary: Dry run package policy upgrade + tags: + - Package policies operationId: upgrade-package-policy-dry-run requestBody: content: diff --git a/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml index 9e05e9516d603..30d89d271a5ff 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/package_policies@{package_policy_id}.yaml @@ -1,6 +1,7 @@ get: - summary: Package policy - Info - tags: [] + summary: Get package policy by ID + tags: + - Package policies responses: '200': description: OK @@ -23,7 +24,9 @@ parameters: in: path required: true put: - summary: Package policy - Update + summary: Update package policy by ID + tags: + - Package policies operationId: update-package-policy requestBody: content: @@ -50,8 +53,9 @@ put: parameters: - $ref: ../components/headers/kbn_xsrf.yaml delete: - summary: Package policy - Delete - tags: [] + summary: Delete package policy by ID + tags: + - Package policies operationId: delete-package-policy responses: '200': diff --git a/x-pack/plugins/fleet/common/openapi/paths/proxies.yaml b/x-pack/plugins/fleet/common/openapi/paths/proxies.yaml index a5f59ec0e7cb5..6c2844a9ac3ef 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/proxies.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/proxies.yaml @@ -1,7 +1,7 @@ get: - summary: Fleet Proxies - List - description: Return a list of Proxies - tags: [] + summary: List proxies + tags: + - Proxies responses: '200': description: OK @@ -24,9 +24,9 @@ get: $ref: ../components/responses/error.yaml operationId: get-fleet-proxies post: - summary: Fleet Proxies - Create - description: 'Create a new Fleet Server Host' - tags: [] + summary: Create proxy + tags: + - Proxies responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/proxies@{item_id}.yaml b/x-pack/plugins/fleet/common/openapi/paths/proxies@{item_id}.yaml index 96a3665718753..3a0a10cb35662 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/proxies@{item_id}.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/proxies@{item_id}.yaml @@ -1,6 +1,7 @@ get: - summary: Fleet Proxies - Info - tags: [] + summary: Get proxy by ID + tags: + - Proxies responses: '200': description: OK @@ -23,7 +24,9 @@ parameters: in: path required: true delete: - summary: Fleet Proxies - Delete + summary: Delete proxy by ID + tags: + - Proxies operationId: delete-fleet-proxies responses: '200': @@ -42,7 +45,9 @@ delete: parameters: - $ref: ../components/headers/kbn_xsrf.yaml put: - summary: Fleet Proxies - Update + summary: Update proxy by ID + tags: + - Proxies operationId: update-fleet-proxies requestBody: content: diff --git a/x-pack/plugins/fleet/common/openapi/paths/service_tokens.yaml b/x-pack/plugins/fleet/common/openapi/paths/service_tokens.yaml index c57614c6c5def..e76f18c5b57d7 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/service_tokens.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/service_tokens.yaml @@ -1,6 +1,7 @@ post: - summary: Generate service tokens - tags: [] + summary: Create service token + tags: + - Service tokens responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/service_tokens_deprecated.yaml b/x-pack/plugins/fleet/common/openapi/paths/service_tokens_deprecated.yaml index f081f207b4d1e..73069830be9e1 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/service_tokens_deprecated.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/service_tokens_deprecated.yaml @@ -1,6 +1,7 @@ post: - summary: Generate service tokens - tags: [] + summary: Create service token + tags: + - Service tokens responses: '200': description: OK diff --git a/x-pack/plugins/fleet/common/openapi/paths/settings.yaml b/x-pack/plugins/fleet/common/openapi/paths/settings.yaml index dc711bcefbfae..4e3d1b3af4bb7 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/settings.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/settings.yaml @@ -1,6 +1,7 @@ get: - summary: Settings - tags: [] + summary: Get settings + tags: + - Fleet internals responses: '200': description: OK @@ -12,8 +13,9 @@ get: $ref: ../components/responses/error.yaml operationId: get-settings put: - summary: Settings - Update - tags: [] + summary: Update settings + tags: + - Fleet internals requestBody: content: application/json: diff --git a/x-pack/plugins/fleet/common/openapi/paths/setup.yaml b/x-pack/plugins/fleet/common/openapi/paths/setup.yaml index 048e5cc51faf9..1f1a3cd035665 100644 --- a/x-pack/plugins/fleet/common/openapi/paths/setup.yaml +++ b/x-pack/plugins/fleet/common/openapi/paths/setup.yaml @@ -1,6 +1,7 @@ post: - summary: Setup - tags: [] + summary: Initiate Fleet setup + tags: + - Fleet internals responses: '200': description: OK From a5b2db4604b45919a9b1e82e93b7b921c7d7ad56 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Mar 2023 14:46:35 +0100 Subject: [PATCH 081/131] [Telemetry] Prepare for versioned HTTP APIs (#152111) ## Summary In this PR we ensure that we are adhering to the goals of versioned HTTP APIs to: 1. Not send SO attributes directly over the wire 2. Have a separate set of interfaces that can be referenced by public and maintained by server --- src/plugins/telemetry/common/routes.ts | 6 -- .../common/{types.ts => types/index.ts} | 5 +- src/plugins/telemetry/common/types/latest.ts | 9 +++ src/plugins/telemetry/common/types/v2.ts | 71 +++++++++++++++++++ src/plugins/telemetry/public/plugin.ts | 5 +- .../public/services/telemetry_sender.ts | 2 +- .../public/services/telemetry_service.ts | 5 +- .../server/routes/telemetry_config.ts | 5 +- .../server/routes/telemetry_last_reported.ts | 9 ++- .../server/routes/telemetry_opt_in.ts | 5 +- .../server/routes/telemetry_opt_in_stats.ts | 4 +- .../server/routes/telemetry_usage_stats.ts | 7 +- .../routes/telemetry_user_has_seen_notice.ts | 13 +++- 13 files changed, 124 insertions(+), 22 deletions(-) rename src/plugins/telemetry/common/{types.ts => types/index.ts} (66%) create mode 100644 src/plugins/telemetry/common/types/latest.ts create mode 100644 src/plugins/telemetry/common/types/v2.ts diff --git a/src/plugins/telemetry/common/routes.ts b/src/plugins/telemetry/common/routes.ts index 2161cb7dd5651..06d6f746bf2c1 100644 --- a/src/plugins/telemetry/common/routes.ts +++ b/src/plugins/telemetry/common/routes.ts @@ -10,9 +10,3 @@ * Fetch Telemetry Config */ export const FetchTelemetryConfigRoute = '/api/telemetry/v2/config'; -export interface FetchTelemetryConfigResponse { - allowChangingOptInStatus: boolean; - optIn: boolean | null; - sendUsageFrom: 'server' | 'browser'; - telemetryNotifyUserAboutOptInDefault: boolean; -} diff --git a/src/plugins/telemetry/common/types.ts b/src/plugins/telemetry/common/types/index.ts similarity index 66% rename from src/plugins/telemetry/common/types.ts rename to src/plugins/telemetry/common/types/index.ts index aefbbd2358861..14b2d3cbefcf4 100644 --- a/src/plugins/telemetry/common/types.ts +++ b/src/plugins/telemetry/common/types/index.ts @@ -6,5 +6,6 @@ * Side Public License, v 1. */ -export type EncryptedTelemetryPayload = Array<{ clusterUuid: string; stats: string }>; -export type UnencryptedTelemetryPayload = Array<{ clusterUuid: string; stats: object }>; +export * from './latest'; + +export * as v2 from './v2'; diff --git a/src/plugins/telemetry/common/types/latest.ts b/src/plugins/telemetry/common/types/latest.ts new file mode 100644 index 0000000000000..557f34eac9ee2 --- /dev/null +++ b/src/plugins/telemetry/common/types/latest.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 * from './v2'; diff --git a/src/plugins/telemetry/common/types/v2.ts b/src/plugins/telemetry/common/types/v2.ts new file mode 100644 index 0000000000000..dc90ad3d242a6 --- /dev/null +++ b/src/plugins/telemetry/common/types/v2.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 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 Telemetry { + /** Whether telemetry is enabled */ + enabled?: boolean | null; + lastVersionChecked?: string; + /** Whether to send usage from the server or browser. */ + sendUsageFrom?: 'browser' | 'server'; + lastReported?: number; + allowChangingOptInStatus?: boolean; + userHasSeenNotice?: boolean; + reportFailureCount?: number; + reportFailureVersion?: string; +} + +export interface FetchTelemetryConfigResponse { + allowChangingOptInStatus: boolean; + optIn: boolean | null; + sendUsageFrom: 'server' | 'browser'; + telemetryNotifyUserAboutOptInDefault: boolean; +} + +export interface FetchLastReportedResponse { + lastReported: undefined | number; +} + +export type UpdateLastReportedResponse = undefined; + +export interface OptInStatsBody { + enabled: boolean; + /** @default true */ + unencrypted?: boolean; +} + +export interface StatsPayload { + cluster_uuid: string; + opt_in_status: boolean; +} + +export type OptInStatsResponse = Array<{ + clusterUuid: string; + stats: StatsPayload; +}>; + +export interface OptInBody { + enabled: boolean; +} + +export type OptInResponse = Array<{ + clusterUuid: string; + stats: string; +}>; + +export interface UsageStatsBody { + /** @default false */ + unencrypted: boolean; + /** @default false */ + refreshCache: boolean; +} + +export type UseHasSeenNoticeResponse = Telemetry; + +export type EncryptedTelemetryPayload = Array<{ clusterUuid: string; stats: string }>; + +export type UnencryptedTelemetryPayload = Array<{ clusterUuid: string; stats: object }>; diff --git a/src/plugins/telemetry/public/plugin.ts b/src/plugins/telemetry/public/plugin.ts index d28868a6dd286..15b581c498366 100644 --- a/src/plugins/telemetry/public/plugin.ts +++ b/src/plugins/telemetry/public/plugin.ts @@ -21,7 +21,8 @@ import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import { ElasticV3BrowserShipper } from '@kbn/analytics-shippers-elastic-v3-browser'; import { of } from 'rxjs'; -import { FetchTelemetryConfigResponse, FetchTelemetryConfigRoute } from '../common/routes'; +import { FetchTelemetryConfigRoute } from '../common/routes'; +import type { v2 } from '../common/types'; import { TelemetrySender, TelemetryService, TelemetryNotifications } from './services'; import { renderWelcomeTelemetryNotice } from './render_welcome_telemetry_notice'; @@ -322,7 +323,7 @@ export class TelemetryPlugin implements Plugin { const { allowChangingOptInStatus, optIn, sendUsageFrom, telemetryNotifyUserAboutOptInDefault } = - await http.get(FetchTelemetryConfigRoute); + await http.get(FetchTelemetryConfigRoute); return { ...this.config, diff --git a/src/plugins/telemetry/public/services/telemetry_sender.ts b/src/plugins/telemetry/public/services/telemetry_sender.ts index 6ffed583ec95c..3006a328fb620 100644 --- a/src/plugins/telemetry/public/services/telemetry_sender.ts +++ b/src/plugins/telemetry/public/services/telemetry_sender.ts @@ -12,7 +12,7 @@ import { exhaustMap } from 'rxjs/operators'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { LOCALSTORAGE_KEY, PAYLOAD_CONTENT_ENCODING } from '../../common/constants'; import { TelemetryService } from './telemetry_service'; -import type { EncryptedTelemetryPayload } from '../../common/types'; +import type { EncryptedTelemetryPayload } from '../../common/types/latest'; import { isReportIntervalExpired } from '../../common/is_report_interval_expired'; export class TelemetrySender { diff --git a/src/plugins/telemetry/public/services/telemetry_service.ts b/src/plugins/telemetry/public/services/telemetry_service.ts index 189df46b2328b..c1b96f4749067 100644 --- a/src/plugins/telemetry/public/services/telemetry_service.ts +++ b/src/plugins/telemetry/public/services/telemetry_service.ts @@ -10,7 +10,10 @@ import { i18n } from '@kbn/i18n'; import { CoreStart } from '@kbn/core/public'; import { TelemetryPluginConfig } from '../plugin'; import { getTelemetryChannelEndpoint } from '../../common/telemetry_config/get_telemetry_channel_endpoint'; -import type { UnencryptedTelemetryPayload, EncryptedTelemetryPayload } from '../../common/types'; +import type { + UnencryptedTelemetryPayload, + EncryptedTelemetryPayload, +} from '../../common/types/latest'; import { PAYLOAD_CONTENT_ENCODING } from '../../common/constants'; interface TelemetryServiceConstructor { diff --git a/src/plugins/telemetry/server/routes/telemetry_config.ts b/src/plugins/telemetry/server/routes/telemetry_config.ts index 4bcf1d1f4c811..60a34d80aad2e 100644 --- a/src/plugins/telemetry/server/routes/telemetry_config.ts +++ b/src/plugins/telemetry/server/routes/telemetry_config.ts @@ -9,7 +9,8 @@ import { type Observable, firstValueFrom } from 'rxjs'; import type { IRouter, SavedObjectsClient } from '@kbn/core/server'; import type { TelemetryConfigType } from '../config'; -import { FetchTelemetryConfigResponse, FetchTelemetryConfigRoute } from '../../common/routes'; +import { v2 } from '../../common/types'; +import { FetchTelemetryConfigRoute } from '../../common/routes'; import { getTelemetrySavedObject } from '../saved_objects'; import { getNotifyUserAboutOptInDefault, @@ -64,7 +65,7 @@ export function registerTelemetryConfigRoutes({ telemetryOptedIn: optIn, }); - const body: FetchTelemetryConfigResponse = { + const body: v2.FetchTelemetryConfigResponse = { allowChangingOptInStatus, optIn, sendUsageFrom, diff --git a/src/plugins/telemetry/server/routes/telemetry_last_reported.ts b/src/plugins/telemetry/server/routes/telemetry_last_reported.ts index 80037761895b2..2e21785b9296d 100644 --- a/src/plugins/telemetry/server/routes/telemetry_last_reported.ts +++ b/src/plugins/telemetry/server/routes/telemetry_last_reported.ts @@ -9,6 +9,7 @@ import type { IRouter, SavedObjectsClient } from '@kbn/core/server'; import type { Observable } from 'rxjs'; import { firstValueFrom } from 'rxjs'; +import { v2 } from '../../common/types'; import { getTelemetrySavedObject, updateTelemetrySavedObject } from '../saved_objects'; export function registerTelemetryLastReported( @@ -25,10 +26,12 @@ export function registerTelemetryLastReported( const savedObjectsInternalClient = await firstValueFrom(savedObjectsInternalClient$); const telemetrySavedObject = await getTelemetrySavedObject(savedObjectsInternalClient); + const body: v2.FetchLastReportedResponse = { + lastReported: telemetrySavedObject && telemetrySavedObject?.lastReported, + }; + return res.ok({ - body: { - lastReported: telemetrySavedObject && telemetrySavedObject?.lastReported, - }, + body, }); } ); diff --git a/src/plugins/telemetry/server/routes/telemetry_opt_in.ts b/src/plugins/telemetry/server/routes/telemetry_opt_in.ts index e26e8c596b53a..cc477c4f23198 100644 --- a/src/plugins/telemetry/server/routes/telemetry_opt_in.ts +++ b/src/plugins/telemetry/server/routes/telemetry_opt_in.ts @@ -14,6 +14,7 @@ import type { StatsGetterConfig, TelemetryCollectionManagerPluginSetup, } from '@kbn/telemetry-collection-manager-plugin/server'; +import { v2 } from '../../common/types'; import { sendTelemetryOptInStatus } from './telemetry_opt_in_stats'; import { getTelemetrySavedObject, @@ -109,7 +110,9 @@ export function registerTelemetryOptInRoutes({ return res.forbidden(); } } - return res.ok({ body: optInStatus }); + + const body: v2.OptInResponse = optInStatus; + return res.ok({ body }); } ); } diff --git a/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts b/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts index d8ec9d4922fc1..8c9c85172ced6 100644 --- a/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts +++ b/src/plugins/telemetry/server/routes/telemetry_opt_in_stats.ts @@ -14,6 +14,7 @@ import type { TelemetryCollectionManagerPluginSetup, StatsGetterConfig, } from '@kbn/telemetry-collection-manager-plugin/server'; +import type { v2 } from '../../common/types'; import { EncryptedTelemetryPayload, UnencryptedTelemetryPayload } from '../../common/types'; import { getTelemetryChannelEndpoint } from '../../common/telemetry_config'; import { PAYLOAD_CONTENT_ENCODING } from '../../common/constants'; @@ -90,7 +91,8 @@ export function registerTelemetryOptInStatsRoutes( newOptInStatus, statsGetterConfig ); - return res.ok({ body: optInStatus }); + const body: v2.OptInStatsResponse = optInStatus; + return res.ok({ body }); } catch (err) { return res.ok({ body: [] }); } diff --git a/src/plugins/telemetry/server/routes/telemetry_usage_stats.ts b/src/plugins/telemetry/server/routes/telemetry_usage_stats.ts index fd613e1318966..53169367b965e 100644 --- a/src/plugins/telemetry/server/routes/telemetry_usage_stats.ts +++ b/src/plugins/telemetry/server/routes/telemetry_usage_stats.ts @@ -13,6 +13,7 @@ import type { StatsGetterConfig, } from '@kbn/telemetry-collection-manager-plugin/server'; import type { SecurityPluginStart } from '@kbn/security-plugin/server'; +import { v2 } from '../../common/types'; export type SecurityGetter = () => SecurityPluginStart | undefined; @@ -64,8 +65,10 @@ export function registerTelemetryUsageStatsRoutes( refreshCache: unencrypted || refreshCache, }; - const stats = await telemetryCollectionManager.getStats(statsConfig); - return res.ok({ body: stats }); + const body: v2.UnencryptedTelemetryPayload = await telemetryCollectionManager.getStats( + statsConfig + ); + return res.ok({ body }); } catch (err) { if (isDev) { // don't ignore errors when running in dev mode diff --git a/src/plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts b/src/plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts index 7686aa4100755..eeac24c0f5a07 100644 --- a/src/plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts +++ b/src/plugins/telemetry/server/routes/telemetry_user_has_seen_notice.ts @@ -8,6 +8,7 @@ import type { IRouter } from '@kbn/core/server'; import { TELEMETRY_SAVED_OBJECT_TYPE } from '../saved_objects'; +import { v2 } from '../../common/types'; import { type TelemetrySavedObjectAttributes, getTelemetrySavedObject, @@ -33,7 +34,17 @@ export function registerTelemetryUserHasSeenNotice(router: IRouter) { }; await updateTelemetrySavedObject(soClient, updatedAttributes); - return res.ok({ body: updatedAttributes }); + const body: v2.Telemetry = { + allowChangingOptInStatus: updatedAttributes.allowChangingOptInStatus, + enabled: updatedAttributes.enabled, + lastReported: updatedAttributes.lastReported, + lastVersionChecked: updatedAttributes.lastVersionChecked, + reportFailureCount: updatedAttributes.reportFailureCount, + reportFailureVersion: updatedAttributes.reportFailureVersion, + sendUsageFrom: updatedAttributes.sendUsageFrom, + userHasSeenNotice: updatedAttributes.userHasSeenNotice, + }; + return res.ok({ body }); } ); } From f6a0b886b143dea6b3b6f8101e21be5c1816558a Mon Sep 17 00:00:00 2001 From: Carlos Crespo Date: Wed, 1 Mar 2023 15:31:35 +0100 Subject: [PATCH 082/131] [Infrastructure UI] Filter out null bucket items from average calculation (#152333) ## Summary Closes [#152328](https://github.com/elastic/kibana/issues/152328) This PR fixes the average calculation in the Snapshot API, filtering out buckets with null values from it, which are more likely to appear with queries that use small data ranges. The results after this change are equal to what Elasticsearch would calculate in the avg aggregation ### How to test - Make sure you have metrics data (either through enabling the system module in metricbeat or connecting your local kibana to an oblt-cli cluster) - Navigate to `Infrastructure` > `Hosts` - Filter the results to see a single host - Change the data range filter and compare the KPIs against the table. - Validate other pages that use the Snapshot API (Inventory UI and Metrics UI to see if the results there are still correct --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/infra/common/http_api/snapshot_api.ts | 1 + .../pages/metrics/hosts/components/kpi_charts/tile.tsx | 1 + .../public/pages/metrics/inventory_view/hooks/use_snaphot.ts | 2 ++ .../routes/snapshot/lib/transform_metrics_ui_response.ts | 5 +++-- .../snapshot/lib/transform_request_to_metrics_api_request.ts | 2 +- x-pack/test/api_integration/apis/metrics_ui/snapshot.ts | 2 +- 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/common/http_api/snapshot_api.ts b/x-pack/plugins/infra/common/http_api/snapshot_api.ts index 3f8e4b5597f31..6b3a683ef7d26 100644 --- a/x-pack/plugins/infra/common/http_api/snapshot_api.ts +++ b/x-pack/plugins/infra/common/http_api/snapshot_api.ts @@ -115,6 +115,7 @@ export const SnapshotRequestRT = rt.intersection([ region: rt.string, filterQuery: rt.union([rt.string, rt.null]), overrideCompositeSize: rt.number, + dropPartialBuckets: rt.boolean, }), ]); diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpi_charts/tile.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpi_charts/tile.tsx index ed5d0f5831ca6..1b86c5a543d06 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpi_charts/tile.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/kpi_charts/tile.tsx @@ -22,6 +22,7 @@ export const Tile = ({ type, ...props }: Props) => { metrics: [{ type }], groupBy: null, includeTimeseries: true, + dropPartialBuckets: false, }); return ; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts index 8818fac0e39ee..ae39a5f03ea7e 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_snaphot.ts @@ -34,6 +34,7 @@ export function useSnapshot({ groupBy = null, sendRequestImmediately = true, includeTimeseries = true, + dropPartialBuckets = true, requestTs, ...args }: UseSnapshotRequest) { @@ -56,6 +57,7 @@ export function useSnapshot({ lookbackSize: 5, }, includeTimeseries, + dropPartialBuckets, }; const { error, loading, response, makeRequest } = useHTTPRequest( diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts index 4b3682db3d1f6..f11a67ecb4a0c 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts @@ -23,7 +23,7 @@ import { applyMetadataToLastPath } from './apply_metadata_to_last_path'; const getMetricValue = (row: MetricsAPIRow) => { if (!isNumber(row.metric_0)) return null; const value = row.metric_0; - return isFinite(value) ? value : null; + return Number.isFinite(value) ? value : null; }; const calculateMax = (rows: MetricsAPIRow[]) => { @@ -31,7 +31,8 @@ const calculateMax = (rows: MetricsAPIRow[]) => { }; const calculateAvg = (rows: MetricsAPIRow[]): number => { - return sum(rows.map(getMetricValue)) / rows.length || 0; + const values = rows.map(getMetricValue).filter(Number.isFinite); + return sum(values) / Math.max(values.length, 1); }; const getLastValue = (rows: MetricsAPIRow[]) => { diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts index ae342cfad7b28..890295561e3a7 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts @@ -45,7 +45,7 @@ export const transformRequestToMetricsAPIRequest = async ({ ? snapshotRequest.overrideCompositeSize : compositeSize, alignDataToEnd: true, - dropPartialBuckets: true, + dropPartialBuckets: snapshotRequest.dropPartialBuckets ?? true, includeTimeseries: snapshotRequest.includeTimeseries, }; diff --git a/x-pack/test/api_integration/apis/metrics_ui/snapshot.ts b/x-pack/test/api_integration/apis/metrics_ui/snapshot.ts index 9fa041108964e..8eef4dc32df1c 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/snapshot.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/snapshot.ts @@ -248,7 +248,7 @@ export default function ({ getService }: FtrProviderContext) { name: 'cpu', value: null, max: 0.47105555555555556, - avg: 0.0672936507936508, + avg: 0.47105555555555556, }; expect(snapshot).to.have.property('nodes'); From f23346e4a61fcbce8d0678edb76a7d3055852dde Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Wed, 1 Mar 2023 09:38:42 -0500 Subject: [PATCH 083/131] [Synthetics] Hide location and enabled toggle on `MonitorDetailsPanel` for test run details (#152373) Co-authored-by: Shahzad --- .../components/monitor_details_panel.tsx | 40 +++++++++++++------ .../error_details/error_details_page.tsx | 4 +- ...sx => monitor_details_panel_container.tsx} | 8 +++- .../monitor_summary/monitor_summary.tsx | 2 +- .../overview/monitor_detail_flyout.tsx | 1 + .../test_run_details/test_run_details.tsx | 4 +- 6 files changed, 40 insertions(+), 19 deletions(-) rename x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/{monitor_details_panel.tsx => monitor_details_panel_container.tsx} (85%) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx index 2bfd04fa26d57..9aa9d90e29ee9 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx @@ -40,19 +40,25 @@ const DescriptionLabel = euiStyled(EuiDescriptionListDescription)` width: 60%; `; +export interface MonitorDetailsPanelProps { + latestPing?: Ping; + loading: boolean; + configId: string; + monitor: EncryptedSyntheticsSavedMonitor | null; + hideEnabled?: boolean; + hideLocations?: boolean; + hasBorder?: boolean; +} + export const MonitorDetailsPanel = ({ monitor, latestPing, loading, configId, hideEnabled = false, -}: { - latestPing?: Ping; - loading: boolean; - configId: string; - monitor: EncryptedSyntheticsSavedMonitor | null; - hideEnabled?: boolean; -}) => { + hideLocations = false, + hasBorder = true, +}: MonitorDetailsPanelProps) => { const dispatch = useDispatch(); if (!monitor) { @@ -60,7 +66,12 @@ export const MonitorDetailsPanel = ({ } return ( - + @@ -116,10 +127,15 @@ export const MonitorDetailsPanel = ({ {FREQUENCY_LABEL} {frequencyStr(monitor[ConfigKey.SCHEDULE])} - {LOCATIONS_LABEL} - - - + + {!hideLocations && ( + <> + {LOCATIONS_LABEL} + + + + + )} {TAGS_LABEL} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx index 3174d85776733..084dd68934626 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx @@ -21,7 +21,7 @@ import { FailedTestsList } from './components/failed_tests_list'; import { ErrorTimeline } from './components/error_timeline'; import { useErrorDetailsBreadcrumbs } from './hooks/use_error_details_breadcrumbs'; import { StepImage } from '../step_details_page/step_screenshot/step_image'; -import { MonitorDetailsPanelContainer } from '../monitor_details/monitor_summary/monitor_details_panel'; +import { MonitorDetailsPanelContainer } from '../monitor_details/monitor_summary/monitor_details_panel_container'; export function ErrorDetailsPage() { const { failedTests, loading } = useErrorFailedTests(); @@ -80,7 +80,7 @@ export function ErrorDetailsPage() { - + diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_details_panel.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_details_panel_container.tsx similarity index 85% rename from x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_details_panel.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_details_panel_container.tsx index c2a26f5242f0f..99885ac30fb87 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_details_panel.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_details_panel_container.tsx @@ -9,12 +9,15 @@ import React from 'react'; import { EuiLoadingContent } from '@elastic/eui'; import { useParams } from 'react-router-dom'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { MonitorDetailsPanel } from '../../common/components/monitor_details_panel'; +import { + MonitorDetailsPanelProps, + MonitorDetailsPanel, +} from '../../common/components/monitor_details_panel'; import { useSelectedMonitor } from '../hooks/use_selected_monitor'; import { ConfigKey } from '../../../../../../common/runtime_types'; import { useMonitorLatestPing } from '../hooks/use_monitor_latest_ping'; -export const MonitorDetailsPanelContainer = () => { +export const MonitorDetailsPanelContainer = (props: Partial) => { const { latestPing } = useMonitorLatestPing(); const { monitorId: configId } = useParams<{ monitorId: string }>(); @@ -34,6 +37,7 @@ export const MonitorDetailsPanelContainer = () => { monitor={monitor} loading={loading} configId={configId} + {...props} /> ); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx index b087da10f767c..ebaaee6e44e50 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_summary/monitor_summary.tsx @@ -21,7 +21,7 @@ import { MonitorDurationTrend } from './duration_trend'; import { StepDurationPanel } from './step_duration_panel'; import { AvailabilityPanel } from './availability_panel'; import { DurationPanel } from './duration_panel'; -import { MonitorDetailsPanelContainer } from './monitor_details_panel'; +import { MonitorDetailsPanelContainer } from './monitor_details_panel_container'; import { AvailabilitySparklines } from './availability_sparklines'; import { LastTestRun } from './last_test_run'; import { LAST_10_TEST_RUNS, TestRunsTable } from './test_runs_table'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx index b34f4f6fe421a..187f590c9b360 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/monitor_detail_flyout.tsx @@ -325,6 +325,7 @@ export function MonitorDetailFlyout(props: Props) { { - + )} From 0c2e2c9b6f96cd936e53f72d13f4934c5bcffa3b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 1 Mar 2023 08:00:59 -0700 Subject: [PATCH 084/131] [maps] fix layers are not displayed in offline environment and map.includeElasticMapsService not set to false (#152396) Fixes https://github.com/elastic/kibana/issues/152389 PR adds check to ensure client has access to EMS before using EMS fonts. If the client does not have access to EMS fonts then a warning is logged and map falls back to open sans fonts served from Kibana server. --- .../connected_components/mb_map/mb_map.tsx | 3 +- x-pack/plugins/maps/public/util.test.js | 66 +++++++++++++------ x-pack/plugins/maps/public/util.ts | 42 +++++++++++- 3 files changed, 89 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 639c8fe5a20db..ab98b69a79f0b 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -155,12 +155,13 @@ export class MbMap extends Component { async _createMbMapInstance(initialView: MapCenterAndZoom | null): Promise { this._reportUsage(); + const glyphsUrlTemplate = await getGlyphUrl(); return new Promise((resolve) => { const mbStyle = { version: 8 as 8, sources: {}, layers: [], - glyphs: getGlyphUrl(), + glyphs: glyphsUrlTemplate, }; const options: MapOptions = { diff --git a/x-pack/plugins/maps/public/util.test.js b/x-pack/plugins/maps/public/util.test.js index 7fc88578b378a..48498f87fe7c0 100644 --- a/x-pack/plugins/maps/public/util.test.js +++ b/x-pack/plugins/maps/public/util.test.js @@ -5,60 +5,88 @@ * 2.0. */ -import { getGlyphUrl, makePublicExecutionContext } from './util'; - -const MOCK_EMS_SETTINGS = { - isEMSEnabled: () => true, -}; +import { + getGlyphUrl, + makePublicExecutionContext, + testOnlyClearCanAccessEmsFontsPromise, +} from './util'; describe('getGlyphUrl', () => { describe('EMS enabled', () => { - beforeAll(() => { + beforeEach(() => { require('./kibana_services').getHttp = () => ({ basePath: { - prepend: (url) => url, // No need to actually prepend a dev basepath for test + prepend: (path) => `abc${path}`, }, }); + testOnlyClearCanAccessEmsFontsPromise(); }); - describe('EMS proxy disabled', () => { + describe('offline', () => { beforeAll(() => { require('./kibana_services').getEMSSettings = () => { return { getEMSFontLibraryUrl() { - return 'foobar'; + return 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf'; }, isEMSEnabled() { return true; }, }; }; + require('node-fetch').default = () => { + throw new Error('Simulated offline environment with no EMS access'); + }; }); - test('should return EMS fonts URL', async () => { - expect(getGlyphUrl()).toBe('foobar'); + test('should return kibana fonts template URL', async () => { + expect(await getGlyphUrl()).toBe('abc/api/maps/fonts/{fontstack}/{range}'); + }); + }); + + describe('online', () => { + beforeAll(() => { + require('./kibana_services').getEMSSettings = () => { + return { + getEMSFontLibraryUrl() { + return 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf'; + }, + isEMSEnabled() { + return true; + }, + }; + }; + require('node-fetch').default = () => { + return Promise.resolve({ status: 200 }); + }; + }); + + test('should return EMS fonts template URL', async () => { + expect(await getGlyphUrl()).toBe( + 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf' + ); }); }); }); describe('EMS disabled', () => { beforeAll(() => { - const mockHttp = { - basePath: { - prepend: (path) => `abc${path}`, - }, + require('./kibana_services').getHttp = () => { + return { + basePath: { + prepend: (path) => `abc${path}`, + }, + }; }; - require('./kibana_services').getHttp = () => mockHttp; require('./kibana_services').getEMSSettings = () => { return { - ...MOCK_EMS_SETTINGS, isEMSEnabled: () => false, }; }; }); - test('should return kibana fonts URL', async () => { - expect(getGlyphUrl()).toBe('abc/api/maps/fonts/{fontstack}/{range}'); + test('should return kibana fonts template URL', async () => { + expect(await getGlyphUrl()).toBe('abc/api/maps/fonts/{fontstack}/{range}'); }); }); }); diff --git a/x-pack/plugins/maps/public/util.ts b/x-pack/plugins/maps/public/util.ts index d63072b163599..3243c8a95cf74 100644 --- a/x-pack/plugins/maps/public/util.ts +++ b/x-pack/plugins/maps/public/util.ts @@ -5,6 +5,7 @@ * 2.0. */ +import fetch from 'node-fetch'; import { EMSClient, FileLayer, TMSService } from '@elastic/ems-client'; import type { KibanaExecutionContext } from '@kbn/core/public'; import { FONTS_API_PATH } from '../common/constants'; @@ -60,9 +61,46 @@ async function getEMSClient(): Promise { return emsClient; } -export function getGlyphUrl(): string { +let canAccessEmsFontsPromise: Promise | null = null; +async function canAccessEmsFonts(): Promise { + if (!canAccessEmsFontsPromise) { + canAccessEmsFontsPromise = new Promise(async (resolve) => { + try { + const emsSettings = getEMSSettings(); + if (!emsSettings!.isEMSEnabled()) { + resolve(false); + } + const emsFontUrlTemplate = emsSettings!.getEMSFontLibraryUrl(); + + const emsFontUrl = emsFontUrlTemplate + .replace('{fontstack}', 'Open Sans') + .replace('{range}', '0-255'); + const resp = await fetch(emsFontUrl, { + method: 'HEAD', + }); + if (resp.status >= 400) { + throw new Error(`status: ${resp.status}`); + } + resolve(true); + } catch (error) { + // eslint-disable-next-line no-console + console.warn( + `Unable to access fonts from Elastic Maps Service (EMS). Set kibana.yml 'map.includeElasticMapsService: false' to avoid unnecessary EMS requests.` + ); + resolve(false); + } + }); + } + return canAccessEmsFontsPromise; +} +// test only function to reset singleton for different test cases. +export function testOnlyClearCanAccessEmsFontsPromise() { + canAccessEmsFontsPromise = null; +} + +export async function getGlyphUrl(): Promise { const emsSettings = getEMSSettings(); - if (!emsSettings!.isEMSEnabled()) { + if (!emsSettings!.isEMSEnabled() || !(await canAccessEmsFonts())) { return getHttp().basePath.prepend(`/${FONTS_API_PATH}/{fontstack}/{range}`); } From 5612da95fe5052af1a51ee7ba537ae355124c1ad Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau Date: Wed, 1 Mar 2023 10:29:17 -0500 Subject: [PATCH 085/131] [RAM] Fix flaky test on rule find api integration (#152455) ## Summary Fix https://github.com/elastic/kibana/issues/148660 ### 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 --- .../security_and_spaces/group1/tests/alerting/find.ts | 4 ++-- .../group1/tests/alerting/find_with_post.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 a75751d6df66f..be950eedb8c18 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 @@ -95,7 +95,7 @@ const findTestUtils = ( name: 'abc', tags: ['foo'], rule_type_id: 'test.noop', - running: false, + running: match.running ?? false, consumer: 'alertsFixture', schedule: { interval: '1m' }, enabled: true, @@ -311,7 +311,7 @@ const findTestUtils = ( name: 'abc', tags: ['foo'], rule_type_id: 'test.noop', - running: false, + running: match.running ?? false, consumer: 'alertsFixture', schedule: { interval: '1m' }, enabled: false, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts index 4bb1c43a29b52..0708d098d81fe 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts @@ -74,7 +74,7 @@ const findTestUtils = ( name: 'abc', tags: ['foo'], rule_type_id: 'test.noop', - running: false, + running: match.running ?? false, consumer: 'alertsFixture', schedule: { interval: '1m' }, enabled: true, @@ -287,7 +287,7 @@ const findTestUtils = ( name: 'abc', tags: ['foo'], rule_type_id: 'test.noop', - running: false, + running: match.running ?? false, consumer: 'alertsFixture', schedule: { interval: '1m' }, enabled: false, From 570eb381c5d20ebd4d1f8b1391683fc5ae492409 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Mar 2023 16:45:43 +0100 Subject: [PATCH 086/131] [Versioned APIs] Versioned interfaces dev docs guide (#150705) ## Summary Adds a dev docs guide for the core-approved versioning strategy. This strategy is subject to some iteration but is based on the work we did for the Saved Objects Management plugin in https://github.com/elastic/kibana/pull/149495. Closes https://github.com/elastic/kibana/issues/149929 ## How to test 1. Run `./scripts/dev_docs.sh` 2. Navigate to "Versioning interfaces" in the side nav menu --------- Co-authored-by: Luke Elmers --- dev_docs/tutorials/versioning_interfaces.mdx | 442 +++++++++++++++++++ nav-kibana-dev.docnav.json | 4 + 2 files changed, 446 insertions(+) create mode 100644 dev_docs/tutorials/versioning_interfaces.mdx diff --git a/dev_docs/tutorials/versioning_interfaces.mdx b/dev_docs/tutorials/versioning_interfaces.mdx new file mode 100644 index 0000000000000..d8ffdb333294a --- /dev/null +++ b/dev_docs/tutorials/versioning_interfaces.mdx @@ -0,0 +1,442 @@ +--- +id: kibDevTutorialVersioningInterfaces +slug: /kibana-dev-docs/versioning-interfaces +title: Versioning interfaces +description: We need to keep old versions of interfaces available. This tutorial describes a strategy for managing versions of your interfaces over time. +date: 2023-02-09 +tags: ['kibana', 'onboarding', 'dev', 'architecture'] +--- + +To support versioned APIs we need to keep past versions of interfaces around. This tutorial presents one strategy to manage your interfaces. + +## The strategy + +Every plugin has a _domain_. A domain consists of one or more concepts, usually objects, that are related in some logical way. + +At a high level the strategy for versioning our interfaces is: + +> Version a collection of related interfaces together. Whenever a single interface changes, increment the version of the entire collection of interfaces. + +Characteristics of this strategy: + +1. Avoid the `extends` keyword for referencing past interfaces. This results in cleaner API docs being generated. +2. Leverage `* as` to create versioned namespaces rather than versioned interfaces. +3. Verbosity is intentional: for a single change in a collection, we create a new version of the related collection. + +### An example: Weather insights unversioned +Consider a fictional Kibana plugin called "Weather insights". It allows users to easily create and curate dashboards that house visualisations and metrics for weather data. The domain contains the following: + +1. **Data source**: an endpoint that is scraped and ingested into ES for aggregation and search. +2. **Weather dashboard**: a set of visualisations and metrics that draws from a data source. + +We have the following `common` interfaces: + +```ts +export interface DataSource { + /** Some URL that provides weather data in an expected format for scraping */ + url: string; + /** The data view data is stored in */ + dataViewId: string; + /** Username to use with source URL */ + username?: string; + /** Password to use with source URL */ + password?: string; +} + +/** Fictional type, only used for this example as an external type */ +import type { PortableDashboard } from '@kbn/dashboard/common'; + +export interface WeatherDashboard { + /** A unique ID for this weather dashboard */ + id: string; + /** Definition of a dashboard imported from the `dashboard` plugin */ + dashboard: PortableDashboard; + /** Data source to use with this dashboard */ + source: DataSource; +} + +type UnsavedWeatherDashboard = Omit; + +/** Below are the HTTP APIs based on the domain types */ + +export interface GetWeatherDashboardHTTPResponse { + weatherDashboard: WeatherDashboard; +} + +export interface CreateWeatherDashboardHTTPBody { + weatherDashboard: UnsavedWeatherDashboard; +} + +export interface CreateWeatherDashboardHTTPResponse { + weatherDashboard: WeatherDashboard; +} + +// Imagine this pattern for the update and list endpoints too. +``` + +These interfaces might be in use by an unversioned HTTP route such as: + +```ts +import type { GetWeatherDashboardHTTPResponse } from '../common'; + +const handler = (ctx, req, res) => { + const body: GetWeatherDashboardHTTPResponse = { ... }; + return res.ok({ body }); +} +``` + +### An example: Weather insights versioned + +The following product requirements are added to the Weather insights plugin: + +1. Data sources need a more user-friendly `name`, currently we just show a URL +2. Some users have said they'd like to give data sources a short `description` too +3. New feature: **Predictions** that will generate forecasts based on past and current weather data + +Before we make these changes, we need to make sure that our current interfaces are not lost. + +#### Preparing our interfaces for versions + +We are going to make our current set of interfaces `v1`. Let's reflect this in our code by creating this file structure in `common`: + +``` +common + index.ts + latest.ts + data_source + v1.ts + weather_dashboard + v1.ts +public + ... +server + ... +``` + +By placing `DataSource` and `WeatherDashboard` in two folders we indicate that they _could_ version independently. Specifically, +`WeatherDashboard` may version independently of `DataSource`. + +**Note:** At this stage, splitting these concepts may be overkill if we expect `WeatherDashboard` to _rarely_ change, but for this example we would like the ability to version them separately. + +The `latest.ts` file is going to act as an alias to the latest set of interfaces. It will look like this: + +```ts +// "export *" is considered safe here because we ONLY have types in these files. +export * from './data_source/v1'; +export * from './weather_data/v1'; +``` + +Our `index.ts` file will contain: + +```ts +// Explicit export of everything from latest +export { DataSource, WeatherDashboard, GetWeatherDashboardHTTPResponse } from './latest'; + +export * as weatherDashboardV1 from './weather_dashboard/v1'; +export * as dataSourceV1 from './data_source/v1'; +``` + +How we use these types depends on whether the code is aware of versions or not. Generally, code that is aware of multiple versions will lead to greater complexity. We might have a logger function that expects the latest dashboards: + +```ts +// This type is being pulled from "latest", so whenever a new latest is linked, +// it will also point to the latest WeatherDashboard. +import type { WeatherDashboard } from '../common'; + +function logIt(dashboard: WeatherDashboard) { + logger.debug(dashboard); +} +``` + +Or we might have a route handler that expects a specific version our domain objects: + +```ts +// Now we bring it all together by using our versioned types in our handler from before: +import type { weatherDashboardV1 } from '../common'; + +const handler = (ctx, req, res) => { + const body: weatherDashboardV1.GetWeatherDashboardHTTPResponse = { ... }; + return res.ok({ body }); +} +``` + + + By referencing types linked from `latest.ts` we will not have to refactor all our app code to point to the latest version of `WeatherDashboard`. This happens by simply re-exporting the newest types from `latest.ts`. Otherwise, code that needs to know about a specific version or versions will have access to it by using the appropriate namespace. + + +### Introducing a new field to `DataSource` + +Now that we have prepared our interfaces to be versioned, let's introduce the `name` field to `DataSource`. + +Create a new `v2.ts` file under the `data_source` directory: + +``` +common + data_source + v1.ts + v2.ts +``` + +The `v2.ts` file will contain: + +```ts +export interface DataSource { + /** Some URL that provides weather data in an expected format for scraping */ + url: string; + /** A user-friendly name */ + name: string; + /** A longer description of this data source */ + description?: string; + /** The data view data is stored in */ + dataViewId: string; + /** Username to use with source URL */ + username?: string; + /** Password to use with source URL */ + password?: string; +} +``` + + + If we had only added the optional `description` field to `DataSource` this would be a backwards-compatible change that does not require a new version. We could have remained on `v1` of the `DataSource` interface. + + +We also need to update the `WeatherDashboard` interface to use our new `DataSource` interface: + +``` +common + weather_dashboard + v1.ts + v2.ts +``` + +```ts +// common/weather_dashboard/v2.ts + +// This is largely a copy of v1.ts, but using a new WeatherDashboard type in all +// the relevant places + +/** Fictional type, only used for this example as an external type */ +import type { PortableDashboard } from '@kbn/dashboard/common'; +import type { DataSource } from '../data_source/v2'; + +// Optionally, re-export the entire set of types. Interfaces and types declared after this will override v1 declarations. +export * from './v1'; + +export interface WeatherDashboard { + /** A unique ID for this weather dashboard */ + id: string; + /** Definition of a dashboard imported from the `dashboard` plugin */ + dashboard: PortableDashboard; + /** Data source to use with this dashboard */ + source: DataSource; +} + +type UnsavedWeatherDashboard = Omit; + +/** Below are the HTTP APIs based on the domain types */ + +export interface GetWeatherDashboardHTTPResponse { + weatherDashboard: WeatherDashboard; +} + +export interface CreateWeatherDashboardHTTPBody { + weatherDashboard: UnsavedWeatherDashboard; +} + +export interface CreateWeatherDashboardHTTPResponse { + weatherDashboard: WeatherDashboard; +} + +// Imagine this pattern for the update and list endpoints too. + +``` + + + It is possible to add `export * from './v1';` to the top of our `weather_dashboard/v2.ts` file to re-export unchanged types and avoid copying the whole file. + + However, copying and adapting the entire set of types is OK too. If we have correctly grouped our sub-domains we should be versioning all collections of types together. + + +Now we update the `latest.ts` and `index.ts` files accordingly: + +```ts +// latest.ts +export * from './data_source/v2'; +export * from './weather_dashboard/v2'; +``` + +```ts +// index.ts +// Explicit export of everything from latest +export { DataSource, WeatherDashboard, GetWeatherDashboardHTTPResponse } from './latest'; + +export * as weatherDashboardV1 from './weather_dashboard/v1'; +export * as dataSourceV1 from './data_source/v1'; + +export * as weatherDashboardV2 from './weather_dashboard/v2'; +export * as dataSourceV2 from './data_source/v2'; +``` + +### Introduce a new sub-domain: `Prediction` + +For our second product requirement we are going to introduce a new concept. Let's start by updating our folder structure: + +``` +common + index.ts + latest.ts + data_source + weather_dashboard + prediction + v1.ts +``` + +```ts +// common/prediction/v1.ts + +import type { DataSource } from '../data_source/v2'; + +/** Random set of weather models, just for illustration */ +type Model = 'GFS' | 'ECMWF' | 'GEM'; + +/** Limited set of options rather than "string" so we can more easily version */ +type TimeFrame = '1d' | '2d' | '3d' | '4d' | '5d' | '6d' | '1w' | '2w'; + +export interface PredictionInput { + /** How far back we should look in our data */ + start_date: string; // !! Introduction of inconsistent snake case naming convention, will need a new version to fix + /** How far out to predict. Note, longer time frames result in lower accuracy */ + timeFrame: TimeFrame; + /** Choice of weather model to use */ + model: Model; + /** Data source for this prediction */ + dataSource: DataSource; +} + +export interface PredictionOutput { ... } + +// Below are HTTP APIs for predictions + +export interface CreatePredictionHTTPBody { + input: PredictionInput; +} + +export interface CreatePredictionHTTPResponse { + result: PredictionOutput; +} + +// And so forth... +``` + + + Both `WeatherDashboard` and `Prediction` reference `DataSource`. Therefore, both will increment their version whenever `DataSource` changes. + + +## Challenge + +Normalize our domain objects by only holding a reference to `DataSource` in `WeatherDashboard` and `Prediction` domain objects. + +
    + Solution +
    + 1. We will add a way to uniquely identify a `DataSource` + 2. `DataSource` is currently specified in both `WeatherDashboard` and `Prediction`, therefore both will need to be updated as well. + + Let's start by updating our folder structure to introduce the new versions. + + ``` + common + data_source + v1.ts + v2.ts + v3.ts + weather_dashboard + v1.ts + v2.ts + v3.ts + prediction + v1.ts + v2.ts + ``` + + Now, let's add our new types : + + ```ts + // common/data_source/v3.ts + export interface DataSource { + /** A string that uniquely identifies a DataSource */ + id: string; + /** Some URL that provides weather data in an expected format for scraping */ + url: string; + /** A user-friendly name */ + name: string; + /** A longer description of this data source */ + description?: string; + /** The data view data is stored in */ + dataViewId: string; + /** Username to use with source URL */ + username?: string; + /** Password to use with source URL */ + password?: string; + } + // ...followed by all other HTTP related interfaces + + // common/weather_dashboard/v3.ts + export interface WeatherDashboard { + /** A unique ID for this weather dashboard */ + id: string; + /** Definition of a dashboard imported from the `dashboard` plugin */ + dashboard: PortableDashboard; + /** ID of the data source to use with this dashboard */ + dataSourceId: string; + } + // ...followed by all other HTTP related interfaces + + // common/prediction/v3.ts + export interface PredictionInput { + /** How far back we should look in our data */ + startDate: string; // Fixed inconsistent naming + /** How far out to predict. Note, longer time frames result in lower accuracy */ + timeFrame: TimeFrame; + /** Choice of weather model to use */ + model: Model; + /** Data source for this prediction */ + dataSourceId: string; + } + // ...followed by all other HTTP related interfaces + ``` + + Next let's update `latest.ts` and `index.ts`: + + ```ts + // latest.ts + export * from './data_source/v3'; + export * from './weather_dashboard/v3'; + export * from './prediction/v3'; + + // index.ts + export { DataSource, WeatherDashboard, GetWeatherDashboardHTTPResponse, Prediction } from './latest'; + export * as weatherDashboardV1 from './weather_dashboard/v1'; + export * as dataSourceV1 from './data_source/v1'; + export * as predictionV1 from './prediction/v1'; + + export * as weatherDashboardV2 from './weather_dashboard/v2'; + export * as dataSourceV2 from './data_source/v2'; + export * as predictionV2 from './prediction/v2'; + + export * as weatherDashboardV3 from './weather_dashboard/v3'; + export * as dataSourceV3 from './data_source/v3'; + ``` + + Refactoring interfaces in this way creates a much larger maintenance burden because: + + 1. application code must now translate between the denormalized and normalized versions of these interfaces + 2. code must remember to support both old and new naming conventions + + ...for as long as these APIs are in use. We will not cover deprecation strategies in this tutorial (incoming). Sufficed to + say: _take care when designing public APIs_. +
    + +## Additional resources + +* [PR to prepare Saved Objects Management](https://github.com/elastic/kibana/pull/149495) for versioning \ No newline at end of file diff --git a/nav-kibana-dev.docnav.json b/nav-kibana-dev.docnav.json index 490718262a816..cfee44522daad 100644 --- a/nav-kibana-dev.docnav.json +++ b/nav-kibana-dev.docnav.json @@ -128,6 +128,10 @@ { "id": "kibDevTutorialSavedObject" }, + { + "id": "kibDevTutorialVersioningInterfaces", + "label": "Versioning interfaces" + }, { "id": "kibDevTutorialSubmitPullRequest" }, From d051183adee6328ef86a8124b835ae69bfbae802 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Wed, 1 Mar 2023 16:46:25 +0100 Subject: [PATCH 087/131] [Synthetics] Error timeline date range (#151965) --- .../common/runtime_types/ping/error_state.ts | 16 +++- .../synthetics/test_run_details.journey.ts | 2 +- .../browser_steps_list.tsx | 51 ++++++++----- .../components/error_duration.tsx | 39 ++++++++-- .../components/error_timeline.tsx | 28 ++++++- .../error_details/components/resolved_at.tsx | 8 +- .../error_details/error_details_page.tsx | 20 +++-- .../hooks/use_error_details_breadcrumbs.ts | 7 +- .../hooks/use_error_failed_tests.tsx | 3 +- .../hooks/use_find_my_killer_state.ts | 76 +++++++++++++++++++ .../components/error_details/route_config.tsx | 2 +- .../hooks/use_monitor_errors.tsx | 9 ++- .../monitor_errors/errors_list.tsx | 74 +++++++++++------- .../monitor_errors/failed_tests.tsx | 33 +++++--- .../monitor_errors/monitor_errors.tsx | 6 +- .../test_time_formats.test.ts | 20 ++--- .../monitor_test_result/test_time_formats.ts | 30 +++++++- 17 files changed, 320 insertions(+), 104 deletions(-) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_find_my_killer_state.ts diff --git a/x-pack/plugins/synthetics/common/runtime_types/ping/error_state.ts b/x-pack/plugins/synthetics/common/runtime_types/ping/error_state.ts index 86b0b07052eac..cf09da6eb92fc 100644 --- a/x-pack/plugins/synthetics/common/runtime_types/ping/error_state.ts +++ b/x-pack/plugins/synthetics/common/runtime_types/ping/error_state.ts @@ -6,14 +6,26 @@ */ import * as t from 'io-ts'; +export const StateEndsCodec = t.type({ + duration_ms: t.union([t.string, t.number]), + checks: t.number, + ends: t.union([t.string, t.null]), + started_at: t.string, + id: t.string, + up: t.number, + down: t.number, + status: t.string, +}); export const ErrorStateCodec = t.type({ - duration_ms: t.string, + duration_ms: t.union([t.string, t.number]), checks: t.number, - ends: t.union([t.string, t.null]), + ends: t.union([StateEndsCodec, t.null]), started_at: t.string, id: t.string, up: t.number, down: t.number, status: t.string, }); + +export type ErrorState = t.TypeOf; diff --git a/x-pack/plugins/synthetics/e2e/journeys/synthetics/test_run_details.journey.ts b/x-pack/plugins/synthetics/e2e/journeys/synthetics/test_run_details.journey.ts index ea8f70742f578..e9f931e64bf04 100644 --- a/x-pack/plugins/synthetics/e2e/journeys/synthetics/test_run_details.journey.ts +++ b/x-pack/plugins/synthetics/e2e/journeys/synthetics/test_run_details.journey.ts @@ -65,6 +65,6 @@ journey(`TestRunDetailsPage`, async ({ page, params }) => { await page.waitForSelector('text=Test run details'); await page.waitForSelector('text=Go to https://www.google.com'); - await page.waitForSelector('text=After 2.1 s'); + await page.waitForSelector('text=After 2.12 s'); }); }); 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 c90a00710f32f..a9341eae5fa69 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 @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import React, { CSSProperties, ReactElement, useState } from 'react'; +import React, { CSSProperties, ReactElement, useCallback, useEffect, useState } from 'react'; import { EuiBasicTable, EuiBasicTableColumn, @@ -62,25 +62,38 @@ export const BrowserStepsList = ({ Record >({}); - const toggleDetails = (item: JourneyStep) => { - const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; - if (itemIdToExpandedRowMapValues[item._id]) { - delete itemIdToExpandedRowMapValues[item._id]; - } else { - if (testNowMode) { - itemIdToExpandedRowMapValues[item._id] = ( - - - - - - ); - } else { - itemIdToExpandedRowMapValues[item._id] = <>; - } + const toggleDetails = useCallback( + (item: JourneyStep) => { + setItemIdToExpandedRowMap((prevState) => { + const itemIdToExpandedRowMapValues = { ...prevState }; + if (itemIdToExpandedRowMapValues[item._id]) { + delete itemIdToExpandedRowMapValues[item._id]; + } else { + if (testNowMode) { + itemIdToExpandedRowMapValues[item._id] = ( + + + + + + ); + } else { + itemIdToExpandedRowMapValues[item._id] = <>; + } + } + return itemIdToExpandedRowMapValues; + }); + }, + [steps, testNowMode] + ); + + const failedStep = stepEnds?.find((step) => step.synthetics.step?.status === 'failed'); + + useEffect(() => { + if (failedStep && showExpand) { + toggleDetails(failedStep); } - setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); - }; + }, [failedStep, showExpand, toggleDetails]); const columns: Array> = [ ...(showExpand diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx index 9b65149be3ad0..bac7b09ecbf84 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_duration.tsx @@ -8,7 +8,8 @@ import React from 'react'; import { EuiDescriptionList } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import moment from 'moment'; +import moment, { Moment } from 'moment'; +import { useFindMyKillerState } from '../hooks/use_find_my_killer_state'; import { useErrorFailedTests } from '../hooks/use_last_error_state'; export const ErrorDuration: React.FC = () => { @@ -16,13 +17,41 @@ export const ErrorDuration: React.FC = () => { const state = failedTests?.[0]?.state; - const duration = state ? moment().diff(moment(state?.started_at), 'minutes') : 0; + const { killerState } = useFindMyKillerState(); - return ( - - ); + const endsAt = killerState?.timestamp ? moment(killerState?.timestamp) : moment(); + const startedAt = moment(state?.started_at); + + const duration = state ? getErrorDuration(startedAt, endsAt) : 0; + + return ; }; const ERROR_DURATION = i18n.translate('xpack.synthetics.errorDetails.errorDuration', { defaultMessage: 'Error duration', }); + +const getErrorDuration = (startedAt: Moment, endsAt: Moment) => { + // const endsAt = state.ends ? moment(state.ends) : moment(); + // const startedAt = moment(state?.started_at); + + const diffInDays = endsAt.diff(startedAt, 'days'); + if (diffInDays > 1) { + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.days', { + defaultMessage: '{value} days', + values: { value: diffInDays }, + }); + } + const diffInHours = endsAt.diff(startedAt, 'hours'); + if (diffInHours > 1) { + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.hours', { + defaultMessage: '{value} hours', + values: { value: diffInHours }, + }); + } + const diffInMinutes = endsAt.diff(startedAt, 'minutes'); + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.mins', { + defaultMessage: '{value} mins', + values: { value: diffInMinutes }, + }); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_timeline.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_timeline.tsx index 30461842e963f..d2e0b12793bc6 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_timeline.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/error_timeline.tsx @@ -5,8 +5,32 @@ * 2.0. */ import React from 'react'; +import { EuiLoadingContent } from '@elastic/eui'; +import moment from 'moment'; +import { Ping } from '../../../../../../common/runtime_types'; import { MonitorFailedTests } from '../../monitor_details/monitor_errors/failed_tests'; -export const ErrorTimeline = () => { - return ; +export const ErrorTimeline = ({ lastTestRun }: { lastTestRun?: Ping }) => { + if (!lastTestRun) { + return ; + } + const diff = moment(lastTestRun.monitor.timespan?.lt).diff( + moment(lastTestRun.monitor.timespan?.gte), + 'minutes' + ); + const startedAt = lastTestRun?.state?.started_at; + + return ( + + ); }; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/resolved_at.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/resolved_at.tsx index 75b1f9a31690b..76e8ca2ebaea1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/resolved_at.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/components/resolved_at.tsx @@ -8,15 +8,13 @@ import React, { ReactElement } from 'react'; import { EuiDescriptionList } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { useErrorFailedTests } from '../hooks/use_last_error_state'; import { useFormatTestRunAt } from '../../../utils/monitor_test_result/test_time_formats'; +import { useFindMyKillerState } from '../hooks/use_find_my_killer_state'; export const ResolvedAt: React.FC = () => { - const { failedTests } = useErrorFailedTests(); + const { killerState } = useFindMyKillerState(); - const state = failedTests?.[0]?.state; - - let endsAt: string | ReactElement = useFormatTestRunAt(state?.ends ?? ''); + let endsAt: string | ReactElement = useFormatTestRunAt(killerState?.timestamp); if (!endsAt) { endsAt = 'N/A'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx index 084dd68934626..4a6ea2d3f34e1 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/error_details_page.tsx @@ -43,7 +43,7 @@ export function ErrorDetailsPage() { return (
    - + @@ -71,13 +71,19 @@ export function ErrorDetailsPage() { - - {data?.details?.journey && failedStep && ( - - )} - + {data?.details?.journey && failedStep && ( + <> + + + + + + )} - diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_details_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_details_breadcrumbs.ts index 61cef2b818615..c96df76b40456 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_details_breadcrumbs.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_details_breadcrumbs.ts @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useSelectedLocation } from '../../monitor_details/hooks/use_selected_location'; import { useTestRunDetailsBreadcrumbs } from '../../test_run_details/hooks/use_test_run_details_breadcrumbs'; import { useSelectedMonitor } from '../../monitor_details/hooks/use_selected_monitor'; import { ConfigKey } from '../../../../../../common/runtime_types'; @@ -19,10 +20,14 @@ export const useErrorDetailsBreadcrumbs = ( const { monitor } = useSelectedMonitor(); + const selectedLocation = useSelectedLocation(); + const errorsBreadcrumbs = [ { text: ERRORS_CRUMB, - href: `${appPath}/monitor/${monitor?.[ConfigKey.CONFIG_ID]}/errors`, + href: `${appPath}/monitor/${monitor?.[ConfigKey.CONFIG_ID]}/errors?locationId=${ + selectedLocation?.id + }`, }, ...(extraCrumbs ?? []), ]; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx index 241c410038276..8b061d7c587f7 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_error_failed_tests.tsx @@ -57,7 +57,8 @@ export function useErrorFailedTests() { return useMemo(() => { const failedTests = data?.hits.hits?.map((doc) => { - return doc._source as Ping; + const source = doc._source as any; + return { ...source, timestamp: source['@timestamp'] } as Ping; }) ?? []; return { diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_find_my_killer_state.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_find_my_killer_state.ts new file mode 100644 index 0000000000000..33f923c94d2ba --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/hooks/use_find_my_killer_state.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useParams } from 'react-router-dom'; +import { useMemo } from 'react'; +import { useReduxEsSearch } from '../../../hooks/use_redux_es_search'; +import { Ping } from '../../../../../../common/runtime_types'; +import { + EXCLUDE_RUN_ONCE_FILTER, + SUMMARY_FILTER, +} from '../../../../../../common/constants/client_defaults'; +import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants'; +import { useSyntheticsRefreshContext } from '../../../contexts'; +import { useGetUrlParams } from '../../../hooks'; + +export function useFindMyKillerState() { + const { lastRefresh } = useSyntheticsRefreshContext(); + + const { errorStateId, monitorId } = useParams<{ errorStateId: string; monitorId: string }>(); + + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); + + const { data, loading } = useReduxEsSearch( + { + index: SYNTHETICS_INDEX_PATTERN, + + body: { + // TODO: remove this once we have a better way to handle this mapping + runtime_mappings: { + 'state.ends.id': { + type: 'keyword', + }, + }, + size: 1, + query: { + bool: { + filter: [ + SUMMARY_FILTER, + EXCLUDE_RUN_ONCE_FILTER, + { + term: { + 'state.ends.id': errorStateId, + }, + }, + { + term: { + config_id: monitorId, + }, + }, + ], + }, + }, + sort: [{ '@timestamp': 'desc' }], + }, + }, + [lastRefresh, monitorId, dateRangeStart, dateRangeEnd], + { name: 'getStateWhichEndTheState' } + ); + + return useMemo(() => { + const killerStates = + data?.hits.hits?.map((doc) => { + const source = doc._source as any; + return { ...source, timestamp: source['@timestamp'] } as Ping; + }) ?? []; + + return { + loading, + killerState: killerStates?.[0], + }; + }, [data, loading]); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/route_config.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/route_config.tsx index c53de93fa5123..3e2d0f39000fe 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/route_config.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/error_details/route_config.tsx @@ -39,7 +39,7 @@ export const getErrorDetailsRouteConfig = ( ), rightSideItems: [ , - , + , , , ], 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 6f6052af64a3f..e45e64dab1c15 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 @@ -87,12 +87,15 @@ export function useMonitorErrors(monitorIdArg?: string) { }, }, }, - [lastRefresh, monitorId, monitorIdArg, dateRangeStart, dateRangeEnd], - { name: 'getMonitorErrors', isRequestReady: Boolean(selectedLocation?.label) } + [lastRefresh, monitorId, monitorIdArg, dateRangeStart, dateRangeEnd, selectedLocation?.label], + { + name: `getMonitorErrors/${dateRangeStart}/${dateRangeEnd}`, + isRequestReady: Boolean(selectedLocation?.label), + } ); return useMemo(() => { - const errorStates = (data?.aggregations?.errorStates.buckets ?? []).map((loc) => { + const errorStates = data?.aggregations?.errorStates.buckets?.map((loc) => { return loc.summary.hits.hits?.[0]._source as PingState; }); 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 ecd1f6141c7f4..d8fb9cc827fcd 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 @@ -50,6 +50,10 @@ export const ErrorsList = ({ const selectedLocation = useSelectedLocation(); + const lastTestRun = errorStates?.sort((a, b) => { + return moment(b.state.started_at).valueOf() - moment(a.state.started_at).valueOf(); + })?.[0]; + const columns = [ { field: 'item.state.started_at', @@ -67,49 +71,56 @@ export const ErrorsList = ({ /> ); const isActive = isActiveState(item); - if (!isActive) { + if (!isActive || lastTestRun.state.id !== item.state.id) { return link; } return ( - {link} + + {link} + - Active + {ACTIVE_LABEL} ); }, }, + ...(isBrowserType + ? [ + { + field: 'monitor.check_group', + name: FAILED_STEP_LABEL, + truncateText: true, + sortable: (a: PingState) => { + const failedStep = failedSteps.find( + (step) => step.monitor.check_group === a.monitor.check_group + ); + if (!failedStep) { + return a.monitor.check_group; + } + return failedStep.synthetics?.step?.name; + }, + render: (value: string, item: PingState) => { + const failedStep = failedSteps.find((step) => step.monitor.check_group === value); + if (!failedStep) { + return <>--; + } + return ( + + {failedStep.synthetics?.step?.index}. {failedStep.synthetics?.step?.name} + + ); + }, + }, + ] + : []), { - field: 'monitor.check_group', - name: !isBrowserType ? ERROR_MESSAGE_LABEL : FAILED_STEP_LABEL, - truncateText: true, - sortable: (a: PingState) => { - const failedStep = failedSteps.find( - (step) => step.monitor.check_group === a.monitor.check_group - ); - if (!failedStep) { - return a.monitor.check_group; - } - return failedStep.synthetics?.step?.name; - }, - render: (value: string, item: PingState) => { - if (!isBrowserType) { - return {item.error.message ?? '--'}; - } - const failedStep = failedSteps.find((step) => step.monitor.check_group === value); - if (!failedStep) { - return <>--; - } - return ( - - {failedStep.synthetics?.step?.index}. {failedStep.synthetics?.step?.name} - - ); - }, + field: 'error.message', + name: ERROR_MESSAGE_LABEL, }, { field: 'state.duration_ms', @@ -157,6 +168,7 @@ export const ErrorsList = ({
    { +export const MonitorFailedTests = ({ + time, + allowBrushing = true, +}: { + time: { to: string; from: string }; + allowBrushing?: boolean; +}) => { const { observability } = useKibana().services; const { ExploratoryViewEmbeddable } = observability; @@ -41,7 +47,8 @@ export const MonitorFailedTests = ({ time }: { time: { to: string; from: string { time, reportDefinitions: { - ...(monitorId ? { 'monitor.id': [monitorId] } : { 'state.id': [errorStateId] }), + ...(monitorId ? { 'monitor.id': [monitorId] } : {}), + ...(errorStateId ? { 'state.id': [errorStateId] } : {}), }, dataType: 'synthetics', selectedMetricField: 'failed_tests', @@ -49,21 +56,25 @@ export const MonitorFailedTests = ({ time }: { time: { to: string; from: string }, ]} onBrushEnd={({ range }) => { - updateUrl({ - dateRangeStart: moment(range[0]).toISOString(), - dateRangeEnd: moment(range[1]).toISOString(), - }); + if (allowBrushing) { + updateUrl({ + dateRangeStart: moment(range[0]).toISOString(), + dateRangeEnd: moment(range[1]).toISOString(), + }); + } }} /> {FAILED_TESTS_LABEL} - - - {BRUSH_LABEL} - - + {allowBrushing && ( + + + {BRUSH_LABEL} + + + )} ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx index 4d2794e9da995..04930af018152 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_errors/monitor_errors.tsx @@ -23,9 +23,9 @@ import { ErrorsTabContent } from './errors_tab_content'; export const MonitorErrors = () => { const { errorStates, loading, data } = useMonitorErrors(); - const initialLoading = loading && !data; + const initialLoading = !data; - const emptyState = !loading && errorStates.length === 0; + const emptyState = !loading && errorStates && errorStates?.length === 0; const redirect = useMonitorDetailsPage(); if (redirect) { @@ -39,7 +39,7 @@ export const MonitorErrors = () => { {initialLoading && } {emptyState && }
    - +
    ); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts index 5337468f6e730..b1e808d748d76 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.test.ts @@ -9,16 +9,16 @@ import { formatTestDuration } from './test_time_formats'; describe('formatTestDuration', () => { it.each` - duration | expected | isMilli - ${undefined} | ${'0 ms'} | ${undefined} - ${120_000_000} | ${'2 min'} | ${undefined} - ${6_200_000} | ${'6.2 s'} | ${false} - ${500_000} | ${'500 ms'} | ${undefined} - ${100} | ${'0 ms'} | ${undefined} - ${undefined} | ${'0 ms'} | ${true} - ${600_000} | ${'10 min'} | ${true} - ${6_200} | ${'6.2 s'} | ${true} - ${500} | ${'500 ms'} | ${true} + duration | expected | isMilli + ${undefined} | ${'0 ms'} | ${undefined} + ${120_000_000} | ${'2 mins'} | ${undefined} + ${6_200_000} | ${'6.2 sec'} | ${false} + ${500_000} | ${'500 ms'} | ${undefined} + ${100} | ${'0 ms'} | ${undefined} + ${undefined} | ${'0 ms'} | ${true} + ${600_000} | ${'10 mins'} | ${true} + ${6_200} | ${'6.2 sec'} | ${true} + ${500} | ${'500 ms'} | ${true} `( 'returns $expected when `duration` is $duration and `isMilli` $isMilli', ({ diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts index 5d605ad4c2192..efae8b1652738 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/monitor_test_result/test_time_formats.ts @@ -6,6 +6,7 @@ */ import moment from 'moment'; +import { i18n } from '@kbn/i18n'; import { useKibanaDateFormat } from '../../../../hooks/use_kibana_date_format'; /** @@ -16,19 +17,40 @@ import { useKibanaDateFormat } from '../../../../hooks/use_kibana_date_format'; export const formatTestDuration = (duration = 0, isMilli = false) => { const secs = isMilli ? duration / 1e3 : duration / 1e6; + const hours = Math.floor(secs / 3600); + + if (hours >= 1) { + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.hours', { + defaultMessage: '{value} hours', + values: { value: hours }, + }); + } + if (secs >= 60) { - return `${parseFloat((secs / 60).toFixed(1))} min`; + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.minutes', { + defaultMessage: '{value} mins', + values: { value: parseFloat((secs / 60).toFixed(1)) }, + }); } if (secs >= 1) { - return `${parseFloat(secs.toFixed(1))} s`; + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.seconds', { + defaultMessage: '{value} sec', + values: { value: parseFloat(secs.toFixed(1)) }, + }); } if (isMilli) { - return `${duration.toFixed(0)} ms`; + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.milliseconds', { + defaultMessage: '{value} ms', + values: { value: duration.toFixed(0) }, + }); } - return `${(duration / 1000).toFixed(0)} ms`; + return i18n.translate('xpack.synthetics.errorDetails.errorDuration.microseconds', { + defaultMessage: '{value} ms', + values: { value: (duration / 1000).toFixed(0) }, + }); }; export function formatTestRunAt(timestamp: string, format: string) { From 5e397c4b609ae9dfc874103621d28f591124b90d Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Wed, 1 Mar 2023 10:54:41 -0500 Subject: [PATCH 088/131] Makes spaces optional in observability plugin (#151147) ## Summary This PR makes spaces optional in the "observability" plugin as requested in https://github.com/elastic/kibana/issues/149687 To test this, use the following setting in your kibana.yml config file: ```yaml xpack.spaces.enabled: false ``` When you log in, there will be no spaces choice. Screenshot 2023-02-21 at 11 53 18 AM --- x-pack/plugins/observability/kibana.jsonc | 3 +-- .../public/hooks/use_kibana_space.tsx | 2 +- .../overview_page/helpers/use_metrics.ts | 17 +++++++++++++++-- x-pack/plugins/observability/public/plugin.ts | 2 +- x-pack/plugins/observability/server/plugin.ts | 2 ++ 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/observability/kibana.jsonc b/x-pack/plugins/observability/kibana.jsonc index ad5fac050d671..d49e3ea870a62 100644 --- a/x-pack/plugins/observability/kibana.jsonc +++ b/x-pack/plugins/observability/kibana.jsonc @@ -24,8 +24,7 @@ "unifiedSearch", "security", "guidedOnboarding", - "share", - "spaces" + "share" ], "optionalPlugins": [ "discover", diff --git a/x-pack/plugins/observability/public/hooks/use_kibana_space.tsx b/x-pack/plugins/observability/public/hooks/use_kibana_space.tsx index 11716e948d855..8f2ebf187dc77 100644 --- a/x-pack/plugins/observability/public/hooks/use_kibana_space.tsx +++ b/x-pack/plugins/observability/public/hooks/use_kibana_space.tsx @@ -15,7 +15,7 @@ export const useKibanaSpace = () => { data: space, loading, error, - } = useFetcher>(() => { + } = useFetcher | undefined>(() => { return services.spaces?.getActiveSpace(); }, [services.spaces]); diff --git a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/use_metrics.ts b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/use_metrics.ts index 78fffde25d629..dd9581bd67867 100644 --- a/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/use_metrics.ts +++ b/x-pack/plugins/observability/public/pages/overview/containers/overview_page/helpers/use_metrics.ts @@ -29,9 +29,22 @@ export const useOverviewMetrics = ({ hasAnyData }: { hasAnyData: boolean | undef } CAPABILITIES_KEYS.forEach((feature) => { - if (capabilities[feature].show === false) { + const name = feature === 'infrastructure' ? 'metrics' : feature; + + // Track metric if the feature has been disabled, either because it + // is missing or has show === false (manual disabling may not be + // possible in all versions of Kibana) + if (!capabilities[feature] || capabilities[feature]?.show === false) { + trackMetric({ + metric: `oblt_disabled_feature_${name}`, + }); + } + + // Track a separate metric if the feature is missing from the capabilities + // (This usually means the plugin was auto-disabled by Kibana) + if (!capabilities[feature]) { trackMetric({ - metric: `oblt_disabled_feature_${feature === 'infrastructure' ? 'metrics' : feature}`, + metric: `oblt_missing_feature_${name}`, }); } }); diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index e43725d0c5681..6af40e9a4345f 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -105,7 +105,7 @@ export interface ObservabilityPublicPluginsStart { ruleTypeRegistry: RuleTypeRegistryContract; security: SecurityPluginStart; share: SharePluginStart; - spaces: SpacesPluginStart; + spaces?: SpacesPluginStart; triggersActionsUi: TriggersAndActionsUIPublicPluginStart; usageCollection: UsageCollectionSetup; unifiedSearch: UnifiedSearchPublicPluginStart; diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts index 39a69d7fa1666..e570fd7887952 100644 --- a/x-pack/plugins/observability/server/plugin.ts +++ b/x-pack/plugins/observability/server/plugin.ts @@ -17,6 +17,7 @@ import { PluginSetupContract } from '@kbn/alerting-plugin/server'; import { Dataset, RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; import { PluginSetupContract as FeaturesSetup } from '@kbn/features-plugin/server'; import { createUICapabilities } from '@kbn/cases-plugin/common'; +import { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; import { experimentalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/experimental_rule_field_map'; import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/alerting-plugin/server'; import type { GuidedOnboardingPluginSetup } from '@kbn/guided-onboarding-plugin/server'; @@ -50,6 +51,7 @@ interface PluginSetup { features: FeaturesSetup; guidedOnboarding: GuidedOnboardingPluginSetup; ruleRegistry: RuleRegistryPluginSetupContract; + spaces?: SpacesPluginSetup; usageCollection?: UsageCollectionSetup; } From 06c70d96c6a3f5cd2e88235a109228639e6a137b Mon Sep 17 00:00:00 2001 From: Coen Warmer Date: Wed, 1 Mar 2023 16:56:23 +0100 Subject: [PATCH 089/131] [SLO] Alternative split to remote indices (#152463) ## Summary This updates the utility to process a string of one or more indices. It assumed when one part of the string passed contained `remote:`, all remaining indices would also have to contain `remote`, but this isn't necessary. --- .../services/slo/transform_generators/common.test.ts | 4 +++- .../services/slo/transform_generators/common.ts | 12 +++--------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/common.test.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/common.test.ts index ba9856860ec84..fa34496573338 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/common.test.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/common.test.ts @@ -13,7 +13,9 @@ describe('common', () => { ['foo-*', 'foo-*'], ['foo-*,bar-*', ['foo-*', 'bar-*']], ['remote:foo-*', 'remote:foo-*'], - ['remote:foo*,bar-*', ['remote:foo*', 'remote:bar-*']], + ['remote:foo*,bar-*', ['remote:foo*', 'bar-*']], + ['remote:foo*,remote:bar-*', ['remote:foo*', 'remote:bar-*']], + ['remote:foo*,bar-*,remote:baz-*', ['remote:foo*', 'bar-*', 'remote:baz-*']], ])("parses the index '%s' correctly", (index, expected) => { expect(parseIndex(index)).toEqual(expected); }); diff --git a/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts b/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts index 54197076d359f..ea64f23662695 100644 --- a/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts +++ b/x-pack/plugins/observability/server/services/slo/transform_generators/common.ts @@ -17,15 +17,9 @@ export function getElastichsearchQueryOrThrow(kuery: string) { } export function parseIndex(index: string): string | string[] { - if (index.indexOf(',') > -1) { - if (index.indexOf(':') > -1) { - const indexParts = index.split(':'); // "remote_name:foo-*,bar*" - const remoteName = indexParts[0]; - return indexParts[1].split(',').map((idx) => `${remoteName}:${idx}`); // [ "remote_name:foo-*", "remote_name:bar-*"] - } - - return index.split(','); + if (index.indexOf(',') === -1) { + return index; } - return index; + return index.split(','); } From b956d91b10bda989c1f11bdfbcb14fcee16b234b Mon Sep 17 00:00:00 2001 From: Khristinin Nikita Date: Wed, 1 Mar 2023 17:42:16 +0100 Subject: [PATCH 090/131] Threat match tests for term query (#152071) Added several tests for terms query rules, which tests that match and term query rules are the same. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../rule_execution_logic/threat_match.ts | 572 ++++++++++-------- x-pack/test/tsconfig.json | 1 + 2 files changed, 311 insertions(+), 262 deletions(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts index 0f92db72d3c2a..8b3e4db6fa542 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/rule_execution_logic/threat_match.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { get, isEqual } from 'lodash'; +import { get, isEqual, omit } from 'lodash'; import expect from '@kbn/expect'; import { ALERT_REASON, @@ -19,6 +19,7 @@ import { VERSION, } from '@kbn/rule-data-utils'; import { flattenWithPrefix } from '@kbn/securitysolution-rules'; +import { ThreatMapping } from '@kbn/securitysolution-io-ts-alerting-types'; import { ThreatMatchRuleCreateProps } from '@kbn/security-solution-plugin/common/detection_engine/rule_schema'; @@ -32,6 +33,7 @@ import { ALERT_ORIGINAL_EVENT_MODULE, ALERT_ORIGINAL_TIME, } from '@kbn/security-solution-plugin/common/field_maps/field_names'; +import { RuleExecutionStatus } from '@kbn/security-solution-plugin/common/detection_engine/rule_monitoring'; import { previewRule, getOpenSignals, @@ -41,7 +43,6 @@ import { createRule, } from '../../utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; - const format = (value: unknown): string => JSON.stringify(value, null, 2); // Asserts that each expected value is included in the subject, independent of @@ -54,6 +55,85 @@ const assertContains = (subject: unknown[], expected: unknown[]) => ) ); +const createThreatMatchRule = ({ + name = 'Query with a rule id', + index = ['auditbeat-*'], + query = '*:*', + // eslint-disable-next-line @typescript-eslint/naming-convention + rule_id = 'rule-1', + // eslint-disable-next-line @typescript-eslint/naming-convention + threat_indicator_path = 'threat.indicator', + // eslint-disable-next-line @typescript-eslint/naming-convention + threat_query = 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip + // eslint-disable-next-line @typescript-eslint/naming-convention + threat_index = ['auditbeat-*'], + // eslint-disable-next-line @typescript-eslint/naming-convention + threat_mapping = [ + // We match host.name against host.name + { + entries: [ + { + field: 'host.name', + value: 'host.name', + type: 'mapping', + }, + ], + }, + ], + override = {}, +}: { + threat_mapping?: ThreatMapping; + name?: string; + query?: string; + rule_id?: string; + index?: string[]; + threat_index?: string[]; + threat_query?: string; + threat_indicator_path?: string; + override?: any; +} = {}): ThreatMatchRuleCreateProps => ({ + description: 'Detecting root and admin users', + name, + severity: 'high', + index, + type: 'threat_match', + risk_score: 55, + language: 'kuery', + rule_id, + from: '1900-01-01T00:00:00.000Z', + query, + threat_query, + threat_index, + threat_mapping, + threat_filters: [], + threat_indicator_path, + ...override, +}); + +function alertsAreTheSame(alertsA: any[], alertsB: any[]): void { + const mapAlert = (alert: any) => { + return omit(alert._source, [ + '@timestamp', + 'kibana.alert.last_detected', + 'kibana.rule.created_at', + 'kibana.rule.execution.uuid', + 'kibana.name.execution.uuid', + 'kibana.alert.rule.parameters', + 'kibana.alert.rule.rule_id', + 'kibana.alert.rule.name', + 'kibana.alert.rule.created_at', + 'kibana.alert.rule.updated_at', + 'kibana.alert.rule.uuid', + 'kibana.alert.rule.execution.uuid', + 'kibana.alert.start', + 'kibana.alert.reason', + 'kibana.alert.uuid', + ]); + }; + + expect(alertsA.map(mapAlert)).to.eql(alertsB.map(mapAlert)); +} + // eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); @@ -66,6 +146,8 @@ export default ({ getService }: FtrProviderContext) => { */ describe('Threat match type rules', () => { before(async () => { + // await deleteSignalsIndex(supertest, log); + // await deleteAllAlerts(supertest, log); await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); }); @@ -76,38 +158,19 @@ export default ({ getService }: FtrProviderContext) => { }); // First 2 test creates a real rule - remaining tests use preview API - it('should be able to execute and get 10 signals when doing a specific query (terms query)', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', - threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip - threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity - threat_mapping: [ - // We match host.name against host.name - { - entries: [ - { - field: 'host.name', - value: 'host.name', - type: 'mapping', - }, - ], - }, - ], - threat_filters: [], - }; + it('should be able to execute and get all signals when doing a specific query (terms query)', async () => { + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule(); const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); - expect(alerts.hits.hits.length).equal(10); + const alerts = await getOpenSignals( + supertest, + log, + es, + createdRule, + RuleExecutionStatus.succeeded, + 100 + ); + expect(alerts.hits.hits.length).equal(88); const fullSource = alerts.hits.hits.find( (signal) => (signal._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' @@ -257,20 +320,8 @@ export default ({ getService }: FtrProviderContext) => { }), }); }); - it('should be able to execute and get 10 signals when doing a specific query (match query)', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', - threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip - threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity + it('should be able to execute and get all signals when doing a specific query (match query)', async () => { + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ // We match host.name against host.name { @@ -288,12 +339,18 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const createdRule = await createRule(supertest, log, rule); - const alerts = await getOpenSignals(supertest, log, es, createdRule); - expect(alerts.hits.hits.length).equal(10); + const alerts = await getOpenSignals( + supertest, + log, + es, + createdRule, + RuleExecutionStatus.succeeded, + 100 + ); + expect(alerts.hits.hits.length).equal(88); const fullSource = alerts.hits.hits.find( (signal) => (signal._source?.[ALERT_ANCESTORS] as Ancestor[])[0].id === '7yJ-B2kBR346wHgnhlMn' @@ -444,20 +501,64 @@ export default ({ getService }: FtrProviderContext) => { }); }); + it('terms and match should have the same alerts with pagination', async () => { + const termRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ + override: { + items_per_search: 1, + concurrent_searches: 1, + }, + }); + + const matchRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ + override: { + items_per_search: 1, + concurrent_searches: 1, + }, + name: 'Math rule', + rule_id: 'rule-2', + threat_mapping: [ + // We match host.name against host.name + { + entries: [ + { + field: 'host.name', + value: 'host.name', + type: 'mapping', + }, + { + field: 'host.name', + value: 'host.name', + type: 'mapping', + }, + ], + }, + ], + }); + + const createdRuleTerm = await createRule(supertest, log, termRule); + const createdRuleMatch = await createRule(supertest, log, matchRule); + const alertsTerm = await getOpenSignals( + supertest, + log, + es, + createdRuleTerm, + RuleExecutionStatus.succeeded, + 100 + ); + const alertsMatch = await getOpenSignals( + supertest, + log, + es, + createdRuleMatch, + RuleExecutionStatus.succeeded, + 100 + ); + + alertsAreTheSame(alertsTerm.hits.hits, alertsMatch.hits.hits); + }); + it('should return 0 matches if the mapping does not match against anything in the mapping', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', - threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip - threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ // We match host.name against host.name { @@ -470,8 +571,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); @@ -479,19 +579,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return 0 signals when using an AND and one of the clauses does not have data', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', - threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip - threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ { entries: [ @@ -508,8 +596,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); @@ -517,19 +604,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return 0 signals when using an AND and one of the clauses has a made up value that does not exist', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - type: 'threat_match', - index: ['auditbeat-*'], - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', - threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip - threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ { entries: [ @@ -546,8 +621,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); @@ -557,35 +631,13 @@ export default ({ getService }: FtrProviderContext) => { describe('timeout behavior', () => { // TODO: unskip this and see if we can make it not flaky it.skip('will return an error if a rule execution exceeds the rule interval', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a short interval', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', - threat_query: '*:*', // broad query to take more time - threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity - threat_mapping: [ - { - entries: [ - { - field: 'host.name', - value: 'host.name', - type: 'mapping', - }, - ], - }, - ], - threat_filters: [], - concurrent_searches: 1, - interval: '1s', // short interval - items_per_search: 1, // iterate only 1 threat item per loop to ensure we're slow - }; + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ + override: { + concurrent_searches: 1, + interval: '1s', // short interval + items_per_search: 1, // iterate only 1 threat item per loop to ensure we're slow + }, + }); const { logs } = await previewRule({ supertest, rule }); expect(logs[0].errors[0]).to.contain('execution has exceeded its allotted interval'); @@ -602,20 +654,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('enriches signals with the single indicator that matched', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', // narrow events down to 2 with a destination.ip - threat_indicator_path: 'threat.indicator', - threat_query: 'threat.indicator.domain: 159.89.119.67', // narrow things down to indicators with a domain - threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ { entries: [ @@ -627,8 +666,9 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + threat_query: 'threat.indicator.domain: 159.89.119.67', // narrow things down to indicators with a domain + threat_index: ['filebeat-*'], + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); @@ -690,18 +730,8 @@ export default ({ getService }: FtrProviderContext) => { }); it('enriches signals with multiple indicators if several matched', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: 'NOT source.port:35326', // specify query to have signals more than treat indicators, but only 1 will match - threat_indicator_path: 'threat.indicator', threat_query: 'threat.indicator.ip: *', threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -715,9 +745,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; - + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); expect(previewAlerts.length).equal(1); @@ -767,18 +795,8 @@ export default ({ getService }: FtrProviderContext) => { }); it('adds a single indicator that matched multiple fields', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: 'NOT source.port:35326', // specify query to have signals more than treat indicators, but only 1 will match - threat_indicator_path: 'threat.indicator', threat_query: 'threat.indicator.port: 57324 or threat.indicator.ip:45.115.45.3', // narrow our query to a single indicator threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -801,8 +819,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); @@ -876,19 +893,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('generates multiple signals with multiple matches', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - threat_language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: '*:*', // narrow our query to a single record that matches two indicators - threat_indicator_path: 'threat.indicator', + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_query: '*:*', threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -916,8 +921,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); @@ -1023,18 +1027,8 @@ export default ({ getService }: FtrProviderContext) => { }); it('enriches signals with the single indicator that matched', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', + const termRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: 'destination.ip:159.89.119.67', - threat_indicator_path: 'threat.indicator', threat_query: 'threat.indicator.domain: *', // narrow things down to indicators with a domain threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -1048,14 +1042,36 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); + const matchRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ + query: 'destination.ip:159.89.119.67', + threat_query: 'threat.indicator.domain: *', // narrow things down to indicators with a domain + threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module + threat_mapping: [ + { + entries: [ + { + value: 'threat.indicator.domain', + field: 'destination.ip', + type: 'mapping', + }, + { + value: 'threat.indicator.domain', + field: 'destination.ip', + type: 'mapping', + }, + ], + }, + ], + }); - const { previewId } = await previewRule({ supertest, rule }); - const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).equal(2); + const { previewId: termPrevieId } = await previewRule({ supertest, rule: termRule }); + const termPreviewAlerts = await getPreviewAlerts({ es, previewId: termPrevieId }); + const { previewId: matchPreviewId } = await previewRule({ supertest, rule: matchRule }); + const matchPrevieAlerts = await getPreviewAlerts({ es, previewId: matchPreviewId }); + expect(termPreviewAlerts.length).equal(2); - const threats = previewAlerts.map((hit) => hit._source?.threat); + const threats = termPreviewAlerts.map((hit) => hit._source?.threat); expect(threats).to.eql([ { enrichments: [ @@ -1108,21 +1124,12 @@ export default ({ getService }: FtrProviderContext) => { ], }, ]); + alertsAreTheSame(termPreviewAlerts, matchPrevieAlerts); }); it('enriches signals with multiple indicators if several matched', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', - query: 'source.port: 57324', // narrow our query to a single record that matches two indicators - threat_indicator_path: 'threat.indicator', + const termRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ + query: 'source.port: 57324', // narrow our query to a single record that matches two indicatorsthreat_query: 'threat.indicator.ip: *', threat_query: 'threat.indicator.ip: *', threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -1136,14 +1143,36 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); + const matchRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ + query: 'source.port: 57324', // narrow our query to a single record that matches two indicatorsthreat_query: 'threat.indicator.ip: *', + threat_query: 'threat.indicator.ip: *', + threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module + threat_mapping: [ + { + entries: [ + { + value: 'threat.indicator.ip', + field: 'source.ip', + type: 'mapping', + }, + { + value: 'threat.indicator.ip', + field: 'source.ip', + type: 'mapping', + }, + ], + }, + ], + }); - const { previewId } = await previewRule({ supertest, rule }); - const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).equal(1); + const { previewId: termPrevieId } = await previewRule({ supertest, rule: termRule }); + const termPreviewAlerts = await getPreviewAlerts({ es, previewId: termPrevieId }); + const { previewId: matchPreviewId } = await previewRule({ supertest, rule: matchRule }); + const matchPrevieAlerts = await getPreviewAlerts({ es, previewId: matchPreviewId }); + expect(termPreviewAlerts.length).equal(1); - const [threat] = previewAlerts.map((hit) => hit._source?.threat) as Array<{ + const [threat] = termPreviewAlerts.map((hit) => hit._source?.threat) as Array<{ enrichments: unknown[]; }>; @@ -1185,21 +1214,12 @@ export default ({ getService }: FtrProviderContext) => { }, }, ]); + alertsAreTheSame(termPreviewAlerts, matchPrevieAlerts); }); it('adds a single indicator that matched multiple fields', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', + const termRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: 'source.port: 57324', // narrow our query to a single record that matches two indicators - threat_indicator_path: 'threat.indicator', threat_query: 'threat.indicator.ip: *', threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -1222,18 +1242,57 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); + const matchRule: ThreatMatchRuleCreateProps = createThreatMatchRule({ + query: 'source.port: 57324', // narrow our query to a single record that matches two indicators + threat_query: 'threat.indicator.ip: *', + threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module + threat_mapping: [ + { + entries: [ + { + value: 'threat.indicator.port', + field: 'source.port', + type: 'mapping', + }, + { + value: 'threat.indicator.port', + field: 'source.port', + type: 'mapping', + }, + ], + }, + { + entries: [ + { + value: 'threat.indicator.ip', + field: 'source.ip', + type: 'mapping', + }, + { + value: 'threat.indicator.ip', + field: 'source.ip', + type: 'mapping', + }, + ], + }, + ], + }); - const { previewId } = await previewRule({ supertest, rule }); - const previewAlerts = await getPreviewAlerts({ es, previewId }); - expect(previewAlerts.length).equal(1); + const { previewId: termPrevieId } = await previewRule({ supertest, rule: termRule }); + const termPreviewAlerts = await getPreviewAlerts({ es, previewId: termPrevieId }); + const { previewId: matchPreviewId } = await previewRule({ supertest, rule: matchRule }); + const matchPrevieAlerts = await getPreviewAlerts({ es, previewId: matchPreviewId }); + expect(termPreviewAlerts.length).equal(1); - const [threat] = previewAlerts.map((hit) => hit._source?.threat) as Array<{ + const [threatTerm] = termPreviewAlerts.map((hit) => hit._source?.threat) as Array<{ enrichments: unknown[]; }>; - assertContains(threat.enrichments, [ + const [threatMatch] = matchPrevieAlerts.map((hit) => hit._source?.threat) as Array<{ + enrichments: unknown[]; + }>; + assertContains(threatTerm.enrichments, [ { feed: {}, indicator: { @@ -1294,22 +1353,23 @@ export default ({ getService }: FtrProviderContext) => { }, }, ]); + const sortEnrichments = (a: any, b: any) => { + const atomicA = a.matched.atomic.toString(); + const atomicB = b.matched.atomic.toString(); + if (atomicA === atomicB) { + return a.indicator.description > b.indicator.description ? 1 : -1; + } + return atomicA > atomicB ? 1 : -1; + }; + + expect(threatTerm.enrichments.sort(sortEnrichments)).to.be.eql( + threatMatch.enrichments.sort(sortEnrichments) + ); }); it('generates multiple signals with multiple matches', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - threat_language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: '(source.port:57324 and source.ip:45.115.45.3) or destination.ip:159.89.119.67', // narrow our query to a single record that matches two indicators - threat_indicator_path: 'threat.indicator', threat_query: '*:*', threat_index: ['filebeat-*'], // Mimics indicators from the filebeat MISP module threat_mapping: [ @@ -1337,8 +1397,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId }); @@ -1444,19 +1503,9 @@ export default ({ getService }: FtrProviderContext) => { }); it('should be enriched with host risk score', async () => { - const rule: ThreatMatchRuleCreateProps = { - description: 'Detecting root and admin users', - name: 'Query with a rule id', - severity: 'high', - index: ['auditbeat-*'], - type: 'threat_match', - risk_score: 55, - language: 'kuery', - rule_id: 'rule-1', - from: '1900-01-01T00:00:00.000Z', + const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ query: '*:*', threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip - threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity threat_mapping: [ // We match host.name against host.name { @@ -1469,8 +1518,7 @@ export default ({ getService }: FtrProviderContext) => { ], }, ], - threat_filters: [], - }; + }); const { previewId } = await previewRule({ supertest, rule }); const previewAlerts = await getPreviewAlerts({ es, previewId, size: 100 }); diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index be736ec73fd0d..58a8f285bc9ef 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -117,5 +117,6 @@ "@kbn/security-api-integration-helpers", "@kbn/alerts-as-data-utils", "@kbn/discover-plugin", + "@kbn/securitysolution-io-ts-alerting-types", ] } From e45586c576e8799d87345a8ebd672388b9d8ccee Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Wed, 1 Mar 2023 17:53:23 +0100 Subject: [PATCH 091/131] =?UTF-8?q?Upgrade=20`undici`=20dependency=20(`5.1?= =?UTF-8?q?4.0`=20=E2=86=92=20`5.20.0`).=20(#152458)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6ffc80f4e34d5..5dbae5b6a72b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27762,9 +27762,9 @@ unc-path-regex@^0.1.2: integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= undici@^5.11.0, undici@^5.5.1: - version "5.14.0" - resolved "https://registry.yarnpkg.com/undici/-/undici-5.14.0.tgz#1169d0cdee06a4ffdd30810f6228d57998884d00" - integrity sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ== + version "5.20.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-5.20.0.tgz#6327462f5ce1d3646bcdac99da7317f455bcc263" + integrity sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g== dependencies: busboy "^1.6.0" From 4e424050bf1dad42eb879b5b9bff1749a7f58333 Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Wed, 1 Mar 2023 12:06:01 -0500 Subject: [PATCH 092/131] [Security Solution] Make timeline confirm prompt space aware (#152457) ## Summary The timeline save prompt's use of application.navigateToUrl was not taking space into account, this pr updates it so that it does. ![timeline-block-space-aware](https://user-images.githubusercontent.com/56408403/222162486-b936ccd8-af62-46da-a4b2-a6c0825a9344.gif) --- .../hooks/timeline/use_timeline_save_prompt.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts index 72337661c6c38..f9bfcfc72c346 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/timeline/use_timeline_save_prompt.ts @@ -30,7 +30,7 @@ export const useTimelineSavePrompt = ( onAppLeave: (handler: AppLeaveHandler) => void ) => { const dispatch = useDispatch(); - const { overlays, application } = useKibana().services; + const { overlays, application, http } = useKibana().services; const getIsTimelineVisible = useShowTimelineForGivenPath(); const history = useHistory(); @@ -66,10 +66,12 @@ export const useTimelineSavePrompt = ( if (confirmRes) { unblock(); - - application.navigateToUrl(location.pathname + location.hash + location.search, { - state: location.state, - }); + application.navigateToUrl( + http.basePath.get() + location.pathname + location.hash + location.search, + { + state: location.state, + } + ); } else { showSaveTimelineModal(); } @@ -92,6 +94,7 @@ export const useTimelineSavePrompt = ( }; }, [ history, + http.basePath, application, overlays, showSaveTimelineModal, From 242d7bcc0c4c49d611918f6c5b61d4cd0b021779 Mon Sep 17 00:00:00 2001 From: Ashokaditya <1849116+ashokaditya@users.noreply.github.com> Date: Wed, 1 Mar 2023 18:52:02 +0100 Subject: [PATCH 093/131] [Security Solution][Endpoint][Response Actions] Show `execute` action output on response actions history (#151344) ## Summary Shows execute action output in actions log details tray ![Screenshot 2023-02-21 at 19 26 55](https://user-images.githubusercontent.com/1849116/220428875-9a7dafd0-a594-4320-8a42-0d20b6f73550.png) **flyout log** ![execute-file-actions-log](https://user-images.githubusercontent.com/1849116/221645720-544a2487-2c6d-427f-a732-9ffe9d13b8a0.gif) **history page** ![execute-file-actions-history](https://user-images.githubusercontent.com/1849116/221645890-329da851-5a40-4008-88ee-b40a07f00c21.gif) ### 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 - [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)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../endpoint_action_generator.ts | 4 +- ...ecute_action_host_response_output.test.tsx | 99 ++++ .../execute_action_host_response_output.tsx | 113 +++-- .../execute_action.tsx | 2 + .../get_file_action.tsx | 7 +- .../components/action_log_expanded_tray.tsx | 237 +++++++++ .../actions_log_date_range_picker.tsx | 4 +- .../components/actions_log_filter.tsx | 5 +- .../components/actions_log_filter_popover.tsx | 4 +- .../components/actions_log_filters.tsx | 15 +- .../components/actions_log_table.tsx | 387 ++++++++++++++ .../actions_log_users_filter.test.tsx | 19 +- .../components/actions_log_users_filter.tsx | 4 +- .../components/status_badge.tsx | 15 +- .../use_action_history_url_params.ts | 25 +- .../response_actions_log.test.tsx | 331 ++++++++---- .../response_actions_log.tsx | 429 ++++++++-------- .../translations.tsx | 12 + .../use_response_actions_log_table.tsx | 471 ------------------ ...esponse_action_file_download_link.test.tsx | 22 +- .../response_action_file_download_link.tsx | 12 +- 21 files changed, 1346 insertions(+), 871 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.test.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx create mode 100644 x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_table.tsx delete mode 100644 x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/use_response_actions_log_table.tsx diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts index cb4848d79eb41..2c2a4fb23e859 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_action_generator.ts @@ -220,9 +220,9 @@ export class EndpointActionGenerator extends BaseDataGenerator { ResponseActionsExecuteParameters > ).parameters = { - command: (overrides.parameters as ResponseActionsExecuteParameters).command ?? 'ls -al', + command: (overrides.parameters as ResponseActionsExecuteParameters)?.command ?? 'ls -al', timeout: - (overrides.parameters as ResponseActionsExecuteParameters).timeout ?? + (overrides.parameters as ResponseActionsExecuteParameters)?.timeout ?? DEFAULT_EXECUTE_ACTION_TIMEOUT, // 4hrs }; } diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.test.tsx new file mode 100644 index 0000000000000..835e816f85f47 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.test.tsx @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { AppContextTestRender } from '../../../common/mock/endpoint'; +import { createAppRootMockRenderer } from '../../../common/mock/endpoint'; +import type { + ActionDetails, + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters, +} from '../../../../common/endpoint/types'; +import React from 'react'; +import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator'; +import { + ExecuteActionHostResponseOutput, + type ExecuteActionHostResponseOutputProps, +} from './execute_action_host_response_output'; +import { responseActionsHttpMocks } from '../../mocks/response_actions_http_mocks'; +import { getDeferred } from '../../mocks/utils'; +import { waitFor } from '@testing-library/react'; +import type { IHttpFetchError } from '@kbn/core-http-browser'; + +describe('When using the `ExecuteActionHostResponseOutput` component', () => { + let render: () => ReturnType; + let renderResult: ReturnType; + let renderProps: ExecuteActionHostResponseOutputProps; + let apiMocks: ReturnType; + + beforeEach(() => { + const appTestContext = createAppRootMockRenderer(); + + apiMocks = responseActionsHttpMocks(appTestContext.coreStart.http); + + renderProps = { + action: new EndpointActionGenerator('seed').generateActionDetails< + ResponseActionExecuteOutputContent, + ResponseActionsExecuteParameters + >({ command: 'execute' }), + 'data-test-subj': 'test', + }; + + render = () => { + renderResult = appTestContext.render(); + return renderResult; + }; + }); + + it('should show execute output and execute errors', async () => { + render(); + expect(renderResult.getByTestId('test')).toBeTruthy(); + }); + + it('should show loading when details are fetching', async () => { + (renderProps.action as ActionDetails).outputs = {}; + + const deferred = getDeferred(); + + apiMocks.responseProvider.actionDetails.mockDelay.mockReturnValue(deferred.promise); + (renderProps.action as ActionDetails).completedAt = '2021-04-15T16:08:47.449Z'; + + render(); + expect(renderResult.getByTestId('test-loading')).toBeTruthy(); + + // Release the `action details` api + deferred.resolve(); + + await waitFor(() => { + expect(apiMocks.responseProvider.actionDetails).toHaveBeenCalledWith({ + path: '/api/endpoint/action/123', + }); + }); + expect(renderResult.queryByTestId('test-loading')).toBeNull(); + expect(renderResult.getByTestId('test')).toBeTruthy(); + }); + + it('should show nothing when no output in action details', () => { + (renderProps.action as ActionDetails).outputs = {}; + render(); + expect(renderResult.queryByTestId('test')).toBeNull(); + }); + + it('should handle API error', async () => { + (renderProps.action as ActionDetails).outputs = {}; + const error = { message: 'server error', response: { status: 500 } } as IHttpFetchError; + + (renderProps.action as ActionDetails).completedAt = '2021-04-15T16:08:47.449Z'; + apiMocks.responseProvider.actionDetails.mockImplementation(() => { + throw error; + }); + + render(); + + await waitFor(() => { + expect(renderResult.getByTestId('test-apiError')).toHaveTextContent('server error'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.tsx index 3624f577716dd..959c6ad0ce5e0 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_execute_action/execute_action_host_response_output.tsx @@ -4,27 +4,24 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { memo, useMemo } from 'react'; +import React, { memo, useEffect, useMemo, useState } from 'react'; import { EuiAccordion, - EuiFlexGroup, EuiFlexItem, + EuiSkeletonText, EuiSpacer, EuiText, useGeneratedHtmlId, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ResponseActionFileDownloadLink } from '../response_action_file_download_link'; +import { useIsMounted } from '@kbn/securitysolution-hook-utils'; +import { useGetActionDetails } from '../../hooks/response_actions/use_get_action_details'; import type { ActionDetails, MaybeImmutable, ResponseActionExecuteOutputContent, } from '../../../../common/endpoint/types'; - -const EXECUTE_FILE_LINK_TITLE = i18n.translate( - 'xpack.securitySolution.responseActionExecuteDownloadLink.downloadButtonLabel', - { defaultMessage: 'Click here to download full output' } -); +import { FormattedError } from '../formatted_error'; const ACCORDION_BUTTON_TEXT = Object.freeze({ output: { @@ -57,14 +54,15 @@ const ACCORDION_BUTTON_TEXT = Object.freeze({ }, }); interface ExecuteActionOutputProps { - content: string; + content?: string; initialIsOpen?: boolean; - isTruncated: boolean; + isTruncated?: boolean; + textSize?: 's' | 'xs'; type: 'error' | 'output'; } const ExecutionActionOutputAccordion = memo( - ({ content, initialIsOpen = false, isTruncated, type }) => { + ({ content, initialIsOpen = false, isTruncated = false, textSize, type }) => { const id = useGeneratedHtmlId({ prefix: 'executeActionOutputAccordions', suffix: type, @@ -77,7 +75,7 @@ const ExecutionActionOutputAccordion = memo( paddingSize="s" > ( ); ExecutionActionOutputAccordion.displayName = 'ExecutionActionOutputAccordion'; -interface ExecuteActionHostResponseOutputProps { +export interface ExecuteActionHostResponseOutputProps { action: MaybeImmutable; agentId?: string; 'data-test-subj'?: string; @@ -99,42 +97,75 @@ interface ExecuteActionHostResponseOutputProps { } export const ExecuteActionHostResponseOutput = memo( - ({ action, agentId = action.agents[0], 'data-test-subj': dataTestSubj, textSize }) => { + ({ action, agentId = action.agents[0], 'data-test-subj': dataTestSubj, textSize = 'xs' }) => { + const isMounted = useIsMounted(); const outputContent = useMemo( () => action.outputs && action.outputs[agentId] && (action.outputs[agentId].content as ResponseActionExecuteOutputContent), - [agentId, action] + [action.outputs, agentId] ); - return ( - - - - + const { + error, + data: actionDetails, + isFetching, + isFetched, + } = useGetActionDetails(action.id, { + enabled: !outputContent, + }); + + const [executeOutputContent, setExecuteOutputContent] = useState< + undefined | ResponseActionExecuteOutputContent + >(outputContent); - {outputContent && ( - - - - - - )} - + useEffect(() => { + if ( + isMounted() && + isFetched && + actionDetails && + actionDetails.data && + actionDetails.data.outputs && + actionDetails.data.outputs[agentId] + ) { + setExecuteOutputContent( + actionDetails.data.outputs[agentId].content as ResponseActionExecuteOutputContent + ); + } + + return () => { + setExecuteOutputContent(undefined); + }; + }, [actionDetails, agentId, isFetched, isMounted]); + + if (isFetching && !executeOutputContent) { + return ( + + ); + } + + if (error) { + return ; + } + + return ( + + + + + ); } ); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx index fe766f2015516..e5ea73de39cf4 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/execute_action.tsx @@ -75,6 +75,8 @@ export const ExecuteActionResult = memo< ); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_file_action.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_file_action.tsx index b65e13003c263..13ad9da09637a 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_file_action.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/command_render_components/get_file_action.tsx @@ -7,6 +7,7 @@ import React, { memo, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { useSendGetFileRequest } from '../../../hooks/response_actions/use_send_get_file_request'; import type { ResponseActionGetFileRequestBody } from '../../../../../common/endpoint/schema/actions'; import { useConsoleActionSubmitter } from '../hooks/use_console_action_submitter'; @@ -18,6 +19,7 @@ export const GetFileActionResult = memo< path: string[]; }> >(({ command, setStore, store, status, setStatus, ResultComponent }) => { + const { canWriteFileOperations } = useUserPrivileges().endpointPrivileges; const actionCreator = useSendGetFileRequest(); const actionRequestBody = useMemo(() => { @@ -59,7 +61,10 @@ export const GetFileActionResult = memo< { defaultMessage: 'File retrieved from the host.' } )} > - + ); } diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx new file mode 100644 index 0000000000000..5be50866a9130 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/action_log_expanded_tray.tsx @@ -0,0 +1,237 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { memo, useMemo } from 'react'; +import { EuiCodeBlock, EuiFlexGroup, EuiFlexItem, EuiDescriptionList } from '@elastic/eui'; +import { css, euiStyled } from '@kbn/kibana-react-plugin/common'; +import { i18n } from '@kbn/i18n'; +import { useUserPrivileges } from '../../../../common/components/user_privileges'; +import { OUTPUT_MESSAGES } from '../translations'; +import { getUiCommand } from './hooks'; +import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; +import { ResponseActionFileDownloadLink } from '../../response_action_file_download_link'; +import { ExecuteActionHostResponseOutput } from '../../endpoint_execute_action'; +import { getEmptyValue } from '../../../../common/components/empty_value'; + +import { type ActionDetails, type MaybeImmutable } from '../../../../../common/endpoint/types'; +const EXECUTE_FILE_LINK_TITLE = i18n.translate( + 'xpack.securitySolution.responseActionExecuteDownloadLink.downloadButtonLabel', + { defaultMessage: 'Click here to download full output' } +); +const emptyValue = getEmptyValue(); + +const customDescriptionListCss = css` + &.euiDescriptionList { + > .euiDescriptionList__title { + color: ${(props) => props.theme.eui.euiColorDarkShade}; + font-size: ${(props) => props.theme.eui.euiFontSizeXS}; + } + + > .euiDescriptionList__title, + > .euiDescriptionList__description { + font-weight: ${(props) => props.theme.eui.euiFontWeightRegular}; + margin-top: ${(props) => props.theme.eui.euiSizeS}; + } + } +`; +const topSpacingCss = css` + ${(props) => `${props.theme.eui.euiSize} 0`} +`; +const dashedBorderCss = css` + ${(props) => `1px dashed ${props.theme.eui.euiColorDisabled}`}; +`; +const StyledDescriptionListOutput = euiStyled(EuiDescriptionList).attrs({ compressed: true })` + ${customDescriptionListCss} + dd { + margin: ${topSpacingCss}; + padding: ${topSpacingCss}; + border-top: ${dashedBorderCss}; + border-bottom: ${dashedBorderCss}; + } +`; + +const StyledDescriptionList = euiStyled(EuiDescriptionList).attrs({ + compressed: true, + type: 'column', +})` + ${customDescriptionListCss} +`; + +const StyledEuiCodeBlock = euiStyled(EuiCodeBlock).attrs({ + transparentBackground: true, + paddingSize: 'none', +})` + code { + color: ${(props) => props.theme.eui.euiColorDarkShade} !important; + } +`; + +const StyledEuiFlexGroup = euiStyled(EuiFlexGroup).attrs({ + direction: 'column', + className: 'eui-yScrollWithShadows', + gutterSize: 's', +})` + max-height: 270px; + overflow-y: auto; +`; + +const OutputContent = memo<{ action: MaybeImmutable; 'data-test-subj'?: string }>( + ({ action, 'data-test-subj': dataTestSubj }) => { + const getTestId = useTestIdGenerator(dataTestSubj); + + const { canWriteFileOperations, canWriteExecuteOperations } = + useUserPrivileges().endpointPrivileges; + + const { command, isCompleted, isExpired, wasSuccessful } = action; + + if (isExpired) { + return <>{OUTPUT_MESSAGES.hasExpired(command)}; + } + + if (!isCompleted) { + return <>{OUTPUT_MESSAGES.isPending(command)}; + } + + if (!wasSuccessful) { + return <>{OUTPUT_MESSAGES.hasFailed(command)}; + } + + if (command === 'get-file') { + return ( + <> + {OUTPUT_MESSAGES.wasSuccessful(command)} + + + ); + } + + if (command === 'execute') { + return ( + + {action.agents.map((agentId) => ( +
    + {OUTPUT_MESSAGES.wasSuccessful(command)} + + + + +
    + ))} +
    + ); + } + + return <>{OUTPUT_MESSAGES.wasSuccessful(command)}; + } +); + +OutputContent.displayName = 'OutputContent'; + +export const ActionsLogExpandedTray = memo<{ + action: MaybeImmutable; + 'data-test-subj'?: string; +}>(({ action, 'data-test-subj': dataTestSubj }) => { + const getTestId = useTestIdGenerator(dataTestSubj); + + const { startedAt, completedAt, command: _command, comment, parameters } = action; + + const parametersList = useMemo( + () => + parameters + ? Object.entries(parameters).map(([key, value]) => { + return `${key}:${value}`; + }) + : undefined, + [parameters] + ); + + const command = getUiCommand(_command); + + const dataList = useMemo( + () => + [ + { + title: OUTPUT_MESSAGES.expandSection.placedAt, + description: `${startedAt}`, + }, + { + title: OUTPUT_MESSAGES.expandSection.startedAt, + description: `${startedAt}`, + }, + { + title: OUTPUT_MESSAGES.expandSection.completedAt, + description: `${completedAt ?? emptyValue}`, + }, + { + title: OUTPUT_MESSAGES.expandSection.input, + description: `${command}`, + }, + { + title: OUTPUT_MESSAGES.expandSection.parameters, + description: parametersList ? parametersList : emptyValue, + }, + { + title: OUTPUT_MESSAGES.expandSection.comment, + description: comment ? comment : emptyValue, + }, + ].map(({ title, description }) => { + return { + title: {title}, + description: {description}, + }; + }), + [command, comment, completedAt, parametersList, startedAt] + ); + + const outputList = useMemo( + () => [ + { + title: ( + {`${OUTPUT_MESSAGES.expandSection.output}:`} + ), + description: ( + // codeblock for output + + + + ), + }, + ], + [action, dataTestSubj, getTestId] + ); + + return ( + <> + + + + + + + + + + ); +}); + +ActionsLogExpandedTray.displayName = 'ActionsLogExpandedTray'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx index af0988040f80e..fef40433c6848 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_date_range_picker.tsx @@ -41,6 +41,7 @@ export const ActionLogDateRangePicker = memo( onRefresh, onRefreshChange, onTimeChange, + 'data-test-subj': dataTestSubj, }: { dateRangePickerState: DateRangePickerValues; isDataLoading: boolean; @@ -48,9 +49,10 @@ export const ActionLogDateRangePicker = memo( onRefresh: () => void; onRefreshChange: (evt: OnRefreshChangeProps) => void; onTimeChange: ({ start, end }: DurationRange) => void; + 'data-test-subj'?: string; }) => { const { startDate: startDateFromUrl, endDate: endDateFromUrl } = useActionHistoryUrlParams(); - const getTestId = useTestIdGenerator('response-actions-list'); + const getTestId = useTestIdGenerator(dataTestSubj); const kibana = useKibana(); const { uiSettings } = kibana.services; const [commonlyUsedRanges] = useState(() => { diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx index 8482e275f7811..8b77b8152a177 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filter.tsx @@ -20,12 +20,14 @@ export const ActionsLogFilter = memo( filterName, isFlyout, onChangeFilterOptions, + 'data-test-subj': dataTestSubj, }: { filterName: FilterName; isFlyout: boolean; onChangeFilterOptions: (selectedOptions: string[]) => void; + 'data-test-subj'?: string; }) => { - const getTestId = useTestIdGenerator('response-actions-list'); + const getTestId = useTestIdGenerator(dataTestSubj); // popover states and handlers const [isPopoverOpen, setIsPopoverOpen] = useState(false); @@ -177,6 +179,7 @@ export const ActionsLogFilter = memo( numActiveFilters={numActiveFilters} numFilters={numFilters} onButtonClick={onPopoverButtonClick} + data-test-subj={dataTestSubj} > void; @@ -30,8 +31,9 @@ export const ActionsLogFilterPopover = memo( numActiveFilters: number; numFilters: number; onButtonClick: () => void; + 'data-test-subj'?: string; }) => { - const getTestId = useTestIdGenerator('response-actions-list'); + const getTestId = useTestIdGenerator(dataTestSubj); const filterGroupPopoverId = useGeneratedHtmlId({ prefix: 'filterGroupPopover', diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx index 9fb8cce0f291a..9215fd5fa3cee 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_filters.tsx @@ -33,6 +33,7 @@ export const ActionsLogFilters = memo( onRefreshChange, onTimeChange, showHostsFilter, + 'data-test-subj': dataTestSubj, }: { dateRangePickerState: DateRangePickerValues; isDataLoading: boolean; @@ -46,8 +47,9 @@ export const ActionsLogFilters = memo( onTimeChange: ({ start, end }: DurationRange) => void; onClick: ReturnType['refetch']; showHostsFilter: boolean; + 'data-test-subj'?: string; }) => { - const getTestId = useTestIdGenerator('response-actions-list'); + const getTestId = useTestIdGenerator(dataTestSubj); const filters = useMemo(() => { return ( <> @@ -56,21 +58,25 @@ export const ActionsLogFilters = memo( filterName={'hosts'} isFlyout={isFlyout} onChangeFilterOptions={onChangeHostsFilter} + data-test-subj={dataTestSubj} /> )} ); }, [ + dataTestSubj, isFlyout, onChangeCommandsFilter, onChangeHostsFilter, @@ -83,7 +89,11 @@ export const ActionsLogFilters = memo( return ( - + {filters} @@ -96,6 +106,7 @@ export const ActionsLogFilters = memo( onRefresh={onRefresh} onRefreshChange={onRefreshChange} onTimeChange={onTimeChange} + data-test-subj={dataTestSubj} /> diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_table.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_table.tsx new file mode 100644 index 0000000000000..09767754dc7fb --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_table.tsx @@ -0,0 +1,387 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { memo, useCallback, useMemo, useState } from 'react'; + +import type { CriteriaWithPagination } from '@elastic/eui'; +import { + EuiI18nNumber, + EuiAvatar, + EuiBasicTable, + EuiButtonIcon, + EuiFacetButton, + EuiHorizontalRule, + RIGHT_ALIGNMENT, + EuiScreenReaderOnly, + EuiText, + EuiToolTip, + type HorizontalAlignment, +} from '@elastic/eui'; +import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import type { ActionListApiResponse } from '../../../../../common/endpoint/types'; +import type { EndpointActionListRequestQuery } from '../../../../../common/endpoint/schema/actions'; +import { FormattedDate } from '../../../../common/components/formatted_date'; +import { TABLE_COLUMN_NAMES, UX_MESSAGES, ARIA_LABELS } from '../translations'; +import { getActionStatus, getUiCommand } from './hooks'; +import { getEmptyValue } from '../../../../common/components/empty_value'; +import { StatusBadge } from './status_badge'; +import { ActionsLogExpandedTray } from './action_log_expanded_tray'; +import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; +import { MANAGEMENT_PAGE_SIZE_OPTIONS } from '../../../common/constants'; +import { useActionHistoryUrlParams } from './use_action_history_url_params'; +import { useUrlPagination } from '../../../hooks/use_url_pagination'; + +const emptyValue = getEmptyValue(); + +// Truncated usernames +const StyledFacetButton = euiStyled(EuiFacetButton)` + .euiText { + margin-top: 0.38rem; + overflow-y: visible !important; + } +`; + +interface ActionsLogTableProps { + error?: string; + 'data-test-subj'?: string; + items: ActionListApiResponse['data']; + isFlyout: boolean; + loading: boolean; + onChange: ({ + page: _page, + }: CriteriaWithPagination) => void; + queryParams: EndpointActionListRequestQuery; + showHostNames: boolean; + totalItemCount: number; +} +interface ExpandedRowMapType { + [k: ActionListApiResponse['data'][number]['id']]: React.ReactNode; +} + +export const ActionsLogTable = memo( + ({ + 'data-test-subj': dataTestSubj, + error, + items, + isFlyout, + loading, + onChange, + queryParams, + showHostNames, + totalItemCount, + }) => { + const getTestId = useTestIdGenerator(dataTestSubj); + + const { pagination: paginationFromUrlParams } = useUrlPagination(); + const { withOutputs, setUrlWithOutputs } = useActionHistoryUrlParams(); + + const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState( + withOutputs + ? withOutputs.reduce((idToRowMap, actionId) => { + if (actionId.length) { + idToRowMap[actionId] = ( + item.id === actionId)[0]} + data-test-subj={dataTestSubj} + /> + ); + } + return idToRowMap; + }, {}) + : {} + ); + + const toggleDetails = useCallback( + (item: ActionListApiResponse['data'][number]) => { + const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; + if (itemIdToExpandedRowMapValues[item.id]) { + // close tray + delete itemIdToExpandedRowMapValues[item.id]; + } else { + // expanded tray contents + itemIdToExpandedRowMapValues[item.id] = ( + + ); + } + const expandedActionIds = Object.keys(itemIdToExpandedRowMapValues); + if (!isFlyout) { + // set and show `withOutputs` URL param on history page + setUrlWithOutputs(expandedActionIds.join()); + } + setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); + }, + [dataTestSubj, isFlyout, itemIdToExpandedRowMap, setUrlWithOutputs] + ); + // memoized callback for toggleDetails + const onClickCallback = useCallback( + (actionListDataItem: ActionListApiResponse['data'][number]) => () => + toggleDetails(actionListDataItem), + [toggleDetails] + ); + + const responseActionListColumns = useMemo(() => { + const columns = [ + { + field: 'startedAt', + name: TABLE_COLUMN_NAMES.time, + width: !showHostNames ? '21%' : '15%', + truncateText: true, + render: (startedAt: ActionListApiResponse['data'][number]['startedAt']) => { + return ( + + ); + }, + }, + { + field: 'command', + name: TABLE_COLUMN_NAMES.command, + width: !showHostNames ? '21%' : '10%', + truncateText: true, + render: (_command: ActionListApiResponse['data'][number]['command']) => { + const command = getUiCommand(_command); + return ( + + + {command} + + + ); + }, + }, + { + field: 'createdBy', + name: TABLE_COLUMN_NAMES.user, + width: !showHostNames ? '21%' : '14%', + truncateText: true, + render: (userId: ActionListApiResponse['data'][number]['createdBy']) => { + return ( + + } + > + + + {userId} + + + + ); + }, + }, + // conditional hostnames column + { + field: 'hosts', + name: TABLE_COLUMN_NAMES.hosts, + width: '20%', + truncateText: true, + render: (_hosts: ActionListApiResponse['data'][number]['hosts']) => { + const hosts = _hosts && Object.values(_hosts); + // join hostnames if the action is for multiple agents + // and skip empty strings for names if any + const _hostnames = hosts + .reduce((acc, host) => { + if (host.name.trim()) { + acc.push(host.name); + } + return acc; + }, []) + .join(', '); + + let hostnames = _hostnames; + if (!_hostnames) { + if (hosts.length > 1) { + // when action was for a single agent and no host name + hostnames = UX_MESSAGES.unenrolled.hosts; + } else if (hosts.length === 1) { + // when action was for a multiple agents + // and none of them have a host name + hostnames = UX_MESSAGES.unenrolled.host; + } + } + return ( + + + {hostnames} + + + ); + }, + }, + { + field: 'comment', + name: TABLE_COLUMN_NAMES.comments, + width: !showHostNames ? '21%' : '30%', + truncateText: true, + render: (comment: ActionListApiResponse['data'][number]['comment']) => { + return ( + + + {comment ?? emptyValue} + + + ); + }, + }, + { + field: 'status', + name: TABLE_COLUMN_NAMES.status, + width: !showHostNames ? '15%' : '10%', + render: (_status: ActionListApiResponse['data'][number]['status']) => { + const status = getActionStatus(_status); + + return ( + + + + ); + }, + }, + { + field: '', + align: RIGHT_ALIGNMENT as HorizontalAlignment, + width: '40px', + isExpander: true, + name: ( + + {UX_MESSAGES.screenReaderExpand} + + ), + render: (actionListDataItem: ActionListApiResponse['data'][number]) => { + return ( + + ); + }, + }, + ]; + // filter out the `hosts` column + // if showHostNames is FALSE + if (!showHostNames) { + return columns.filter((column) => column.field !== 'hosts'); + } + return columns; + }, [showHostNames, getTestId, itemIdToExpandedRowMap, onClickCallback]); + + // table pagination + const tablePagination = useMemo(() => { + return { + pageIndex: isFlyout ? (queryParams.page || 1) - 1 : paginationFromUrlParams.page - 1, + pageSize: isFlyout ? queryParams.pageSize || 10 : paginationFromUrlParams.pageSize, + totalItemCount, + pageSizeOptions: MANAGEMENT_PAGE_SIZE_OPTIONS as number[], + }; + }, [ + isFlyout, + paginationFromUrlParams.page, + paginationFromUrlParams.pageSize, + queryParams.page, + queryParams.pageSize, + totalItemCount, + ]); + + // compute record ranges + const pagedResultsCount = useMemo(() => { + const page = queryParams.page ?? 1; + const perPage = queryParams?.pageSize ?? 10; + + const totalPages = Math.ceil(totalItemCount / perPage); + const fromCount = perPage * page - perPage + 1; + const toCount = + page === totalPages || totalPages === 1 ? totalItemCount : fromCount + perPage - 1; + return { fromCount, toCount }; + }, [queryParams.page, queryParams.pageSize, totalItemCount]); + + // create range label to display + const recordRangeLabel = useMemo( + () => ( + + + + {'-'} + + + ), + total: , + recordsLabel: {UX_MESSAGES.recordsLabel(totalItemCount)}, + }} + /> + + ), + [getTestId, pagedResultsCount.fromCount, pagedResultsCount.toCount, totalItemCount] + ); + + return ( + <> + {recordRangeLabel} + + + + ); + } +); + +ActionsLogTable.displayName = 'ActionsLogTable'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx index 60b5f5368dafc..e6a4c4c242576 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.test.tsx @@ -23,7 +23,8 @@ describe('Users filter', () => { let history: AppContextTestRender['history']; let mockedContext: AppContextTestRender; - const testPrefix = 'response-actions-list-users-filter'; + const testPrefix = 'test'; + const filterPrefix = 'users-filter'; let onChangeUsersFilter: jest.Mock; beforeEach(async () => { @@ -32,7 +33,11 @@ describe('Users filter', () => { ({ history } = mockedContext); render = (props?: React.ComponentProps) => (renderResult = mockedContext.render( - + )); reactTestingLibrary.act(() => { history.push(`${MANAGEMENT_PATH}/response_actions`); @@ -42,7 +47,7 @@ describe('Users filter', () => { it('should show a search input for users', () => { render(); - const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + const searchInput = renderResult.getByTestId(`${testPrefix}-${filterPrefix}-search`); expect(searchInput).toBeTruthy(); expect(searchInput.getAttribute('placeholder')).toEqual('Filter by username'); }); @@ -50,7 +55,7 @@ describe('Users filter', () => { it('should search on given search string on enter', () => { render(); - const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + const searchInput = renderResult.getByTestId(`${testPrefix}-${filterPrefix}-search`); userEvent.type(searchInput, 'usernameX'); userEvent.type(searchInput, '{enter}'); expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX']); @@ -59,7 +64,7 @@ describe('Users filter', () => { it('should search comma separated strings as multiple users', () => { render(); - const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + const searchInput = renderResult.getByTestId(`${testPrefix}-${filterPrefix}-search`); userEvent.type(searchInput, 'usernameX,usernameY,usernameZ'); userEvent.type(searchInput, '{enter}'); expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX', 'usernameY', 'usernameZ']); @@ -68,7 +73,7 @@ describe('Users filter', () => { it('should ignore white spaces in a given username when updating the API params', () => { render(); - const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + const searchInput = renderResult.getByTestId(`${testPrefix}-${filterPrefix}-search`); userEvent.type(searchInput, ' usernameX '); userEvent.type(searchInput, '{enter}'); expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX']); @@ -77,7 +82,7 @@ describe('Users filter', () => { it('should ignore white spaces in comma separated usernames when updating the API params', () => { render(); - const searchInput = renderResult.getByTestId(`${testPrefix}-search`); + const searchInput = renderResult.getByTestId(`${testPrefix}-${filterPrefix}-search`); userEvent.type(searchInput, ' , usernameX ,usernameY , '); userEvent.type(searchInput, '{enter}'); expect(onChangeUsersFilter).toHaveBeenCalledWith(['usernameX', 'usernameY']); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.tsx index d9de7986c5e80..68cbfbffeb261 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/actions_log_users_filter.tsx @@ -15,11 +15,13 @@ export const ActionsLogUsersFilter = memo( ({ isFlyout, onChangeUsersFilter, + 'data-test-subj': dataTestSubj, }: { isFlyout: boolean; onChangeUsersFilter: (selectedUserIds: string[]) => void; + 'data-test-subj'?: string; }) => { - const getTestId = useTestIdGenerator('response-actions-list'); + const getTestId = useTestIdGenerator(dataTestSubj); const { users: usersFromUrlParams, setUrlUsersFilters } = useActionHistoryUrlParams(); const [searchValue, setSearchValue] = useState(''); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/status_badge.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/status_badge.tsx index fd8138a3f08e5..046811160c57d 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/status_badge.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/status_badge.tsx @@ -6,14 +6,19 @@ */ import React, { memo } from 'react'; import { EuiBadge, type EuiBadgeProps } from '@elastic/eui'; -import { useTestIdGenerator } from '../../../hooks/use_test_id_generator'; export const StatusBadge = memo( - ({ color, status }: { color: EuiBadgeProps['color']; status: string }) => { - const getTestId = useTestIdGenerator('response-actions-list'); - + ({ + color, + status, + 'data-test-subj': dataTestSubj, + }: { + color: EuiBadgeProps['color']; + 'data-test-subj'?: string; + status: string; + }) => { return ( - + {status} ); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts index a0e1623055f26..b483ed8a132cc 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/components/use_action_history_url_params.ts @@ -22,11 +22,13 @@ interface UrlParamsActionsLogFilters { startDate: string; endDate: string; users: string; + withOutputs: string; } interface ActionsLogFiltersFromUrlParams { commands?: ConsoleResponseActionCommands[]; hosts?: string[]; + withOutputs?: string[]; statuses?: ResponseActionStatus[]; startDate?: string; endDate?: string; @@ -35,12 +37,13 @@ interface ActionsLogFiltersFromUrlParams { setUrlHostsFilters: (agentIds: UrlParamsActionsLogFilters['hosts']) => void; setUrlStatusesFilters: (statuses: UrlParamsActionsLogFilters['statuses']) => void; setUrlUsersFilters: (users: UrlParamsActionsLogFilters['users']) => void; + setUrlWithOutputs: (outputs: UrlParamsActionsLogFilters['withOutputs']) => void; users?: string[]; } type FiltersFromUrl = Pick< ActionsLogFiltersFromUrlParams, - 'commands' | 'hosts' | 'statuses' | 'users' | 'startDate' | 'endDate' + 'commands' | 'hosts' | 'withOutputs' | 'statuses' | 'users' | 'startDate' | 'endDate' >; export const actionsLogFiltersFromUrlParams = ( @@ -53,6 +56,7 @@ export const actionsLogFiltersFromUrlParams = ( startDate: 'now-24h/h', endDate: 'now', users: [], + withOutputs: [], }; const urlCommands = urlParams.commands @@ -72,6 +76,10 @@ export const actionsLogFiltersFromUrlParams = ( const urlHosts = urlParams.hosts ? String(urlParams.hosts).split(',').sort() : []; + const urlWithOutputs = urlParams.withOutputs + ? String(urlParams.withOutputs).split(',').sort() + : []; + const urlStatuses = urlParams.statuses ? (String(urlParams.statuses).split(',') as ResponseActionStatus[]).reduce< ResponseActionStatus[] @@ -91,6 +99,7 @@ export const actionsLogFiltersFromUrlParams = ( actionsLogFilters.startDate = urlParams.startDate ? String(urlParams.startDate) : undefined; actionsLogFilters.endDate = urlParams.endDate ? String(urlParams.endDate) : undefined; actionsLogFilters.users = urlUsers.length ? urlUsers : undefined; + actionsLogFilters.withOutputs = urlWithOutputs.length ? urlWithOutputs : undefined; return actionsLogFilters; }; @@ -133,6 +142,19 @@ export const useActionHistoryUrlParams = (): ActionsLogFiltersFromUrlParams => { [history, location, toUrlParams, urlParams] ); + const setUrlWithOutputs = useCallback( + (actionIds: string) => { + history.push({ + ...location, + search: toUrlParams({ + ...urlParams, + withOutputs: actionIds.length ? actionIds : undefined, + }), + }); + }, + [history, location, toUrlParams, urlParams] + ); + const setUrlStatusesFilters = useCallback( (statuses: string) => { history.push({ @@ -187,6 +209,7 @@ export const useActionHistoryUrlParams = (): ActionsLogFiltersFromUrlParams => { setUrlActionsFilters, setUrlDateRangeFilters, setUrlHostsFilters, + setUrlWithOutputs, setUrlStatusesFilters, setUrlUsersFilters, }; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx index ae8d652aeaeb9..39ef4f40211b8 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.test.tsx @@ -16,6 +16,7 @@ import { } from '../../../common/mock/endpoint'; import { ResponseActionsLog } from './response_actions_log'; import type { + ActionDetailsApiResponse, ActionFileInfoApiResponse, ActionListApiResponse, } from '../../../../common/endpoint/types'; @@ -138,6 +139,20 @@ jest.mock('../../hooks/response_actions/use_get_file_info', () => { }; }); +let mockUseGetActionDetails: { + isFetching?: boolean; + isFetched?: boolean; + error?: Partial | null; + data?: ActionDetailsApiResponse; +}; +jest.mock('../../hooks/response_actions/use_get_action_details', () => { + const original = jest.requireActual('../../hooks/response_actions/use_get_action_details'); + return { + ...original, + useGetActionDetails: () => mockUseGetActionDetails, + }; +}); + const mockUseGetEndpointsList = useGetEndpointsList as jest.Mock; const getBaseMockedActionList = () => ({ @@ -147,7 +162,7 @@ const getBaseMockedActionList = () => ({ refetch: jest.fn(), }); describe('Response actions history', () => { - const testPrefix = 'response-actions-list'; + const testPrefix = 'test'; let render: ( props?: React.ComponentProps @@ -161,7 +176,9 @@ describe('Response actions history', () => { mockedContext = createAppRootMockRenderer(); ({ history } = mockedContext); render = (props?: React.ComponentProps) => - (renderResult = mockedContext.render()); + (renderResult = mockedContext.render( + + )); reactTestingLibrary.act(() => { history.push(`${MANAGEMENT_PATH}/response_actions`); }); @@ -246,7 +263,7 @@ describe('Response actions history', () => { const { getByTestId } = renderResult; - expect(getByTestId(`${testPrefix}-table-view`)).toBeTruthy(); + expect(getByTestId(`${testPrefix}`)).toBeTruthy(); expect(getByTestId(`${testPrefix}-endpointListTableTotal`)).toHaveTextContent( 'Showing 1-10 of 13 response actions' ); @@ -256,9 +273,7 @@ describe('Response actions history', () => { render({ agentIds: 'agent-a' }); expect( - Array.from( - renderResult.getByTestId(`${testPrefix}-table-view`).querySelectorAll('thead th') - ) + Array.from(renderResult.getByTestId(`${testPrefix}`).querySelectorAll('thead th')) .slice(0, 6) .map((col) => col.textContent) ).toEqual(['Time', 'Command', 'User', 'Comments', 'Status', 'Expand rows']); @@ -268,9 +283,7 @@ describe('Response actions history', () => { render({ showHostNames: true }); expect( - Array.from( - renderResult.getByTestId(`${testPrefix}-table-view`).querySelectorAll('thead th') - ) + Array.from(renderResult.getByTestId(`${testPrefix}`).querySelectorAll('thead th')) .slice(0, 7) .map((col) => col.textContent) ).toEqual(['Time', 'Command', 'User', 'Hosts', 'Comments', 'Status', 'Expand rows']); @@ -347,7 +360,7 @@ describe('Response actions history', () => { render(); const { getByTestId } = renderResult; - expect(getByTestId(`${testPrefix}-table-view`)).toBeTruthy(); + expect(getByTestId(`${testPrefix}`)).toBeTruthy(); expect(getByTestId(`${testPrefix}-endpointListTableTotal`)).toHaveTextContent( 'Showing 1-10 of 13 response actions' ); @@ -368,7 +381,7 @@ describe('Response actions history', () => { render(); const { getByTestId } = renderResult; - expect(getByTestId(`${testPrefix}-table-view`)).toBeTruthy(); + expect(getByTestId(`${testPrefix}`)).toBeTruthy(); expect(getByTestId(`${testPrefix}-endpointListTableTotal`)).toHaveTextContent( 'Showing 1-10 of 33 response actions' ); @@ -438,91 +451,6 @@ describe('Response actions history', () => { ); }); - it('should contain download link in expanded row for `get-file` action WITH file operation permission', async () => { - mockUseGetEndpointActionList = { - ...getBaseMockedActionList(), - data: await getActionListMock({ actionCount: 1, commands: ['get-file'] }), - }; - - mockUseGetFileInfo = { - isFetching: false, - error: null, - data: apiMocks.responseProvider.fileInfo(), - }; - - render(); - - const { getByTestId } = renderResult; - const expandButton = getByTestId(`${testPrefix}-expand-button`); - userEvent.click(expandButton); - - await waitFor(() => { - expect(apiMocks.responseProvider.fileInfo).toHaveBeenCalled(); - }); - - const downloadLink = getByTestId(`${testPrefix}-getFileDownloadLink`); - expect(downloadLink).toBeTruthy(); - expect(downloadLink.textContent).toEqual( - 'Click here to download(ZIP file passcode: elastic).Files are periodically deleted to clear storage space. Download and save file locally if needed.' - ); - }); - - it('should show file unavailable for download for `get-file` action WITH file operation permission when file is deleted', async () => { - mockUseGetEndpointActionList = { - ...getBaseMockedActionList(), - data: await getActionListMock({ actionCount: 1, commands: ['get-file'] }), - }; - - const fileInfo = apiMocks.responseProvider.fileInfo(); - fileInfo.data.status = 'DELETED'; - - apiMocks.responseProvider.fileInfo.mockReturnValue(fileInfo); - - mockUseGetFileInfo = { - isFetching: false, - error: null, - data: apiMocks.responseProvider.fileInfo(), - }; - - render(); - - const { getByTestId } = renderResult; - const expandButton = getByTestId(`${testPrefix}-expand-button`); - userEvent.click(expandButton); - - await waitFor(() => { - expect(apiMocks.responseProvider.fileInfo).toHaveBeenCalled(); - }); - - const unavailableText = getByTestId( - `${testPrefix}-getFileDownloadLink-fileNoLongerAvailable` - ); - expect(unavailableText).toBeTruthy(); - }); - - it('should not contain download link in expanded row for `get-file` action when NO file operation permission', async () => { - useUserPrivilegesMock.mockReturnValue({ - endpointPrivileges: getEndpointAuthzInitialStateMock({ - canWriteFileOperations: false, - }), - }); - - mockUseGetEndpointActionList = { - ...getBaseMockedActionList(), - data: await getActionListMock({ actionCount: 1, commands: ['get-file'] }), - }; - - render(); - const { getByTestId, queryByTestId } = renderResult; - - const expandButton = getByTestId(`${testPrefix}-expand-button`); - userEvent.click(expandButton); - const output = getByTestId(`${testPrefix}-details-tray-output`); - expect(output).toBeTruthy(); - expect(output.textContent).toEqual('get-file completed successfully'); - expect(queryByTestId(`${testPrefix}-getFileDownloadLink`)).toBeNull(); - }); - it('should refresh data when autoRefresh is toggled on', async () => { mockUseGetEndpointActionList = getBaseMockedActionList(); render(); @@ -570,6 +498,217 @@ describe('Response actions history', () => { userEvent.click(getByTestId('superDatePickerCommonlyUsed_Last_15 minutes')); expect(startDatePopoverButton).toHaveTextContent('Last 15 minutes'); }); + + describe('`get-file` action', () => { + it('should contain download link in expanded row for `get-file` action WITH file operation permission', async () => { + useUserPrivilegesMock.mockReturnValue({ + endpointPrivileges: getEndpointAuthzInitialStateMock({ + canWriteExecuteOperations: false, + }), + }); + mockUseGetEndpointActionList = { + ...getBaseMockedActionList(), + data: await getActionListMock({ actionCount: 1, commands: ['get-file'] }), + }; + + mockUseGetFileInfo = { + isFetching: false, + error: null, + data: apiMocks.responseProvider.fileInfo(), + }; + + render(); + + const { getByTestId } = renderResult; + const expandButton = getByTestId(`${testPrefix}-expand-button`); + userEvent.click(expandButton); + + await waitFor(() => { + expect(apiMocks.responseProvider.fileInfo).toHaveBeenCalled(); + }); + + const downloadLink = getByTestId(`${testPrefix}-getFileDownloadLink`); + expect(downloadLink).toBeTruthy(); + expect(downloadLink.textContent).toEqual( + 'Click here to download(ZIP file passcode: elastic).Files are periodically deleted to clear storage space. Download and save file locally if needed.' + ); + }); + + it('should not contain download link in expanded row for `get-file` action when NO file operation permission', async () => { + useUserPrivilegesMock.mockReturnValue({ + endpointPrivileges: getEndpointAuthzInitialStateMock({ + canWriteFileOperations: false, + }), + }); + + mockUseGetEndpointActionList = { + ...getBaseMockedActionList(), + data: await getActionListMock({ actionCount: 1, commands: ['get-file'] }), + }; + + render(); + const { getByTestId, queryByTestId } = renderResult; + + const expandButton = getByTestId(`${testPrefix}-expand-button`); + userEvent.click(expandButton); + const output = getByTestId(`${testPrefix}-details-tray-output`); + expect(output).toBeTruthy(); + expect(output.textContent).toEqual('get-file completed successfully'); + expect(queryByTestId(`${testPrefix}-getFileDownloadLink`)).toBeNull(); + }); + }); + + describe('`execute` action', () => { + it('should contain full output download link in expanded row for `execute` action WITH execute operation privilege', async () => { + useUserPrivilegesMock.mockReturnValue({ + endpointPrivileges: getEndpointAuthzInitialStateMock({ + canWriteExecuteOperations: true, + canWriteFileOperations: false, + }), + }); + const actionDetails = await getActionListMock({ actionCount: 1, commands: ['execute'] }); + mockUseGetEndpointActionList = { + ...getBaseMockedActionList(), + data: actionDetails, + }; + + mockUseGetFileInfo = { + isFetching: false, + error: null, + data: apiMocks.responseProvider.fileInfo(), + }; + + mockUseGetActionDetails = { + isFetching: false, + isFetched: true, + error: null, + data: { + ...apiMocks.responseProvider.actionDetails({ + path: `/api/endpoint/action/${actionDetails.data[0].id}`, + }), + data: { + ...apiMocks.responseProvider.actionDetails({ + path: `/api/endpoint/action/${actionDetails.data[0].id}`, + }).data, + outputs: { + [actionDetails.data[0].agents[0]]: { + content: {}, + type: 'json', + }, + }, + }, + }, + }; + + render(); + + const { getByTestId } = renderResult; + const expandButton = getByTestId(`${testPrefix}-expand-button`); + userEvent.click(expandButton); + + await waitFor(() => { + expect(apiMocks.responseProvider.fileInfo).toHaveBeenCalled(); + }); + + const downloadExecuteLink = getByTestId(`${testPrefix}-getExecuteLink`); + expect(downloadExecuteLink).toBeTruthy(); + expect(downloadExecuteLink.textContent).toEqual( + 'Click here to download full output(ZIP file passcode: elastic).Files are periodically deleted to clear storage space. Download and save file locally if needed.' + ); + }); + + it('should contain execute output and error for `execute` action WITH execute operation privilege', async () => { + const actionDetails = await getActionListMock({ actionCount: 1, commands: ['execute'] }); + mockUseGetEndpointActionList = { + ...getBaseMockedActionList(), + data: actionDetails, + }; + + mockUseGetFileInfo = { + isFetching: false, + error: null, + data: apiMocks.responseProvider.fileInfo(), + }; + + mockUseGetActionDetails = { + isFetching: false, + isFetched: true, + error: null, + data: { + data: { + ...apiMocks.responseProvider.actionDetails({ + path: `/api/endpoint/action/${actionDetails.data[0].id}`, + }).data, + outputs: { + [actionDetails.data[0].agents[0]]: { + content: {}, + type: 'json', + }, + }, + }, + }, + }; + + render(); + + const { getByTestId } = renderResult; + const expandButton = getByTestId(`${testPrefix}-expand-button`); + userEvent.click(expandButton); + + await waitFor(() => { + expect(apiMocks.responseProvider.fileInfo).toHaveBeenCalled(); + }); + + const executeAccordions = getByTestId(`${testPrefix}-executeResponseOutput`); + expect(executeAccordions).toBeTruthy(); + expect(executeAccordions).toHaveTextContent('Execution outputExecution error'); + }); + + it('should contain execute output for `execute` action WITHOUT execute operation privilege', async () => { + useUserPrivilegesMock.mockReturnValue({ + endpointPrivileges: getEndpointAuthzInitialStateMock({ + canWriteExecuteOperations: false, + }), + }); + mockUseGetEndpointActionList = { + ...getBaseMockedActionList(), + data: await getActionListMock({ actionCount: 1, commands: ['execute'] }), + }; + + render(); + + const { getByTestId } = renderResult; + const expandButton = getByTestId(`${testPrefix}-expand-button`); + userEvent.click(expandButton); + + const executeAccordions = getByTestId(`${testPrefix}-executeResponseOutput`); + expect(executeAccordions).toBeTruthy(); + }); + + it('should not contain full output download link in expanded row for `execute` action WITHOUT execute operation privilege', async () => { + useUserPrivilegesMock.mockReturnValue({ + endpointPrivileges: getEndpointAuthzInitialStateMock({ + canWriteExecuteOperations: false, + }), + }); + + mockUseGetEndpointActionList = { + ...getBaseMockedActionList(), + data: await getActionListMock({ actionCount: 1, commands: ['execute'] }), + }; + + render(); + const { getByTestId, queryByTestId } = renderResult; + + const expandButton = getByTestId(`${testPrefix}-expand-button`); + userEvent.click(expandButton); + expect(queryByTestId(`${testPrefix}-getExecuteLink`)).toBeNull(); + + const output = getByTestId(`${testPrefix}-details-tray-output`); + expect(output).toBeTruthy(); + expect(output.textContent).toContain('execute completed successfully'); + }); + }); }); describe('Action status ', () => { diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx index fc046ff574685..39601035250e9 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_log.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiBasicTable, EuiEmptyPrompt, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; +import { EuiEmptyPrompt, EuiFlexItem } from '@elastic/eui'; import type { CriteriaWithPagination } from '@elastic/eui'; import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; @@ -27,247 +27,244 @@ import { useActionHistoryUrlParams } from './components/use_action_history_url_p import { useUrlPagination } from '../../hooks/use_url_pagination'; import { ManagementPageLoader } from '../management_page_loader'; import { ActionsLogEmptyState } from './components/actions_log_empty_state'; -import { useResponseActionsLogTable } from './use_response_actions_log_table'; +import { ActionsLogTable } from './components/actions_log_table'; export const ResponseActionsLog = memo< Pick & { showHostNames?: boolean; isFlyout?: boolean; setIsDataInResponse?: (isData: boolean) => void; + 'data-test-subj'?: string; } ->(({ agentIds, showHostNames = false, isFlyout = true, setIsDataInResponse }) => { - const { pagination: paginationFromUrlParams, setPagination: setPaginationOnUrlParams } = - useUrlPagination(); - const { - commands: commandsFromUrl, - hosts: agentIdsFromUrl, - statuses: statusesFromUrl, - startDate: startDateFromUrl, - endDate: endDateFromUrl, - users: usersFromUrl, - } = useActionHistoryUrlParams(); +>( + ({ + agentIds, + showHostNames = false, + isFlyout = true, + setIsDataInResponse, + 'data-test-subj': dataTestSubj = 'response-actions-list', + }) => { + const { pagination: paginationFromUrlParams, setPagination: setPaginationOnUrlParams } = + useUrlPagination(); + const { + commands: commandsFromUrl, + hosts: agentIdsFromUrl, + statuses: statusesFromUrl, + startDate: startDateFromUrl, + endDate: endDateFromUrl, + users: usersFromUrl, + } = useActionHistoryUrlParams(); - const getTestId = useTestIdGenerator('response-actions-list'); + const getTestId = useTestIdGenerator(dataTestSubj); - // Used to decide if display global loader or not (only the fist time tha page loads) - const [isFirstAttempt, setIsFirstAttempt] = useState(true); + // Used to decide if display global loader or not (only the fist time tha page loads) + const [isFirstAttempt, setIsFirstAttempt] = useState(true); - const [queryParams, setQueryParams] = useState({ - page: isFlyout ? 1 : paginationFromUrlParams.page, - pageSize: isFlyout ? 10 : paginationFromUrlParams.pageSize, - agentIds: isFlyout ? agentIds : agentIdsFromUrl?.length ? agentIdsFromUrl : agentIds, - commands: [], - statuses: [], - userIds: [], - }); - - // update query state from URL params - useEffect(() => { - if (!isFlyout) { - setQueryParams((prevState) => ({ - ...prevState, - commands: commandsFromUrl?.length - ? commandsFromUrl.map((commandFromUrl) => getCommandKey(commandFromUrl)) - : prevState.commands, - hosts: agentIdsFromUrl?.length ? agentIdsFromUrl : prevState.agentIds, - statuses: statusesFromUrl?.length - ? (statusesFromUrl as ResponseActionStatus[]) - : prevState.statuses, - userIds: usersFromUrl?.length ? usersFromUrl : prevState.userIds, - })); - } - }, [commandsFromUrl, agentIdsFromUrl, isFlyout, statusesFromUrl, setQueryParams, usersFromUrl]); + const [queryParams, setQueryParams] = useState({ + page: isFlyout ? 1 : paginationFromUrlParams.page, + pageSize: isFlyout ? 10 : paginationFromUrlParams.pageSize, + agentIds: isFlyout ? agentIds : agentIdsFromUrl?.length ? agentIdsFromUrl : agentIds, + commands: [], + statuses: [], + userIds: [], + }); - // date range picker state and handlers - const { dateRangePickerState, onRefreshChange, onTimeChange } = useDateRangePicker(isFlyout); + // update query state from URL params + useEffect(() => { + if (!isFlyout) { + setQueryParams((prevState) => ({ + ...prevState, + commands: commandsFromUrl?.length + ? commandsFromUrl.map((commandFromUrl) => getCommandKey(commandFromUrl)) + : prevState.commands, + hosts: agentIdsFromUrl?.length ? agentIdsFromUrl : prevState.agentIds, + statuses: statusesFromUrl?.length + ? (statusesFromUrl as ResponseActionStatus[]) + : prevState.statuses, + userIds: usersFromUrl?.length ? usersFromUrl : prevState.userIds, + })); + } + }, [commandsFromUrl, agentIdsFromUrl, isFlyout, statusesFromUrl, setQueryParams, usersFromUrl]); - // initial fetch of list data - const { - error, - data: actionList, - isFetching, - isFetched, - refetch: reFetchEndpointActionList, - } = useGetEndpointActionList( - { - ...queryParams, - startDate: isFlyout ? dateRangePickerState.startDate : startDateFromUrl, - endDate: isFlyout ? dateRangePickerState.endDate : endDateFromUrl, - }, - { retry: false } - ); + // date range picker state and handlers + const { dateRangePickerState, onRefreshChange, onTimeChange } = useDateRangePicker(isFlyout); - // total actions - const totalItemCount = useMemo(() => actionList?.total ?? 0, [actionList]); + // initial fetch of list data + const { + error, + data: actionList, + isFetching, + isFetched, + refetch: reFetchEndpointActionList, + } = useGetEndpointActionList( + { + ...queryParams, + startDate: isFlyout ? dateRangePickerState.startDate : startDateFromUrl, + endDate: isFlyout ? dateRangePickerState.endDate : endDateFromUrl, + }, + { retry: false } + ); - // table columns and expanded row state - const { itemIdToExpandedRowMap, recordRangeLabel, responseActionListColumns, tablePagination } = - useResponseActionsLogTable({ - showHostNames, - pageIndex: isFlyout ? (queryParams.page || 1) - 1 : paginationFromUrlParams.page - 1, - pageSize: isFlyout ? queryParams.pageSize || 10 : paginationFromUrlParams.pageSize, - queryParams, - totalItemCount, - }); + // total actions + const totalItemCount = useMemo(() => actionList?.total ?? 0, [actionList]); + // table items + const tableItems = useMemo(() => actionList?.data ?? [], [actionList?.data]); - // Hide page header when there is no actions index calling the setIsDataInResponse with false value. - // Otherwise, it shows the page header calling the setIsDataInResponse with true value and it also keeps track - // if the API request was done for the first time. - useEffect(() => { - if ( - !isFetching && - error?.body?.statusCode === 404 && - error?.body?.message === 'index_not_found_exception' - ) { - if (setIsDataInResponse) { - setIsDataInResponse(false); - } - } else if (!isFetching && actionList) { - setIsFirstAttempt(false); - if (setIsDataInResponse) { - setIsDataInResponse(true); + // Hide page header when there is no actions index calling the setIsDataInResponse with false value. + // Otherwise, it shows the page header calling the setIsDataInResponse with true value and it also keeps track + // if the API request was done for the first time. + useEffect(() => { + if ( + !isFetching && + error?.body?.statusCode === 404 && + error?.body?.message === 'index_not_found_exception' + ) { + if (setIsDataInResponse) { + setIsDataInResponse(false); + } + } else if (!isFetching && actionList) { + setIsFirstAttempt(false); + if (setIsDataInResponse) { + setIsDataInResponse(true); + } } - } - }, [actionList, error, isFetching, setIsDataInResponse]); + }, [actionList, error, isFetching, setIsDataInResponse]); - // handle auto refresh data - const onRefresh = useCallback(() => { - if (dateRangePickerState.autoRefreshOptions.enabled) { - reFetchEndpointActionList(); - } - }, [dateRangePickerState.autoRefreshOptions.enabled, reFetchEndpointActionList]); + // handle auto refresh data + const onRefresh = useCallback(() => { + if (dateRangePickerState.autoRefreshOptions.enabled) { + reFetchEndpointActionList(); + } + }, [dateRangePickerState.autoRefreshOptions.enabled, reFetchEndpointActionList]); - // handle on change actions filter - const onChangeCommandsFilter = useCallback( - (selectedCommands: string[]) => { - setQueryParams((prevState) => ({ - ...prevState, - commands: selectedCommands as ResponseActionsApiCommandNames[], - })); - }, - [setQueryParams] - ); + // handle on change actions filter + const onChangeCommandsFilter = useCallback( + (selectedCommands: string[]) => { + setQueryParams((prevState) => ({ + ...prevState, + commands: selectedCommands as ResponseActionsApiCommandNames[], + })); + }, + [setQueryParams] + ); - // handle on change actions filter - const onChangeStatusesFilter = useCallback( - (selectedStatuses: string[]) => { - setQueryParams((prevState) => ({ - ...prevState, - statuses: selectedStatuses as ResponseActionStatus[], - })); - }, - [setQueryParams] - ); + // handle on change actions filter + const onChangeStatusesFilter = useCallback( + (selectedStatuses: string[]) => { + setQueryParams((prevState) => ({ + ...prevState, + statuses: selectedStatuses as ResponseActionStatus[], + })); + }, + [setQueryParams] + ); - // handle on change hosts filter - const onChangeHostsFilter = useCallback( - (selectedAgentIds: string[]) => { - setQueryParams((prevState) => ({ ...prevState, agentIds: selectedAgentIds })); - }, - [setQueryParams] - ); + // handle on change hosts filter + const onChangeHostsFilter = useCallback( + (selectedAgentIds: string[]) => { + setQueryParams((prevState) => ({ ...prevState, agentIds: selectedAgentIds })); + }, + [setQueryParams] + ); - // handle on change users filter - const onChangeUsersFilter = useCallback( - (selectedUserIds: string[]) => { - setQueryParams((prevState) => ({ ...prevState, userIds: selectedUserIds })); - }, - [setQueryParams] - ); + // handle on change users filter + const onChangeUsersFilter = useCallback( + (selectedUserIds: string[]) => { + setQueryParams((prevState) => ({ ...prevState, userIds: selectedUserIds })); + }, + [setQueryParams] + ); - // handle onChange - const handleTableOnChange = useCallback( - ({ page: _page }: CriteriaWithPagination) => { - // table paging is 0 based - const { index, size } = _page; - // adjust the page to conform to - // 1-based API page - const pagingArgs = { - page: index + 1, - pageSize: size, - }; + // handle onChange + const handleTableOnChange = useCallback( + ({ page: _page }: CriteriaWithPagination) => { + // table paging is 0 based + const { index, size } = _page; + // adjust the page to conform to + // 1-based API page + const pagingArgs = { + page: index + 1, + pageSize: size, + }; - setQueryParams((prevState) => ({ - ...prevState, - ...pagingArgs, - })); - if (!isFlyout) { - setPaginationOnUrlParams({ + setQueryParams((prevState) => ({ + ...prevState, ...pagingArgs, - }); - } - reFetchEndpointActionList(); - }, - [isFlyout, reFetchEndpointActionList, setQueryParams, setPaginationOnUrlParams] - ); + })); + if (!isFlyout) { + setPaginationOnUrlParams({ + ...pagingArgs, + }); + } + reFetchEndpointActionList(); + }, + [isFlyout, reFetchEndpointActionList, setQueryParams, setPaginationOnUrlParams] + ); - if (error?.body?.statusCode === 404 && error?.body?.message === 'index_not_found_exception') { - return ; - } else if (isFetching && isFirstAttempt) { - return ; - } - return ( - <> - - {isFetched && !totalItemCount ? ( - - - - - - } - body={ -

    - -

    - } - data-test-subj="responseActions-empty" - /> -
    -
    - ) : ( - <> - {recordRangeLabel} - - ; + } else if (isFetching && isFirstAttempt) { + return ; + } + return ( + <> + + {isFetched && !totalItemCount ? ( + + + + + + } + body={ +

    + +

    + } + data-test-subj="responseActions-empty" + /> +
    +
    + ) : ( + - - )} - - ); -}); + )} + + ); + } +); ResponseActionsLog.displayName = 'ResponseActionsLog'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx index 363da92a025bf..d185500612deb 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/translations.tsx @@ -180,3 +180,15 @@ export const FILTER_NAMES = Object.freeze({ defaultMessage: 'Filter by username', }), }); + +export const ARIA_LABELS = Object.freeze({ + collapse: i18n.translate( + 'xpack.securitySolution.responseActionsList.list.expandButton.collapse', + { + defaultMessage: 'Collapse', + } + ), + expand: i18n.translate('xpack.securitySolution.responseActionsList.list.expandButton.expand', { + defaultMessage: 'Expand', + }), +}); diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/use_response_actions_log_table.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/use_response_actions_log_table.tsx deleted file mode 100644 index 4ecd860a4876e..0000000000000 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/use_response_actions_log_table.tsx +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React, { useCallback, useMemo, useState } from 'react'; - -import { - EuiI18nNumber, - EuiAvatar, - EuiButtonIcon, - EuiCodeBlock, - EuiDescriptionList, - EuiFacetButton, - EuiFlexGroup, - EuiFlexItem, - RIGHT_ALIGNMENT, - EuiScreenReaderOnly, - EuiText, - EuiToolTip, - type HorizontalAlignment, -} from '@elastic/eui'; -import { css, euiStyled } from '@kbn/kibana-react-plugin/common'; -import { FormattedMessage } from '@kbn/i18n-react'; - -import type { ActionListApiResponse } from '../../../../common/endpoint/types'; -import type { EndpointActionListRequestQuery } from '../../../../common/endpoint/schema/actions'; -import { FormattedDate } from '../../../common/components/formatted_date'; -import { OUTPUT_MESSAGES, TABLE_COLUMN_NAMES, UX_MESSAGES } from './translations'; -import { getActionStatus, getUiCommand } from './components/hooks'; -import { getEmptyValue } from '../../../common/components/empty_value'; -import { StatusBadge } from './components/status_badge'; -import { useTestIdGenerator } from '../../hooks/use_test_id_generator'; -import { MANAGEMENT_PAGE_SIZE_OPTIONS } from '../../common/constants'; -import { ResponseActionFileDownloadLink } from '../response_action_file_download_link'; - -const emptyValue = getEmptyValue(); - -// Truncated usernames -const StyledFacetButton = euiStyled(EuiFacetButton)` - .euiText { - margin-top: 0.38rem; - overflow-y: visible !important; - } -`; - -const customDescriptionListCss = css` - &.euiDescriptionList { - > .euiDescriptionList__title { - color: ${(props) => props.theme.eui.euiColorDarkShade}; - font-size: ${(props) => props.theme.eui.euiFontSizeXS}; - } - - > .euiDescriptionList__title, - > .euiDescriptionList__description { - font-weight: ${(props) => props.theme.eui.euiFontWeightRegular}; - margin-top: ${(props) => props.theme.eui.euiSizeS}; - } - } -`; - -const StyledDescriptionList = euiStyled(EuiDescriptionList).attrs({ - compressed: true, - type: 'column', -})` - ${customDescriptionListCss} -`; - -// output section styles -const topSpacingCss = css` - ${(props) => `${props.theme.eui.euiSize} 0`} -`; -const dashedBorderCss = css` - ${(props) => `1px dashed ${props.theme.eui.euiColorDisabled}`}; -`; -const StyledDescriptionListOutput = euiStyled(EuiDescriptionList).attrs({ compressed: true })` - ${customDescriptionListCss} - dd { - margin: ${topSpacingCss}; - padding: ${topSpacingCss}; - border-top: ${dashedBorderCss}; - border-bottom: ${dashedBorderCss}; - } -`; - -// code block styles -const StyledEuiCodeBlock = euiStyled(EuiCodeBlock).attrs({ - transparentBackground: true, - paddingSize: 'none', -})` - code { - color: ${(props) => props.theme.eui.euiColorDarkShade} !important; - } -`; - -export const useResponseActionsLogTable = ({ - pageIndex, - pageSize, - queryParams, - showHostNames, - totalItemCount, -}: { - pageIndex: number; - pageSize: number; - queryParams: EndpointActionListRequestQuery; - showHostNames: boolean; - totalItemCount: number; -}) => { - const getTestId = useTestIdGenerator('response-actions-list'); - - const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<{ - [k: ActionListApiResponse['data'][number]['id']]: React.ReactNode; - }>({}); - - // expanded tray contents - const toggleDetails = useCallback( - (item: ActionListApiResponse['data'][number]) => { - const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; - if (itemIdToExpandedRowMapValues[item.id]) { - delete itemIdToExpandedRowMapValues[item.id]; - } else { - const { - startedAt, - completedAt, - isCompleted, - wasSuccessful, - isExpired, - command: _command, - comment, - parameters, - } = item; - - const parametersList = parameters - ? Object.entries(parameters).map(([key, value]) => { - return `${key}:${value}`; - }) - : undefined; - - const command = getUiCommand(_command); - const isGetFileCommand = command === 'get-file'; - const dataList = [ - { - title: OUTPUT_MESSAGES.expandSection.placedAt, - description: `${startedAt}`, - }, - { - title: OUTPUT_MESSAGES.expandSection.startedAt, - description: `${startedAt}`, - }, - { - title: OUTPUT_MESSAGES.expandSection.completedAt, - description: `${completedAt ?? emptyValue}`, - }, - { - title: OUTPUT_MESSAGES.expandSection.input, - description: `${command}`, - }, - { - title: OUTPUT_MESSAGES.expandSection.parameters, - description: parametersList ? parametersList : emptyValue, - }, - { - title: OUTPUT_MESSAGES.expandSection.comment, - description: comment ? comment : emptyValue, - }, - ].map(({ title, description }) => { - return { - title: {title}, - description: {description}, - }; - }); - - const getOutputContent = () => { - if (isExpired) { - return OUTPUT_MESSAGES.hasExpired(command); - } - - if (!isCompleted) { - return OUTPUT_MESSAGES.isPending(command); - } - - if (!wasSuccessful) { - return OUTPUT_MESSAGES.hasFailed(command); - } - - if (isGetFileCommand) { - return ( - <> - {OUTPUT_MESSAGES.wasSuccessful(command)} - - - ); - } - - return OUTPUT_MESSAGES.wasSuccessful(command); - }; - - const outputList = [ - { - title: ( - {`${OUTPUT_MESSAGES.expandSection.output}:`} - ), - description: ( - // codeblock for output - - {getOutputContent()} - - ), - }, - ]; - - itemIdToExpandedRowMapValues[item.id] = ( - <> - - - - - - - - - - ); - } - setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); - }, - [getTestId, itemIdToExpandedRowMap] - ); - // memoized callback for toggleDetails - const onClickCallback = useCallback( - (actionListDataItem: ActionListApiResponse['data'][number]) => () => - toggleDetails(actionListDataItem), - [toggleDetails] - ); - - const responseActionListColumns = useMemo(() => { - const columns = [ - { - field: 'startedAt', - name: TABLE_COLUMN_NAMES.time, - width: !showHostNames ? '21%' : '15%', - truncateText: true, - render: (startedAt: ActionListApiResponse['data'][number]['startedAt']) => { - return ( - - ); - }, - }, - { - field: 'command', - name: TABLE_COLUMN_NAMES.command, - width: !showHostNames ? '21%' : '10%', - truncateText: true, - render: (_command: ActionListApiResponse['data'][number]['command']) => { - const command = getUiCommand(_command); - return ( - - - {command} - - - ); - }, - }, - { - field: 'createdBy', - name: TABLE_COLUMN_NAMES.user, - width: !showHostNames ? '21%' : '14%', - truncateText: true, - render: (userId: ActionListApiResponse['data'][number]['createdBy']) => { - return ( - - } - > - - - {userId} - - - - ); - }, - }, - // conditional hostnames column - { - field: 'hosts', - name: TABLE_COLUMN_NAMES.hosts, - width: '20%', - truncateText: true, - render: (_hosts: ActionListApiResponse['data'][number]['hosts']) => { - const hosts = _hosts && Object.values(_hosts); - // join hostnames if the action is for multiple agents - // and skip empty strings for names if any - const _hostnames = hosts - .reduce((acc, host) => { - if (host.name.trim()) { - acc.push(host.name); - } - return acc; - }, []) - .join(', '); - - let hostnames = _hostnames; - if (!_hostnames) { - if (hosts.length > 1) { - // when action was for a single agent and no host name - hostnames = UX_MESSAGES.unenrolled.hosts; - } else if (hosts.length === 1) { - // when action was for a multiple agents - // and none of them have a host name - hostnames = UX_MESSAGES.unenrolled.host; - } - } - return ( - - - {hostnames} - - - ); - }, - }, - { - field: 'comment', - name: TABLE_COLUMN_NAMES.comments, - width: !showHostNames ? '21%' : '30%', - truncateText: true, - render: (comment: ActionListApiResponse['data'][number]['comment']) => { - return ( - - - {comment ?? emptyValue} - - - ); - }, - }, - { - field: 'status', - name: TABLE_COLUMN_NAMES.status, - width: !showHostNames ? '15%' : '10%', - render: (_status: ActionListApiResponse['data'][number]['status']) => { - const status = getActionStatus(_status); - - return ( - - - - ); - }, - }, - { - field: '', - align: RIGHT_ALIGNMENT as HorizontalAlignment, - width: '40px', - isExpander: true, - name: ( - - {UX_MESSAGES.screenReaderExpand} - - ), - render: (actionListDataItem: ActionListApiResponse['data'][number]) => { - return ( - - ); - }, - }, - ]; - // filter out the `hosts` column - // if showHostNames is FALSE - if (!showHostNames) { - return columns.filter((column) => column.field !== 'hosts'); - } - return columns; - }, [showHostNames, getTestId, itemIdToExpandedRowMap, onClickCallback]); - - // table pagination - const tablePagination = useMemo(() => { - return { - pageIndex, - pageSize, - totalItemCount, - pageSizeOptions: MANAGEMENT_PAGE_SIZE_OPTIONS as number[], - }; - }, [pageIndex, pageSize, totalItemCount]); - - // compute record ranges - const pagedResultsCount = useMemo(() => { - const page = queryParams.page ?? 1; - const perPage = queryParams?.pageSize ?? 10; - - const totalPages = Math.ceil(totalItemCount / perPage); - const fromCount = perPage * page - perPage + 1; - const toCount = - page === totalPages || totalPages === 1 ? totalItemCount : fromCount + perPage - 1; - return { fromCount, toCount }; - }, [queryParams.page, queryParams.pageSize, totalItemCount]); - - // create range label to display - const recordRangeLabel = useMemo( - () => ( - - - - {'-'} - - - ), - total: , - recordsLabel: {UX_MESSAGES.recordsLabel(totalItemCount)}, - }} - /> - - ), - [getTestId, pagedResultsCount.fromCount, pagedResultsCount.toCount, totalItemCount] - ); - - return { itemIdToExpandedRowMap, responseActionListColumns, recordRangeLabel, tablePagination }; -}; diff --git a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx index b212b884f77b8..e8a7d387ca0ba 100644 --- a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.test.tsx @@ -20,18 +20,11 @@ import { type ResponseActionFileDownloadLinkProps, } from './response_action_file_download_link'; import { responseActionsHttpMocks } from '../../mocks/response_actions_http_mocks'; -import { useUserPrivileges as _useUserPrivileges } from '../../../common/components/user_privileges'; import { getDeferred } from '../../mocks/utils'; import { waitFor } from '@testing-library/react'; import type { IHttpFetchError } from '@kbn/core-http-browser'; -jest.mock('../../../common/components/user_privileges'); - describe('When using the `ResponseActionFileDownloadLink` component', () => { - const useUserPrivilegesMock = _useUserPrivileges as jest.Mock< - ReturnType - >; - let render: () => ReturnType; let renderResult: ReturnType; let renderProps: ResponseActionFileDownloadLinkProps; @@ -48,6 +41,7 @@ describe('When using the `ResponseActionFileDownloadLink` component', () => { ResponseActionGetFileParameters >({ command: 'get-file' }), 'data-test-subj': 'test', + canAccessFileDownloadLink: true, }; render = () => { @@ -152,18 +146,8 @@ describe('When using the `ResponseActionFileDownloadLink` component', () => { }); }); - it('should show nothing if user does not have authz', () => { - const privileges = useUserPrivilegesMock(); - - useUserPrivilegesMock.mockImplementationOnce(() => { - return { - ...privileges, - endpointPrivileges: { - ...privileges.endpointPrivileges, - canWriteFileOperations: false, - }, - }; - }); + it('should show nothing if user does not have permission', () => { + renderProps.canAccessFileDownloadLink = false; render(); diff --git a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx index f17ac1a4b205f..c795bfc9bc191 100644 --- a/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx +++ b/x-pack/plugins/security_solution/public/management/components/response_action_file_download_link/response_action_file_download_link.tsx @@ -6,7 +6,7 @@ */ import React, { memo, useMemo, type CSSProperties } from 'react'; -import { EuiButtonEmpty, EuiLoadingContent, EuiText } from '@elastic/eui'; +import { EuiButtonEmpty, EuiSkeletonText, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import styled from 'styled-components'; @@ -14,7 +14,6 @@ import { getFileDownloadId } from '../../../../common/endpoint/service/response_ import { resolvePathVariables } from '../../../common/utils/resolve_path_variables'; import { FormattedError } from '../formatted_error'; import { useGetFileInfo } from '../../hooks/response_actions/use_get_file_info'; -import { useUserPrivileges } from '../../../common/components/user_privileges'; import { useTestIdGenerator } from '../../hooks/use_test_id_generator'; import type { MaybeImmutable } from '../../../../common/endpoint/types'; import type { ActionDetails } from '../../../../common/endpoint/types/actions'; @@ -45,6 +44,7 @@ export interface ResponseActionFileDownloadLinkProps { /** If left undefined, the first agent that the action was sent to will be used */ agentId?: string; buttonTitle?: string; + canAccessFileDownloadLink: boolean; 'data-test-subj'?: string; textSize?: 's' | 'xs'; } @@ -60,12 +60,12 @@ export const ResponseActionFileDownloadLink = memo { const action = _action as ActionDetails; // cast to remove `Immutable` const getTestId = useTestIdGenerator(dataTestSubj); - const { canWriteFileOperations } = useUserPrivileges().endpointPrivileges; const shouldFetchFileInfo: boolean = useMemo(() => { return action.isCompleted && action.wasSuccessful; @@ -83,15 +83,15 @@ export const ResponseActionFileDownloadLink = memo; + return ; } // Check if file is no longer available From a9313eefe0799d032e5176b1de8d3f1608e4e914 Mon Sep 17 00:00:00 2001 From: Kevin Qualters <56408403+kqualters-elastic@users.noreply.github.com> Date: Wed, 1 Mar 2023 13:07:05 -0500 Subject: [PATCH 094/131] [Security Solution] Analyzer with sysmon via filebeat (#152418) ## Summary Related issue: https://github.com/elastic/kibana/issues/148043 With the switch from beats to elastic agent, analyzer broke for sysmon data ingested via elastic agent, as some fields the code expects to exist became slightly different, this pr updates the frontend and server side api of analyzer to work with both old winlogbeat style sysmom ingestion and new elastic agent + filebeat shipping sysmon generated data. https://user-images.githubusercontent.com/56408403/222063497-64b2853e-5d09-4178-b336-1007886c396b.mov Video with 8.6 agent/fleet + latest main kibana/es + windows 10 w/sysmon vm ### 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 --- .../investigate_in_resolver.test.tsx | 22 ++++++++++++++++++ .../investigate_in_resolver.tsx | 23 ++++++++++++++----- .../entity/utils/supported_schemas.ts | 18 +++++++++++++++ .../routes/resolver/queries/events.ts | 1 + .../routes/resolver/utils/pagination.test.ts | 2 +- .../routes/resolver/utils/pagination.ts | 7 ++++-- 6 files changed, 64 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.test.tsx index 4695e19d77126..6e5c5472820a6 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.test.tsx @@ -57,5 +57,27 @@ describe('InvestigateInResolverAction', () => { expect(isInvestigateInResolverActionEnabled(data)).toBeFalsy(); }); + + it('returns true for process event from sysmon via filebeat', () => { + const data: Ecs = { + _id: '1', + agent: { type: ['filebeat'] }, + event: { dataset: ['windows.sysmon_operational'] }, + process: { entity_id: ['always_unique'] }, + }; + + expect(isInvestigateInResolverActionEnabled(data)).toBeTruthy(); + }); + + it('returns false for process event from filebeat but not from sysmon', () => { + const data: Ecs = { + _id: '1', + agent: { type: ['filebeat'] }, + event: { dataset: ['windows.not_sysmon'] }, + process: { entity_id: ['always_unique'] }, + }; + + expect(isInvestigateInResolverActionEnabled(data)).toBeFalsy(); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.tsx index 365aac96c8f48..f6b328a63b2c5 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/timeline_actions/investigate_in_resolver.tsx @@ -8,9 +8,20 @@ import { get } from 'lodash/fp'; import type { EcsSecurityExtension as Ecs } from '@kbn/securitysolution-ecs'; -export const isInvestigateInResolverActionEnabled = (ecsData?: Ecs) => - (get(['agent', 'type', 0], ecsData) === 'endpoint' || - (get(['agent', 'type', 0], ecsData) === 'winlogbeat' && - get(['event', 'module', 0], ecsData) === 'sysmon')) && - get(['process', 'entity_id'], ecsData)?.length === 1 && - get(['process', 'entity_id', 0], ecsData) !== ''; +export const isInvestigateInResolverActionEnabled = (ecsData?: Ecs) => { + const agentType = get(['agent', 'type', 0], ecsData); + const processEntityIds = get(['process', 'entity_id'], ecsData); + const firstProcessEntityId = get(['process', 'entity_id', 0], ecsData); + const eventModule = get(['event', 'module', 0], ecsData); + const eventDataStream = get(['event', 'dataset'], ecsData); + const datasetIncludesSysmon = + Array.isArray(eventDataStream) && + eventDataStream.some((datastream) => datastream.includes('windows.sysmon')); + const agentTypeIsEndpoint = agentType === 'endpoint'; + const agentTypeIsWinlogBeat = agentType === 'winlogbeat' && eventModule === 'sysmon'; + const isEndpointOrSysmonFromWinlogBeat = + agentTypeIsEndpoint || agentTypeIsWinlogBeat || datasetIncludesSysmon; + const hasProcessEntityId = + processEntityIds != null && processEntityIds.length === 1 && firstProcessEntityId !== ''; + return isEndpointOrSysmonFromWinlogBeat && hasProcessEntityId; +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity/utils/supported_schemas.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity/utils/supported_schemas.ts index 38f03c987ea34..788e7f3ae7713 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity/utils/supported_schemas.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/entity/utils/supported_schemas.ts @@ -63,6 +63,24 @@ export const supportedSchemas: SupportedSchema[] = [ name: 'process.name', }, }, + { + name: 'sysmonViaFilebeat', + constraints: [ + { + field: 'agent.type', + value: 'filebeat', + }, + { + field: 'event.dataset', + value: 'windows.sysmon_operational', + }, + ], + schema: { + id: 'process.entity_id', + parent: 'process.parent.entity_id', + name: 'process.name', + }, + }, ]; export function getFieldAsString(doc: unknown, field: string): string | undefined { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts index 869ae911ad890..bd0642702fc11 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/queries/events.ts @@ -86,6 +86,7 @@ export class EventsQuery extends BaseResolverQuery { return { body: this.query(filters), index: this.indexPatterns, + allow_partial_search_results: true, }; } diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts index a44be24ef2fca..c0b50798a822c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.test.ts @@ -61,7 +61,7 @@ describe('Pagination', () => { const builder = PaginationBuilder.createBuilder(100); expect(builder.buildQueryFields('a', 'desc').sort).toStrictEqual([ { '@timestamp': 'desc' }, - { a: 'asc' }, + { a: { order: 'asc', unmapped_type: 'long' } }, ]); }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts index 96086f1312f85..295d930ff24f5 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/utils/pagination.ts @@ -31,7 +31,7 @@ export type SortFields = [ { '@timestamp': string; }, - { [x: string]: string } + { [x: string]: { order: string; unmapped_type?: string } } ]; /** @@ -177,7 +177,10 @@ export class PaginationBuilder { tiebreaker: string, timeSort: TimeSortDirection = 'asc' ): PaginationFields { - const sort: SortFields = [{ '@timestamp': timeSort }, { [tiebreaker]: 'asc' }]; + const sort: SortFields = [ + { '@timestamp': timeSort }, + { [tiebreaker]: { order: 'asc', unmapped_type: 'long' } }, + ]; let searchAfter: SearchAfterFields | undefined; if (this.timestamp && this.eventID) { searchAfter = [this.timestamp, this.eventID]; From 647126aad47e4aa9ba919982aafb8cc6916bc3b6 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 1 Mar 2023 14:17:18 -0500 Subject: [PATCH 095/131] skip failing test suite (#152476) --- .../apps/dashboard/group2/dashboard_maps_by_value.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/dashboard/group2/dashboard_maps_by_value.ts b/x-pack/test/functional/apps/dashboard/group2/dashboard_maps_by_value.ts index 949aaa65008c5..9a65bd0f2f95f 100644 --- a/x-pack/test/functional/apps/dashboard/group2/dashboard_maps_by_value.ts +++ b/x-pack/test/functional/apps/dashboard/group2/dashboard_maps_by_value.ts @@ -76,7 +76,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.dashboard.clickNewDashboard(); } - describe('dashboard maps by value', function () { + // Failing: See https://github.com/elastic/kibana/issues/152476 + describe.skip('dashboard maps by value', function () { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await kibanaServer.importExport.load( From 5187a6f9aa706a94dbf759b12cc11940698a81b5 Mon Sep 17 00:00:00 2001 From: Alexi Doak <109488926+doakalexi@users.noreply.github.com> Date: Wed, 1 Mar 2023 15:19:38 -0500 Subject: [PATCH 096/131] [ResponseOps] Update flapping logic order to determine whether an alert is flapping after it's returned for notification (#151148) Resolves https://github.com/elastic/kibana/issues/151135 ## Summary Moved the logic around to check flapping after an alert is already returned for notification. I also updated the event log test cases to match examples in the rfc. ### 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 The new test cases capture this example but if you want to test it locally: - Create a connector and make sure to save the connector id ``` curl -X POST -u {username}:{password} "http://localhost:5601/api/actions/connector" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d' { "connector_type_id": ".server-log", "name": "server log", "config": {}, "secrets": {} }' ``` - Create the rule and let it run ``` curl -X POST -u {username}:{password} "http://localhost:5601/api/alerting/rule/" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d' { "rule_type_id": "example.pattern", "name": "pattern", "schedule": { "interval": "5s" }, "actions": [ { "group": "default", "id": {connector id}, "params": { "message": "{{alert.id}} active on run {{context.runs}} step {{context.patternIndex}} flapping {{alert.flapping}}"}}, { "group": "recovered", "id": {connector id}, "params": { "message": "{{alert.id}} recovered on run flapping {{alert.flapping}}"}} ], "consumer": "alerts", "tags": [], "notify_when": "onActionGroupChange", "params": { "patterns": { "instA": " a - - a - a - a - a - - - - - - - - " } } }' ``` - Verify that you see the following, we want to make sure that aren't missing any notifications ![image](https://user-images.githubusercontent.com/109488926/221615405-48061d10-4b80-4b98-812a-6951da4178da.png) --- .../legacy_alerts_client.test.ts | 15 +- .../alerts_client/legacy_alerts_client.ts | 14 +- .../server/task_runner/task_runner.ts | 2 + .../utils/create_lifecycle_executor.test.ts | 87 ++++++- .../server/utils/create_lifecycle_executor.ts | 15 +- .../tests/alerting/group1/event_log.ts | 215 +++++++++++++++--- .../tests/alerting/group4/event_log_alerts.ts | 2 +- 7 files changed, 276 insertions(+), 74 deletions(-) diff --git a/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts b/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts index 5da807ddba65d..3fb1877756d15 100644 --- a/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts +++ b/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.test.ts @@ -12,7 +12,7 @@ import { createAlertFactory, getPublicAlertFactory } from '../alert/create_alert import { Alert } from '../alert/alert'; import { alertingEventLoggerMock } from '../lib/alerting_event_logger/alerting_event_logger.mock'; import { ruleRunMetricsStoreMock } from '../lib/rule_run_metrics_store.mock'; -import { getAlertsForNotification, processAlerts, setFlapping } from '../lib'; +import { getAlertsForNotification, processAlerts } from '../lib'; import { logAlerts } from '../task_runner/log_alerts'; import { DEFAULT_FLAPPING_SETTINGS } from '../../common/rules_settings'; @@ -254,19 +254,6 @@ describe('Legacy Alerts Client', () => { flappingSettings: DEFAULT_FLAPPING_SETTINGS, }); - expect(setFlapping).toHaveBeenCalledWith( - { - enabled: true, - lookBackWindow: 20, - statusChangeThreshold: 4, - }, - { - '1': new Alert('1', testAlert1), - '2': new Alert('2', testAlert2), - }, - {} - ); - expect(getAlertsForNotification).toHaveBeenCalledWith( { enabled: true, diff --git a/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.ts b/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.ts index 9affe3a67d7eb..8fce6782cd2f1 100644 --- a/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.ts +++ b/x-pack/plugins/alerting/server/alerts_client/legacy_alerts_client.ts @@ -143,12 +143,6 @@ export class LegacyAlertsClient< flappingSettings, }); - setFlapping( - flappingSettings, - processedAlertsActive, - processedAlertsRecovered - ); - const { trimmedAlertsRecovered, earlyRecoveredAlerts } = trimRecoveredAlerts( this.options.logger, processedAlertsRecovered, @@ -213,4 +207,12 @@ export class LegacyAlertsClient< public getExecutorServices() { return getPublicAlertFactory(this.alertFactory!); } + + public setFlapping(flappingSettings: RulesSettingsFlappingProperties) { + setFlapping( + flappingSettings, + this.processedAlerts.active, + this.processedAlerts.recovered + ); + } } diff --git a/x-pack/plugins/alerting/server/task_runner/task_runner.ts b/x-pack/plugins/alerting/server/task_runner/task_runner.ts index a94512e1be483..82e01a93125e5 100644 --- a/x-pack/plugins/alerting/server/task_runner/task_runner.ts +++ b/x-pack/plugins/alerting/server/task_runner/task_runner.ts @@ -466,6 +466,8 @@ export class TaskRunner< } }); + this.legacyAlertsClient.setFlapping(flappingSettings); + let alertsToReturn: Record = {}; let recoveredAlertsToReturn: Record = {}; // Only serialize alerts into task state if we're auto-recovering, otherwise diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts index 2902533c145f1..8019e5bf3254a 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.test.ts @@ -1015,7 +1015,7 @@ describe('createLifecycleExecutor', () => { return { state }; }); - await executor( + const serializedAlerts = await executor( createDefaultAlertExecutorOptions({ alertId: 'TEST_ALERT_0', params: {}, @@ -1061,6 +1061,43 @@ describe('createLifecycleExecutor', () => { }) ); + expect(serializedAlerts.state.trackedAlerts).toEqual({ + TEST_ALERT_0: { + alertId: 'TEST_ALERT_0', + alertUuid: 'TEST_ALERT_0_UUID', + flapping: true, + flappingHistory: flapping.slice(1).concat([false]), + pendingRecoveredCount: 0, + started: '2020-01-01T12:00:00.000Z', + }, + TEST_ALERT_1: { + alertId: 'TEST_ALERT_1', + alertUuid: 'TEST_ALERT_1_UUID', + flapping: false, + flappingHistory: [false, false, false], + pendingRecoveredCount: 0, + started: '2020-01-02T12:00:00.000Z', + }, + TEST_ALERT_2: { + alertId: 'TEST_ALERT_2', + alertUuid: 'TEST_ALERT_2_UUID', + flapping: true, + flappingHistory: flapping.slice(1).concat([false]), + pendingRecoveredCount: 0, + started: '2020-01-01T12:00:00.000Z', + }, + TEST_ALERT_3: { + alertId: 'TEST_ALERT_3', + alertUuid: 'TEST_ALERT_3_UUID', + flapping: true, + flappingHistory: [false, false, false], + pendingRecoveredCount: 0, + started: '2020-01-02T12:00:00.000Z', + }, + }); + + expect(serializedAlerts.state.trackedAlertsRecovered).toEqual({}); + expect((await ruleDataClientMock.getWriter()).bulk).toHaveBeenCalledWith( expect.objectContaining({ body: [ @@ -1070,7 +1107,7 @@ describe('createLifecycleExecutor', () => { [ALERT_INSTANCE_ID]: 'TEST_ALERT_0', [ALERT_WORKFLOW_STATUS]: 'closed', [ALERT_STATUS]: ALERT_STATUS_ACTIVE, - [ALERT_FLAPPING]: true, + [ALERT_FLAPPING]: false, [EVENT_ACTION]: 'active', [EVENT_KIND]: 'signal', }), @@ -1182,7 +1219,7 @@ describe('createLifecycleExecutor', () => { return { state }; }); - await executor( + const serializedAlerts = await executor( createDefaultAlertExecutorOptions({ alertId: 'TEST_ALERT_0', params: {}, @@ -1228,6 +1265,44 @@ describe('createLifecycleExecutor', () => { }) ); + expect(serializedAlerts.state.trackedAlerts).toEqual({ + TEST_ALERT_2: { + alertId: 'TEST_ALERT_2', + alertUuid: 'TEST_ALERT_2_UUID', + flapping: true, + flappingHistory: [true, true, true], + pendingRecoveredCount: 1, + started: '2020-01-02T12:00:00.000Z', + }, + }); + + expect(serializedAlerts.state.trackedAlertsRecovered).toEqual({ + TEST_ALERT_0: { + alertId: 'TEST_ALERT_0', + alertUuid: 'TEST_ALERT_0_UUID', + flapping: true, + flappingHistory: [true, true, true, true, true], + pendingRecoveredCount: 0, + started: '2020-01-01T12:00:00.000Z', + }, + TEST_ALERT_1: { + alertId: 'TEST_ALERT_1', + alertUuid: 'TEST_ALERT_1_UUID', + flapping: false, + flappingHistory: notFlapping.slice(0, notFlapping.length - 1).concat([true]), + pendingRecoveredCount: 0, + started: '2020-01-02T12:00:00.000Z', + }, + TEST_ALERT_3: { + alertId: 'TEST_ALERT_3', + alertUuid: 'TEST_ALERT_3_UUID', + flapping: false, + flappingHistory: notFlapping.slice(0, notFlapping.length - 1).concat([true]), + pendingRecoveredCount: 0, + started: '2020-01-02T12:00:00.000Z', + }, + }); + expect((await ruleDataClientMock.getWriter()).bulk).toHaveBeenCalledWith( expect.objectContaining({ body: expect.arrayContaining([ @@ -1235,10 +1310,10 @@ describe('createLifecycleExecutor', () => { { index: { _id: 'TEST_ALERT_0_UUID' } }, expect.objectContaining({ [ALERT_INSTANCE_ID]: 'TEST_ALERT_0', - [ALERT_STATUS]: ALERT_STATUS_ACTIVE, - [EVENT_ACTION]: 'active', + [ALERT_STATUS]: ALERT_STATUS_RECOVERED, + [EVENT_ACTION]: 'close', [EVENT_KIND]: 'signal', - [ALERT_FLAPPING]: true, + [ALERT_FLAPPING]: false, }), { index: { _id: 'TEST_ALERT_1_UUID' } }, expect.objectContaining({ diff --git a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts index fdb73c85cecb1..c5387f66d000b 100644 --- a/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts +++ b/x-pack/plugins/rule_registry/server/utils/create_lifecycle_executor.ts @@ -278,12 +278,7 @@ export const createLifecycleExecutor = trackedAlertRecoveredIds ); - const { - alertUuid, - started, - flapping: isCurrentlyFlapping, - pendingRecoveredCount, - } = !isNew + const { alertUuid, started, flapping, pendingRecoveredCount } = !isNew ? state.trackedAlerts[alertId] : { alertUuid: lifecycleAlertServices.getAlertUuid(alertId), @@ -294,8 +289,6 @@ export const createLifecycleExecutor = pendingRecoveredCount: 0, }; - const flapping = isFlapping(flappingSettings, flappingHistory, isCurrentlyFlapping); - const event: ParsedTechnicalFields & ParsedExperimentalFields = { ...alertData?.fields, ...commonRuleFields, @@ -368,10 +361,11 @@ export const createLifecycleExecutor = const nextTrackedAlerts = Object.fromEntries( allEventsToIndex .filter(({ event }) => event[ALERT_STATUS] !== ALERT_STATUS_RECOVERED) - .map(({ event, flappingHistory, flapping, pendingRecoveredCount }) => { + .map(({ event, flappingHistory, flapping: isCurrentlyFlapping, pendingRecoveredCount }) => { const alertId = event[ALERT_INSTANCE_ID]!; const alertUuid = event[ALERT_UUID]!; const started = new Date(event[ALERT_START]!).toISOString(); + const flapping = isFlapping(flappingSettings, flappingHistory, isCurrentlyFlapping); return [ alertId, { alertId, alertUuid, started, flappingHistory, flapping, pendingRecoveredCount }, @@ -389,10 +383,11 @@ export const createLifecycleExecutor = event[ALERT_STATUS] === ALERT_STATUS_RECOVERED && (flapping || flappingHistory.filter((f: boolean) => f).length > 0) ) - .map(({ event, flappingHistory, flapping, pendingRecoveredCount }) => { + .map(({ event, flappingHistory, flapping: isCurrentlyFlapping, pendingRecoveredCount }) => { const alertId = event[ALERT_INSTANCE_ID]!; const alertUuid = event[ALERT_UUID]!; const started = new Date(event[ALERT_START]!).toISOString(); + const flapping = isFlapping(flappingSettings, flappingHistory, isCurrentlyFlapping); return [ alertId, { alertId, alertUuid, started, flappingHistory, flapping, pendingRecoveredCount }, 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 2ee65b9edc3e7..ac862b55aaadc 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 @@ -619,15 +619,15 @@ export default function eventLogTests({ getService }: FtrProviderContext) { }); }); - it('should generate expected events for flapping alerts that are mainly active', async () => { + it('should generate expected events for flapping alerts that settle on active', async () => { await supertest .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_flapping`) .set('kbn-xsrf', 'foo') .auth('superuser', 'superuser') .send({ enabled: true, - look_back_window: 3, - status_change_threshold: 2, + look_back_window: 6, + status_change_threshold: 4, }) .expect(200); const { body: createdAction } = await supertest @@ -642,7 +642,10 @@ export default function eventLogTests({ getService }: FtrProviderContext) { .expect(200); // pattern of when the alert should fire - const instance = [true, false, true, true, true, true, true]; + const instance = [true, false, false, true, false, true, false, true, false].concat( + ...new Array(8).fill(true), + false + ); const pattern = { instance, }; @@ -664,6 +667,11 @@ export default function eventLogTests({ getService }: FtrProviderContext) { group: 'default', params: {}, }, + { + id: createdAction.id, + group: 'recovered', + params: {}, + }, ], notify_when: RuleNotifyWhen.CHANGE, }) @@ -685,10 +693,10 @@ export default function eventLogTests({ getService }: FtrProviderContext) { // make sure the counts of the # of events per type are as expected ['execute-start', { gte: 6 }], ['execute', { gte: 6 }], - ['execute-action', { equal: 1 }], - ['new-instance', { equal: 1 }], + ['execute-action', { equal: 6 }], + ['new-instance', { equal: 3 }], ['active-instance', { gte: 6 }], - ['recovered-instance', { equal: 1 }], + ['recovered-instance', { equal: 3 }], ]), }); }); @@ -700,19 +708,24 @@ export default function eventLogTests({ getService }: FtrProviderContext) { event?.event?.action === 'recovered-instance' ) .map((event) => event?.kibana?.alert?.flapping); - const result = [false, true, true, true, false, false, false, false]; + const result = [false, false, false, false, false].concat( + new Array(9).fill(true), + false, + false, + false + ); expect(flapping).to.eql(result); }); - it('should generate expected events for flapping alerts that are mainly recovered', async () => { + it('should generate expected events for flapping alerts settle on recovered', async () => { await supertest .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_flapping`) .set('kbn-xsrf', 'foo') .auth('superuser', 'superuser') .send({ enabled: true, - look_back_window: 3, - status_change_threshold: 2, + look_back_window: 6, + status_change_threshold: 4, }) .expect(200); const { body: createdAction } = await supertest @@ -727,7 +740,9 @@ export default function eventLogTests({ getService }: FtrProviderContext) { .expect(200); // pattern of when the alert should fire - const instance = [true, false, true, false, false, false, true]; + const instance = [true, false, false, true, false, true, false, true, false, true].concat( + new Array(11).fill(false) + ); const pattern = { instance, }; @@ -749,6 +764,11 @@ export default function eventLogTests({ getService }: FtrProviderContext) { group: 'default', params: {}, }, + { + id: createdAction.id, + group: 'recovered', + params: {}, + }, ], notify_when: RuleNotifyWhen.CHANGE, }) @@ -770,10 +790,10 @@ export default function eventLogTests({ getService }: FtrProviderContext) { // make sure the counts of the # of events per type are as expected ['execute-start', { gte: 6 }], ['execute', { gte: 6 }], - ['execute-action', { equal: 2 }], - ['new-instance', { equal: 2 }], - ['active-instance', { gte: 6 }], - ['recovered-instance', { equal: 2 }], + ['execute-action', { equal: 6 }], + ['new-instance', { equal: 3 }], + ['active-instance', { gte: 3 }], + ['recovered-instance', { equal: 3 }], ]), }); }); @@ -785,18 +805,20 @@ export default function eventLogTests({ getService }: FtrProviderContext) { event?.event?.action === 'recovered-instance' ) .map((event) => event?.kibana?.alert?.flapping); - expect(flapping).to.eql([false, true, true, true, true, true, true, true]); + expect(flapping).to.eql( + [false, false, false, false, false].concat(new Array(8).fill(true)) + ); }); - it('should generate expected events for flapping alerts that are mainly active with notifyWhen not set to "on status change"', async () => { + it('should generate expected events for flapping alerts over a period of time longer than the look back', async () => { await supertest .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_flapping`) .set('kbn-xsrf', 'foo') .auth('superuser', 'superuser') .send({ enabled: true, - look_back_window: 3, - status_change_threshold: 2, + look_back_window: 5, + status_change_threshold: 5, }) .expect(200); const { body: createdAction } = await supertest @@ -811,7 +833,10 @@ export default function eventLogTests({ getService }: FtrProviderContext) { .expect(200); // pattern of when the alert should fire - const instance = [true, false, true, true, true, true, true]; + const instance = [true, false, false, true, false, true, false, true, false].concat( + ...new Array(8).fill(true), + false + ); const pattern = { instance, }; @@ -833,7 +858,13 @@ export default function eventLogTests({ getService }: FtrProviderContext) { group: 'default', params: {}, }, + { + id: createdAction.id, + group: 'recovered', + params: {}, + }, ], + notify_when: RuleNotifyWhen.CHANGE, }) ); @@ -851,12 +882,110 @@ export default function eventLogTests({ getService }: FtrProviderContext) { provider: 'alerting', actions: new Map([ // make sure the counts of the # of events per type are as expected - ['execute-start', { gte: 6 }], - ['execute', { gte: 6 }], - ['execute-action', { equal: 6 }], - ['new-instance', { equal: 1 }], + ['execute-start', { gte: 8 }], + ['execute', { gte: 8 }], + ['execute-action', { equal: 8 }], + ['new-instance', { equal: 4 }], + ['active-instance', { gte: 4 }], + ['recovered-instance', { equal: 4 }], + ]), + }); + }); + + const flapping = events + .filter( + (event) => + event?.event?.action === 'active-instance' || + event?.event?.action === 'recovered-instance' + ) + .map((event) => event?.kibana?.alert?.flapping); + const result = [false, false, false, false, false, false, false].concat( + new Array(6).fill(true), + false, + false, + false, + false + ); + expect(flapping).to.eql(result); + }); + + it('should generate expected events for flapping alerts that settle on active where notifyWhen is not set to "on status change"', async () => { + await supertest + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_flapping`) + .set('kbn-xsrf', 'foo') + .auth('superuser', 'superuser') + .send({ + enabled: true, + look_back_window: 6, + status_change_threshold: 4, + }) + .expect(200); + 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); + + // pattern of when the alert should fire + const instance = [true, false, false, true, false, true, false, true, false].concat( + ...new Array(8).fill(true), + false + ); + const pattern = { + instance, + }; + + const response = await supertest + .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send( + getTestRuleData({ + rule_type_id: 'test.patternFiring', + schedule: { interval: '1s' }, + throttle: null, + params: { + pattern, + }, + actions: [ + { + id: createdAction.id, + group: 'default', + params: {}, + }, + { + id: createdAction.id, + group: 'recovered', + params: {}, + }, + ], + }) + ); + + expect(response.status).to.eql(200); + const alertId = response.body.id; + objectRemover.add(space.id, alertId, 'rule', 'alerting'); + + // get the events we're expecting + const events = await retry.try(async () => { + return await getEventLog({ + getService, + spaceId: space.id, + type: 'alert', + id: alertId, + provider: 'alerting', + actions: new Map([ + // make sure the counts of the # of events per type are as expected + ['execute-start', { gte: 15 }], + ['execute', { gte: 15 }], + ['execute-action', { equal: 15 }], + ['new-instance', { equal: 3 }], ['active-instance', { gte: 6 }], - ['recovered-instance', { equal: 1 }], + ['recovered-instance', { equal: 3 }], ]), }); }); @@ -868,19 +997,24 @@ export default function eventLogTests({ getService }: FtrProviderContext) { event?.event?.action === 'recovered-instance' ) .map((event) => event?.kibana?.alert?.flapping); - const result = [false, true, true, false, false, false, false]; + const result = [false, false, false, false, false].concat( + new Array(7).fill(true), + false, + false, + false + ); expect(flapping).to.eql(result); }); - it('should generate expected events for flapping alerts that are mainly recovered with notifyWhen not set to "on status change"', async () => { + it('should generate expected events for flapping alerts that settle on recovered where notifyWhen is not set to "on status change"', async () => { await supertest .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/settings/_flapping`) .set('kbn-xsrf', 'foo') .auth('superuser', 'superuser') .send({ enabled: true, - look_back_window: 3, - status_change_threshold: 2, + look_back_window: 6, + status_change_threshold: 4, }) .expect(200); const { body: createdAction } = await supertest @@ -895,7 +1029,9 @@ export default function eventLogTests({ getService }: FtrProviderContext) { .expect(200); // pattern of when the alert should fire - const instance = [true, false, true, false, false, false, true]; + const instance = [true, false, false, true, false, true, false, true, false, true].concat( + new Array(11).fill(false) + ); const pattern = { instance, }; @@ -917,6 +1053,11 @@ export default function eventLogTests({ getService }: FtrProviderContext) { group: 'default', params: {}, }, + { + id: createdAction.id, + group: 'recovered', + params: {}, + }, ], }) ); @@ -935,12 +1076,12 @@ export default function eventLogTests({ getService }: FtrProviderContext) { provider: 'alerting', actions: new Map([ // make sure the counts of the # of events per type are as expected - ['execute-start', { gte: 5 }], - ['execute', { gte: 5 }], - ['execute-action', { equal: 3 }], - ['new-instance', { equal: 2 }], + ['execute-start', { gte: 8 }], + ['execute', { gte: 8 }], + ['execute-action', { equal: 8 }], + ['new-instance', { equal: 3 }], ['active-instance', { gte: 3 }], - ['recovered-instance', { equal: 2 }], + ['recovered-instance', { equal: 3 }], ]), }); }); @@ -952,7 +1093,7 @@ export default function eventLogTests({ getService }: FtrProviderContext) { event?.event?.action === 'recovered-instance' ) .map((event) => event?.kibana?.alert?.flapping); - expect(flapping).to.eql([false, true, true, true, true]); + expect(flapping).to.eql([false, false, false, false, false, true, true, true]); }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/event_log_alerts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/event_log_alerts.ts index 97ef276fef930..cc5f3108ddd54 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/event_log_alerts.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/event_log_alerts.ts @@ -132,7 +132,7 @@ export default function eventLogAlertTests({ getService }: FtrProviderContext) { break; } } - expect(flapping).to.eql(new Array(instanceEvents.length - 1).fill(false).concat([true])); + expect(flapping).to.eql(new Array(instanceEvents.length).fill(false)); }); }); } From 3de0009dd184d031c08fe5b3c3a4e7f56352b510 Mon Sep 17 00:00:00 2001 From: Kaarina Tungseth Date: Wed, 1 Mar 2023 14:28:19 -0600 Subject: [PATCH 097/131] [DOCS] Adds Visualizations features for 8.7 (#151045) ## Summary Adds the 8.7 docs for: - #149388 - #148829 - Closes #144590 - Replaces #144551 --- .../create-panels-with-editors.asciidoc | 18 +++++++++--------- ..._lineChartMetricOverTimeBottomAxis_8.3.png | Bin 36271 -> 0 bytes ..._lineChartMetricOverTimeBottomAxis_8.7.png | Bin 0 -> 49513 bytes ...ns_lineChartMetricOverTimeLeftAxis_8.3.png | Bin 51338 -> 0 bytes ...ns_lineChartMetricOverTimeLeftAxis_8.7.png | Bin 0 -> 56496 bytes docs/user/dashboard/lens.asciidoc | 2 +- ...create-a-dashboard-of-lens-panels.asciidoc | 4 ++-- docs/user/reporting/index.asciidoc | 16 ++++++++-------- 8 files changed, 20 insertions(+), 20 deletions(-) delete mode 100644 docs/user/dashboard/images/lens_lineChartMetricOverTimeBottomAxis_8.3.png create mode 100644 docs/user/dashboard/images/lens_lineChartMetricOverTimeBottomAxis_8.7.png delete mode 100644 docs/user/dashboard/images/lens_lineChartMetricOverTimeLeftAxis_8.3.png create mode 100644 docs/user/dashboard/images/lens_lineChartMetricOverTimeLeftAxis_8.7.png diff --git a/docs/user/dashboard/create-panels-with-editors.asciidoc b/docs/user/dashboard/create-panels-with-editors.asciidoc index ff61e03b381fe..9b55a86784636 100644 --- a/docs/user/dashboard/create-panels-with-editors.asciidoc +++ b/docs/user/dashboard/create-panels-with-editors.asciidoc @@ -62,7 +62,7 @@ | | Gauge and Goal -| +| ✓ | ✓ | ✓ | ✓ @@ -136,7 +136,7 @@ | ✓ | Synchronized tooltips -| +| ✓ | ✓ | | @@ -196,7 +196,7 @@ | | Annotations -| +| ✓ | ✓ | | @@ -256,11 +256,11 @@ | ✓ | <> -| +| Use <> | ✓ | Static value -| +| ✓ | ✓ |=== @@ -301,7 +301,7 @@ Metric aggregations are calculated from the values in the aggregated documents. | ✓ | Percentiles Rank -| +| ✓ | ✓ | ✓ | ✓ @@ -325,13 +325,13 @@ Metric aggregations are calculated from the values in the aggregated documents. | ✓ | Value count -| +| ✓ | | ✓ | ✓ | Variance -| +| ✓ | ✓ | | ✓ @@ -364,7 +364,7 @@ Bucket aggregations group, or bucket, documents based on the aggregation type. T | Date range | Use filters -| +| ✓ | ✓ | ✓ diff --git a/docs/user/dashboard/images/lens_lineChartMetricOverTimeBottomAxis_8.3.png b/docs/user/dashboard/images/lens_lineChartMetricOverTimeBottomAxis_8.3.png deleted file mode 100644 index 5a6cfb2bf740a720e2b0f4850d13b0562c228b7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36271 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

    rt0fT@+z#!m12q=lULPA3MLsdRf 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 G;Qs*$(^&!l diff --git a/docs/user/dashboard/images/lens_lineChartMetricOverTimeLeftAxis_8.7.png b/docs/user/dashboard/images/lens_lineChartMetricOverTimeLeftAxis_8.7.png new file mode 100644 index 0000000000000000000000000000000000000000..19b2d5121649103baef99ed5b3c040733b9e40cb GIT binary patch literal 56496 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�qzj<=TX{2lm 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 literal 0 HcmV?d00001 diff --git a/docs/user/dashboard/lens.asciidoc b/docs/user/dashboard/lens.asciidoc index ff6ffe230f7e7..eafe5cbf076c3 100644 --- a/docs/user/dashboard/lens.asciidoc +++ b/docs/user/dashboard/lens.asciidoc @@ -21,7 +21,7 @@ With *Lens*, you can: If you're unsure about the visualization type you want to use, or how you want to display the data, drag the fields you want to visualize onto the workspace, then let *Lens* choose for you. -If you already know the visualization type you want to use, and how you want to display the data, use the following process: +If you already know the visualization type you want to use, and how you want to display the data, use the following process. Choose the visualization type. diff --git a/docs/user/dashboard/tutorial-create-a-dashboard-of-lens-panels.asciidoc b/docs/user/dashboard/tutorial-create-a-dashboard-of-lens-panels.asciidoc index 0c183b91fc495..18b2b0a148154 100644 --- a/docs/user/dashboard/tutorial-create-a-dashboard-of-lens-panels.asciidoc +++ b/docs/user/dashboard/tutorial-create-a-dashboard-of-lens-panels.asciidoc @@ -130,12 +130,12 @@ To save space on the dashboard, hide the axis labels. . Open the *Left axis* menu, then select *None* from the *Axis title* dropdown. + [role="screenshot"] -image::images/lens_lineChartMetricOverTimeLeftAxis_8.3.png[Left axis menu] +image::images/lens_lineChartMetricOverTimeLeftAxis_8.7.png[Left axis menu] . Open the *Bottom axis* menu, then select *None* from the *Axis title* dropdown. + [role="screenshot"] -image::images/lens_lineChartMetricOverTimeBottomAxis_8.3.png[Bottom axis menu] +image::images/lens_lineChartMetricOverTimeBottomAxis_8.7.png[Bottom axis menu] . Click *Save and return* diff --git a/docs/user/reporting/index.asciidoc b/docs/user/reporting/index.asciidoc index a10c3a6ec8737..e85c46d04ed38 100644 --- a/docs/user/reporting/index.asciidoc +++ b/docs/user/reporting/index.asciidoc @@ -19,17 +19,17 @@ You access the options from the *Share* menu in the toolbar. The sharing options * *CSV Reports* — Generate and download a CSV file of a *Discover* saved search. -* *Permalinks* — Share a direct link to a *Discover* saved search, dashboard, or visualization. +* *Get links* — Share a direct link to a *Discover* saved search, dashboard, or visualization. * *Download as JSON* — Generate and download a JSON file of a *Canvas* workpad. * beta[] *Share on a website* — Download and securely share *Canvas* workpads on any website. -* *Embed code* — Embed a fully interactive dashboard or visualization as an iframe on a web page. +* *Embed code* — Embed a fully interactive dashboard as an iframe on a web page. [[reporting-on-cloud-resource-requirements]] -NOTE: For Elastic Cloud deployments, Kibana instances require a minimum of 2GB RAM to generate PDF or PNG reports. To -change Kibana sizing, {ess-console}[edit the deployment]. +NOTE: For Elastic Cloud deployments, {kib} instances require a minimum of 2GB RAM to generate PDF or PNG reports. To +change {kib} sizing, {ess-console}[edit the deployment]. [float] [[manually-generate-reports]] @@ -84,7 +84,7 @@ Share a direct link to a saved search, dashboard, or visualization. To access th . Open the main menu, then open the saved search, dashboard, or visualization you want to share. -. From the toolbar, click *Share*, then select *Permalinks*. +. From the toolbar, click *Share*, then select *Get links*. . Specify how you want to generate the link: @@ -142,11 +142,11 @@ NOTE: Shareable workpads encode the current state of the workpad in a JSON file. [[embed-code]] == Embed code -Display your dashboard or visualization on an internal company website or personal web page with an iframe. Embedding other {kib} objects is generally supported, but you might need to manually craft the proper HTML code. +Display your dashboard on an internal company website or personal web page with an iframe. Embedding other {kib} objects is generally supported, but you might need to manually craft the proper HTML code. Some users might not have access to the dashboard or visualization. For more information, refer to <> and <>. -. Open the main menu, then open the dashboard or visualization you want to share. +. Open the main menu, then open the dashboard you want to share. . Click *Share > Embed code*. @@ -156,7 +156,7 @@ Some users might not have access to the dashboard or visualization. For more inf * To display up-to-date changes, select *Saved object*. -* Select the dashboard or visualization elements you want to include. +* Select the dashboard components you want to include. * To generate a shortened link, select *Short URL*. From 72868e2ae1cb2ba8bd6e26783ee4327baddceeb3 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 1 Mar 2023 13:34:23 -0700 Subject: [PATCH 098/131] [canvas] unskip Jest Tests.x-pack/plugins/canvas/shareable_runtime/components (#152401) Fixes https://github.com/elastic/kibana/issues/95899 unskips test. There is no flaky test runner for jest. --- .../components/__snapshots__/app.test.tsx.snap | 10 +--------- .../canvas/shareable_runtime/components/app.test.tsx | 3 +-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap b/x-pack/plugins/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap index 5c431dee43fe6..f9583adaa84c7 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap +++ b/x-pack/plugins/canvas/shareable_runtime/components/__snapshots__/app.test.tsx.snap @@ -1,11 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` App renders properly 1`] = ` -"

    markdown mock
    markdown mock
    My Canvas Workpad
    " -`; +exports[` App renders properly 1`] = `"
    markdown mock
    markdown mock
    My Canvas Workpad
    "`; diff --git a/x-pack/plugins/canvas/shareable_runtime/components/app.test.tsx b/x-pack/plugins/canvas/shareable_runtime/components/app.test.tsx index b68642d184542..acf71cad3f3ba 100644 --- a/x-pack/plugins/canvas/shareable_runtime/components/app.test.tsx +++ b/x-pack/plugins/canvas/shareable_runtime/components/app.test.tsx @@ -59,8 +59,7 @@ const getWrapper: (name?: WorkpadNames) => ReactWrapper = (name = 'hello') => { return mount(); }; -// FLAKY: https://github.com/elastic/kibana/issues/95899 -describe.skip('', () => { +describe('', () => { test('App renders properly', () => { expect(getWrapper().html()).toMatchSnapshot(); }); From 4eefb9ec3040c1f80fb4c0e9a32c43497dc71681 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau Date: Wed, 1 Mar 2023 15:35:29 -0500 Subject: [PATCH 099/131] [RAM] Uptime allow rac api in read (#152475) ## Summary Allow `rac` api in read for uptime privileges and to avoid that image --- x-pack/plugins/synthetics/server/feature.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/synthetics/server/feature.ts b/x-pack/plugins/synthetics/server/feature.ts index 4026bbdb19fb9..908d6e6f1f9fa 100644 --- a/x-pack/plugins/synthetics/server/feature.ts +++ b/x-pack/plugins/synthetics/server/feature.ts @@ -57,7 +57,7 @@ export const uptimeFeature = { read: { app: ['uptime', 'kibana', 'synthetics'], catalogue: ['uptime'], - api: ['uptime-read', 'lists-read'], + api: ['uptime-read', 'lists-read', 'rac'], savedObject: { all: [], read: [ From d4abfa28a89de4c97334ccde98405f28eab74a49 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Wed, 1 Mar 2023 22:33:18 +0100 Subject: [PATCH 100/131] [Saved Object Finder] Move to the component in saved_objects_finder plugin (#151764) ## Summary This PR replaces the `SavedObjectsFinder` component from `saved_objects` plugin with the one in `saved_objects_finder` plugin. Code changes are pretty straightforward; most of the changes are around modifying the functional tests to work with the selectors from the new component. ### 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 ~- [ ] 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> --- src/plugins/dashboard/kibana.jsonc | 2 + .../public/dashboard_actions/index.ts | 6 +- .../embeddable/api/add_panel_from_library.ts | 9 ++- src/plugins/dashboard/public/plugin.tsx | 2 + .../public/services/plugin_services.stub.ts | 2 + .../public/services/plugin_services.ts | 2 + .../saved_objects_management_service.stub.ts | 17 +++++ .../saved_objects_management_service.ts | 24 +++++++ .../dashboard/public/services/types.ts | 2 + src/plugins/dashboard/tsconfig.json | 2 + src/plugins/embeddable/kibana.jsonc | 4 +- src/plugins/embeddable/public/mocks.tsx | 23 ++++++ src/plugins/embeddable/public/plugin.tsx | 12 +++- .../embeddable/public/tests/test_plugin.ts | 25 ++++++- src/plugins/embeddable/tsconfig.json | 3 + src/plugins/saved_objects_finder/kibana.jsonc | 4 +- .../public/finder/index.tsx | 18 +++++ .../public/finder/saved_object_finder.tsx | 47 ++++++------ .../saved_objects_finder/public/index.ts | 2 +- .../saved_objects_finder/tsconfig.json | 2 + test/examples/embeddables/adding_children.ts | 25 ++++++- .../dashboard/group2/embeddable_library.ts | 5 +- .../apps/dashboard/group3/panel_replacing.ts | 2 +- .../services/dashboard/add_panel.ts | 54 +++++--------- .../services/dashboard/replace_panel.ts | 18 +---- test/functional/services/index.ts | 2 + .../services/saved_objects_finder.ts | 71 +++++++++++++++++++ x-pack/plugins/canvas/kibana.jsonc | 10 +-- .../embeddable_flyout/flyout.component.tsx | 13 ++-- x-pack/plugins/canvas/public/plugin.tsx | 2 + .../canvas/public/services/kibana/platform.ts | 1 + .../canvas/public/services/platform.ts | 2 + .../canvas/public/services/stubs/platform.ts | 1 + x-pack/plugins/canvas/tsconfig.json | 3 +- 34 files changed, 310 insertions(+), 107 deletions(-) create mode 100644 src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.stub.ts create mode 100644 src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.ts create mode 100644 test/functional/services/saved_objects_finder.ts diff --git a/src/plugins/dashboard/kibana.jsonc b/src/plugins/dashboard/kibana.jsonc index ae5194d662c2b..aba26ca66ed7d 100644 --- a/src/plugins/dashboard/kibana.jsonc +++ b/src/plugins/dashboard/kibana.jsonc @@ -16,6 +16,8 @@ "inspector", "navigation", "savedObjects", + "savedObjectsFinder", + "savedObjectsManagement", "share", "screenshotMode", "uiActions", diff --git a/src/plugins/dashboard/public/dashboard_actions/index.ts b/src/plugins/dashboard/public/dashboard_actions/index.ts index 652b66b2ad195..199854710f1f2 100644 --- a/src/plugins/dashboard/public/dashboard_actions/index.ts +++ b/src/plugins/dashboard/public/dashboard_actions/index.ts @@ -8,7 +8,7 @@ import { CONTEXT_MENU_TRIGGER, PANEL_NOTIFICATION_TRIGGER } from '@kbn/embeddable-plugin/public'; import { CoreStart } from '@kbn/core/public'; -import { getSavedObjectFinder } from '@kbn/saved-objects-plugin/public'; +import { getSavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public'; import { ExportCSVAction } from './export_csv_action'; import { ClonePanelAction } from './clone_panel_action'; @@ -33,13 +33,13 @@ export const buildAllDashboardActions = async ({ allowByValueEmbeddables, }: BuildAllDashboardActionsProps) => { const { uiSettings } = core; - const { uiActions, share, presentationUtil } = plugins; + const { uiActions, share, presentationUtil, savedObjectsManagement } = plugins; const clonePanelAction = new ClonePanelAction(core.savedObjects); uiActions.registerAction(clonePanelAction); uiActions.attachAction(CONTEXT_MENU_TRIGGER, clonePanelAction.id); - const SavedObjectFinder = getSavedObjectFinder(uiSettings, core.http); + const SavedObjectFinder = getSavedObjectFinder(uiSettings, core.http, savedObjectsManagement); const changeViewAction = new ReplacePanelAction(SavedObjectFinder); uiActions.registerAction(changeViewAction); uiActions.attachAction(CONTEXT_MENU_TRIGGER, changeViewAction.id); diff --git a/src/plugins/dashboard/public/dashboard_container/embeddable/api/add_panel_from_library.ts b/src/plugins/dashboard/public/dashboard_container/embeddable/api/add_panel_from_library.ts index 79a3caeafba17..06389afc2a576 100644 --- a/src/plugins/dashboard/public/dashboard_container/embeddable/api/add_panel_from_library.ts +++ b/src/plugins/dashboard/public/dashboard_container/embeddable/api/add_panel_from_library.ts @@ -8,7 +8,7 @@ import { HttpStart } from '@kbn/core/public'; import { isErrorEmbeddable, openAddPanelFlyout } from '@kbn/embeddable-plugin/public'; -import { getSavedObjectFinder } from '@kbn/saved-objects-plugin/public'; +import { getSavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public'; import { pluginServices } from '../../../services/plugin_services'; import { DashboardContainer } from '../dashboard_container'; @@ -21,12 +21,17 @@ export function addFromLibrary(this: DashboardContainer) { settings: { uiSettings, theme }, embeddable: { getEmbeddableFactories, getEmbeddableFactory }, http, + savedObjectsManagement, } = pluginServices.getServices(); if (isErrorEmbeddable(this)) return; this.openOverlay( openAddPanelFlyout({ - SavedObjectFinder: getSavedObjectFinder(uiSettings, http as HttpStart), + SavedObjectFinder: getSavedObjectFinder( + uiSettings, + http as HttpStart, + savedObjectsManagement + ), reportUiCounter: usageCollection.reportUiCounter, getAllFactories: getEmbeddableFactories, getFactory: getEmbeddableFactory, diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index cb13afd4aabf7..3c4031072ca92 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -50,6 +50,7 @@ import type { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public'; import { CustomBrandingStart } from '@kbn/core-custom-branding-browser'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { DashboardContainerFactoryDefinition } from './dashboard_container/embeddable/dashboard_container_factory'; import { type DashboardAppLocator, @@ -90,6 +91,7 @@ export interface DashboardStartDependencies { presentationUtil: PresentationUtilPluginStart; savedObjects: SavedObjectsStart; savedObjectsClient: SavedObjectsClientContract; + savedObjectsManagement: SavedObjectsManagementPluginStart; savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart; screenshotMode: ScreenshotModePluginStart; share?: SharePluginStart; diff --git a/src/plugins/dashboard/public/services/plugin_services.stub.ts b/src/plugins/dashboard/public/services/plugin_services.stub.ts index eabe85288687a..f0ec4a91f3fd6 100644 --- a/src/plugins/dashboard/public/services/plugin_services.stub.ts +++ b/src/plugins/dashboard/public/services/plugin_services.stub.ts @@ -39,6 +39,7 @@ import { urlForwardingServiceFactory } from './url_forwarding/url_fowarding.stub import { visualizationsServiceFactory } from './visualizations/visualizations.stub'; import { dashboardSavedObjectServiceFactory } from './dashboard_saved_object/dashboard_saved_object.stub'; import { customBrandingServiceFactory } from './custom_branding/custom_branding.stub'; +import { savedObjectsManagementServiceFactory } from './saved_objects_management/saved_objects_management_service.stub'; export const providers: PluginServiceProviders = { dashboardSavedObject: new PluginServiceProvider(dashboardSavedObjectServiceFactory), @@ -66,6 +67,7 @@ export const providers: PluginServiceProviders = { usageCollection: new PluginServiceProvider(usageCollectionServiceFactory), visualizations: new PluginServiceProvider(visualizationsServiceFactory), customBranding: new PluginServiceProvider(customBrandingServiceFactory), + savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory), }; export const registry = new PluginServiceRegistry(providers); diff --git a/src/plugins/dashboard/public/services/plugin_services.ts b/src/plugins/dashboard/public/services/plugin_services.ts index 4382506a37948..599eb6a5b7249 100644 --- a/src/plugins/dashboard/public/services/plugin_services.ts +++ b/src/plugins/dashboard/public/services/plugin_services.ts @@ -40,6 +40,7 @@ import { usageCollectionServiceFactory } from './usage_collection/usage_collecti import { analyticsServiceFactory } from './analytics/analytics_service'; import { dashboardSavedObjectServiceFactory } from './dashboard_saved_object/dashboard_saved_object_service'; import { customBrandingServiceFactory } from './custom_branding/custom_branding_service'; +import { savedObjectsManagementServiceFactory } from './saved_objects_management/saved_objects_management_service'; const providers: PluginServiceProviders = { dashboardSavedObject: new PluginServiceProvider(dashboardSavedObjectServiceFactory, [ @@ -80,6 +81,7 @@ const providers: PluginServiceProviders(); diff --git a/src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.stub.ts b/src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.stub.ts new file mode 100644 index 0000000000000..b5ea444e702a8 --- /dev/null +++ b/src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.stub.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { PluginServiceFactory } from '@kbn/presentation-util-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; +import { savedObjectsManagementPluginMock } from '@kbn/saved-objects-management-plugin/public/mocks'; + +type SavedObjectsManagementServiceFactory = PluginServiceFactory; + +export const savedObjectsManagementServiceFactory: SavedObjectsManagementServiceFactory = () => { + return savedObjectsManagementPluginMock.createStartContract(); +}; diff --git a/src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.ts b/src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.ts new file mode 100644 index 0000000000000..271a056948687 --- /dev/null +++ b/src/plugins/dashboard/public/services/saved_objects_management/saved_objects_management_service.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { KibanaPluginServiceFactory } from '@kbn/presentation-util-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; +import { DashboardStartDependencies } from '../../plugin'; + +export type SavedObjectsManagementServiceFactory = KibanaPluginServiceFactory< + SavedObjectsManagementPluginStart, + DashboardStartDependencies +>; + +export const savedObjectsManagementServiceFactory: SavedObjectsManagementServiceFactory = ({ + startPlugins, +}) => { + const { savedObjectsManagement } = startPlugins; + + return savedObjectsManagement; +}; diff --git a/src/plugins/dashboard/public/services/types.ts b/src/plugins/dashboard/public/services/types.ts index fc7e0acf1b5c4..1992cd83d4b6d 100644 --- a/src/plugins/dashboard/public/services/types.ts +++ b/src/plugins/dashboard/public/services/types.ts @@ -8,6 +8,7 @@ import { PluginInitializerContext } from '@kbn/core/public'; import { KibanaPluginServiceParams } from '@kbn/presentation-util-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { DashboardStartDependencies } from '../plugin'; import { DashboardAnalyticsService } from './analytics/types'; @@ -66,4 +67,5 @@ export interface DashboardServices { usageCollection: DashboardUsageCollectionService; // TODO: make this optional in follow up visualizations: DashboardVisualizationsService; customBranding: DashboardCustomBrandingService; + savedObjectsManagement: SavedObjectsManagementPluginStart; } diff --git a/src/plugins/dashboard/tsconfig.json b/src/plugins/dashboard/tsconfig.json index 17ec86d25e6ef..4bfb899c5301d 100644 --- a/src/plugins/dashboard/tsconfig.json +++ b/src/plugins/dashboard/tsconfig.json @@ -53,6 +53,8 @@ "@kbn/core-execution-context-common", "@kbn/core-custom-branding-browser", "@kbn/shared-ux-router", + "@kbn/saved-objects-finder-plugin", + "@kbn/saved-objects-management-plugin", "@kbn/shared-ux-button-toolbar", ], "exclude": [ diff --git a/src/plugins/embeddable/kibana.jsonc b/src/plugins/embeddable/kibana.jsonc index 89aa3e41026a6..b7a164b459d77 100644 --- a/src/plugins/embeddable/kibana.jsonc +++ b/src/plugins/embeddable/kibana.jsonc @@ -10,7 +10,9 @@ "requiredPlugins": [ "data", "inspector", - "uiActions" + "uiActions", + "savedObjectsFinder", + "savedObjectsManagement" ], "requiredBundles": [ "savedObjects", diff --git a/src/plugins/embeddable/public/mocks.tsx b/src/plugins/embeddable/public/mocks.tsx index 25ccb141cd356..478845cf66f6d 100644 --- a/src/plugins/embeddable/public/mocks.tsx +++ b/src/plugins/embeddable/public/mocks.tsx @@ -14,6 +14,11 @@ import { type AggregateQuery, type Filter, type Query } from '@kbn/es-query'; import { inspectorPluginMock } from '@kbn/inspector-plugin/public/mocks'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; +import { + SavedObjectManagementTypeInfo, + SavedObjectsManagementPluginStart, +} from '@kbn/saved-objects-management-plugin/public'; +import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import { UiActionsService } from './lib/ui_actions'; import { EmbeddablePublicPlugin } from './plugin'; import { @@ -156,10 +161,28 @@ const createInstance = (setupPlugins: Partial = {}) const setup = plugin.setup(coreMock.createSetup(), { uiActions: setupPlugins.uiActions || uiActionsPluginMock.createSetupContract(), }); + const savedObjectsManagementMock = { + parseQuery: (query: Query, types: SavedObjectManagementTypeInfo[]) => { + return { + queryText: 'some search', + }; + }, + getTagFindReferences: ({ + selectedTags, + taggingApi, + }: { + selectedTags?: string[]; + taggingApi?: SavedObjectsTaggingApi; + }) => { + return undefined; + }, + }; const doStart = (startPlugins: Partial = {}) => plugin.start(coreMock.createStart(), { uiActions: startPlugins.uiActions || uiActionsPluginMock.createStartContract(), inspector: inspectorPluginMock.createStartContract(), + savedObjectsManagement: + savedObjectsManagementMock as unknown as SavedObjectsManagementPluginStart, }); return { plugin, diff --git a/src/plugins/embeddable/public/plugin.tsx b/src/plugins/embeddable/public/plugin.tsx index 1ea92fe129ccf..b064ae3f77592 100644 --- a/src/plugins/embeddable/public/plugin.tsx +++ b/src/plugins/embeddable/public/plugin.tsx @@ -11,7 +11,7 @@ import { Subscription } from 'rxjs'; import { identity } from 'lodash'; import { UI_SETTINGS } from '@kbn/data-plugin/public'; import type { SerializableRecord } from '@kbn/utility-types'; -import { getSavedObjectFinder } from '@kbn/saved-objects-plugin/public'; +import { getSavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public'; import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { Start as InspectorStart } from '@kbn/inspector-plugin/public'; import { @@ -23,6 +23,7 @@ import { } from '@kbn/core/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; import { migrateToLatest, PersistableStateService } from '@kbn/kibana-utils-plugin/common'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { EmbeddableFactoryRegistry, EmbeddableFactoryProvider, @@ -64,6 +65,7 @@ export interface EmbeddableSetupDependencies { export interface EmbeddableStartDependencies { uiActions: UiActionsStart; inspector: InspectorStart; + savedObjectsManagement: SavedObjectsManagementPluginStart; } export interface EmbeddableSetup { @@ -143,7 +145,7 @@ export class EmbeddablePublicPlugin implements Plugin { this.embeddableFactories.set( @@ -207,7 +209,11 @@ export class EmbeddablePublicPlugin implements Plugin diff --git a/src/plugins/embeddable/public/tests/test_plugin.ts b/src/plugins/embeddable/public/tests/test_plugin.ts index 6587d42dfda12..09412d973ec78 100644 --- a/src/plugins/embeddable/public/tests/test_plugin.ts +++ b/src/plugins/embeddable/public/tests/test_plugin.ts @@ -11,8 +11,13 @@ import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import { inspectorPluginMock } from '@kbn/inspector-plugin/public/mocks'; import { coreMock } from '@kbn/core/public/mocks'; +import { + SavedObjectManagementTypeInfo, + SavedObjectsManagementPluginStart, +} from '@kbn/saved-objects-management-plugin/public'; +import { Query } from '@kbn/es-query'; +import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import { EmbeddablePublicPlugin, EmbeddableSetup, EmbeddableStart } from '../plugin'; - export interface TestPluginReturn { plugin: EmbeddablePublicPlugin; coreSetup: CoreSetup; @@ -32,6 +37,22 @@ export const testPlugin = ( const setup = plugin.setup(coreSetup, { uiActions: uiActions.setup, }); + const savedObjectsManagementMock = { + parseQuery: (query: Query, types: SavedObjectManagementTypeInfo[]) => { + return { + queryText: 'some search', + }; + }, + getTagFindReferences: ({ + selectedTags, + taggingApi, + }: { + selectedTags?: string[]; + taggingApi?: SavedObjectsTaggingApi; + }) => { + return undefined; + }, + }; return { plugin, @@ -42,6 +63,8 @@ export const testPlugin = ( const start = plugin.start(anotherCoreStart, { inspector: inspectorPluginMock.createStartContract(), uiActions: uiActionsPluginMock.createStartContract(), + savedObjectsManagement: + savedObjectsManagementMock as unknown as SavedObjectsManagementPluginStart, }); return start; }, diff --git a/src/plugins/embeddable/tsconfig.json b/src/plugins/embeddable/tsconfig.json index 67102414915d9..6f8a146187b2a 100644 --- a/src/plugins/embeddable/tsconfig.json +++ b/src/plugins/embeddable/tsconfig.json @@ -30,6 +30,9 @@ "@kbn/data-plugin", "@kbn/core-overlays-browser-mocks", "@kbn/core-theme-browser-mocks", + "@kbn/saved-objects-management-plugin", + "@kbn/saved-objects-tagging-oss-plugin", + "@kbn/saved-objects-finder-plugin", ], "exclude": [ "target/**/*", diff --git a/src/plugins/saved_objects_finder/kibana.jsonc b/src/plugins/saved_objects_finder/kibana.jsonc index bfe35d688b9cf..9373ef8d5f9de 100644 --- a/src/plugins/saved_objects_finder/kibana.jsonc +++ b/src/plugins/saved_objects_finder/kibana.jsonc @@ -6,8 +6,6 @@ "id": "savedObjectsFinder", "server": true, "browser": true, - "requiredBundles": [ - "savedObjects" - ] + "requiredBundles": ["savedObjects"] } } diff --git a/src/plugins/saved_objects_finder/public/finder/index.tsx b/src/plugins/saved_objects_finder/public/finder/index.tsx index 0819ebf8141b6..789d09ec520b1 100644 --- a/src/plugins/saved_objects_finder/public/finder/index.tsx +++ b/src/plugins/saved_objects_finder/public/finder/index.tsx @@ -8,6 +8,10 @@ import { EuiDelayRender, EuiLoadingContent } from '@elastic/eui'; import React from 'react'; +import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; +import { HttpStart } from '@kbn/core-http-browser'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; +import { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { SavedObjectFinderProps } from './saved_object_finder'; const LazySavedObjectFinder = React.lazy(() => import('./saved_object_finder')); @@ -23,5 +27,19 @@ const SavedObjectFinder = (props: SavedObjectFinderProps) => ( ); +export const getSavedObjectFinder = ( + uiSettings: IUiSettingsClient, + http: HttpStart, + savedObjectsManagement: SavedObjectsManagementPluginStart, + savedObjectsTagging?: SavedObjectsTaggingApi +) => { + return (props: SavedObjectFinderProps) => ( + + ); +}; + export type { SavedObjectMetaData, SavedObjectFinderProps } from './saved_object_finder'; export { SavedObjectFinder }; diff --git a/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx b/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx index 570890e015409..2db81716876c9 100644 --- a/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx +++ b/src/plugins/saved_objects_finder/public/finder/saved_object_finder.tsx @@ -28,7 +28,7 @@ import { i18n } from '@kbn/i18n'; import type { IUiSettingsClient, HttpStart } from '@kbn/core/public'; import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public'; import { LISTING_LIMIT_SETTING } from '@kbn/saved-objects-plugin/public'; -import { SavedObjectCommon, FindQueryHTTP, FindResponseHTTP } from '../../common'; +import { SavedObjectCommon, FindQueryHTTP, FindResponseHTTP, FinderAttributes } from '../../common'; export interface SavedObjectMetaData { type: string; @@ -41,12 +41,6 @@ export interface SavedObjectMetaData { defaultSearchField?: string; } -interface FinderAttributes { - title?: string; - name?: string; - type: string; -} - interface SavedObjectFinderItem extends SavedObjectCommon { title: string | null; name: string | null; @@ -64,7 +58,7 @@ interface SavedObjectFinderServices { http: HttpStart; uiSettings: IUiSettingsClient; savedObjectsManagement: SavedObjectsManagementPluginStart; - savedObjectsTagging: SavedObjectsTaggingApi | undefined; + savedObjectsTagging?: SavedObjectsTaggingApi; } interface BaseSavedObjectFinder { @@ -109,16 +103,7 @@ export class SavedObjectFinderUi extends React.Component< private debouncedFetch = debounce(async (query: Query) => { const metaDataMap = this.getSavedObjectMetaDataMap(); - const { queryText, visibleTypes, selectedTags } = - this.props.services.savedObjectsManagement.parseQuery( - query, - Object.values(metaDataMap).map((metadata) => ({ - name: metadata.type, - namespaceType: 'single', - hidden: false, - displayName: metadata.name, - })) - ); + const { savedObjectsManagement, uiSettings, http } = this.props.services; const fields = Object.values(metaDataMap) .map((metaData) => metaData.includeFields || []) @@ -131,22 +116,32 @@ export class SavedObjectFinderUi extends React.Component< return col; }, []); - const perPage = this.props.services.uiSettings.get(LISTING_LIMIT_SETTING); - const hasReference = this.props.services.savedObjectsManagement.getTagFindReferences({ + const perPage = uiSettings.get(LISTING_LIMIT_SETTING); + const { queryText, visibleTypes, selectedTags } = savedObjectsManagement.parseQuery( + query, + Object.values(metaDataMap).map((metadata) => ({ + name: metadata.type, + namespaceType: 'single', + hidden: false, + displayName: metadata.name, + })) + ); + const hasReference = savedObjectsManagement.getTagFindReferences({ selectedTags, taggingApi: this.props.services.savedObjectsTagging, }); const params: FindQueryHTTP = { type: visibleTypes ?? Object.keys(metaDataMap), - fields: [...new Set(fields)], search: queryText ? `${queryText}*` : undefined, + fields: [...new Set(fields)], page: 1, perPage, searchFields: ['title^3', 'description', ...additionalSearchFields], defaultSearchOperator: 'AND', hasReference: hasReference ? JSON.stringify(hasReference) : undefined, }; - const response = (await this.props.services.http.get('/internal/saved-objects-finder/find', { + + const response = (await http.get('/internal/saved-objects-finder/find', { query: params as Record, })) as FindResponseHTTP; @@ -156,7 +151,7 @@ export class SavedObjectFinderUi extends React.Component< attributes: { name, title }, } = savedObject; const titleToUse = typeof title === 'string' ? title : ''; - const nameToUse = name && typeof name === 'string' ? name : titleToUse; + const nameToUse = name ? name : titleToUse; return { ...savedObject, version: savedObject.version, @@ -169,9 +164,8 @@ export class SavedObjectFinderUi extends React.Component< const metaData = metaDataMap[savedObject.type]; if (metaData.showSavedObject) { return metaData.showSavedObject(savedObject.simple); - } else { - return true; } + return true; }); if (!this.isComponentMounted) { @@ -289,7 +283,7 @@ export class SavedObjectFinderUi extends React.Component< name: i18n.translate('savedObjectsFinder.titleName', { defaultMessage: 'Title', }), - width: '55%', + width: tagColumn ? '55%' : '100%', description: i18n.translate('savedObjectsFinder.titleDescription', { defaultMessage: 'Title of the saved object', }), @@ -369,6 +363,7 @@ export class SavedObjectFinderUi extends React.Component< itemId="id" items={this.state.items} columns={columns} + data-test-subj="savedObjectsFinderTable" message={this.props.noItemsMessage} search={search} pagination={pagination} diff --git a/src/plugins/saved_objects_finder/public/index.ts b/src/plugins/saved_objects_finder/public/index.ts index b266860185365..ada561d5ccb0d 100644 --- a/src/plugins/saved_objects_finder/public/index.ts +++ b/src/plugins/saved_objects_finder/public/index.ts @@ -8,6 +8,6 @@ import { SavedObjectsFinderPublicPlugin } from './plugin'; export type { SavedObjectMetaData, SavedObjectFinderProps } from './finder'; -export { SavedObjectFinder } from './finder'; +export { SavedObjectFinder, getSavedObjectFinder } from './finder'; export const plugin = () => new SavedObjectsFinderPublicPlugin(); diff --git a/src/plugins/saved_objects_finder/tsconfig.json b/src/plugins/saved_objects_finder/tsconfig.json index 02aa4bf8208ea..8725d23a5ea14 100644 --- a/src/plugins/saved_objects_finder/tsconfig.json +++ b/src/plugins/saved_objects_finder/tsconfig.json @@ -13,6 +13,8 @@ "@kbn/saved-objects-plugin", "@kbn/core-saved-objects-server", "@kbn/config-schema", + "@kbn/core-ui-settings-browser", + "@kbn/core-http-browser", ], "exclude": [ "target/**/*", diff --git a/test/examples/embeddables/adding_children.ts b/test/examples/embeddables/adding_children.ts index 1b99413b184f7..7b3e48151fd17 100644 --- a/test/examples/embeddables/adding_children.ts +++ b/test/examples/embeddables/adding_children.ts @@ -12,8 +12,29 @@ import { PluginFunctionalProviderContext } from '../../plugin_functional/service // eslint-disable-next-line import/no-default-export export default function ({ getService }: PluginFunctionalProviderContext) { const testSubjects = getService('testSubjects'); + const find = getService('find'); const flyout = getService('flyout'); + const toggleFilterPopover = async () => { + const filtersHolder = await find.byClassName('euiSearchBar__filtersHolder'); + const filtersButton = await filtersHolder.findByCssSelector('button'); + await filtersButton.click(); + }; + + const clickFilter = async (type: string) => { + const list = await testSubjects.find('euiSelectableList'); + const listItems = await list.findAllByCssSelector('li'); + for (let i = 0; i < listItems.length; i++) { + const listItem = await listItems[i].findByClassName('euiSelectableListItem__text'); + const text = await listItem.getVisibleText(); + if (text.includes(type)) { + await listItem.click(); + await toggleFilterPopover(); + break; + } + } + }; + describe('adding children', () => { before(async () => { await testSubjects.click('embeddablePanelExample'); @@ -23,8 +44,8 @@ export default function ({ getService }: PluginFunctionalProviderContext) { await testSubjects.click('embeddablePanelToggleMenuIcon'); await testSubjects.click('embeddablePanelAction-ACTION_ADD_PANEL'); await testSubjects.waitForDeleted('savedObjectFinderLoadingIndicator'); - await testSubjects.click('savedObjectFinderFilterButton'); - await testSubjects.click('savedObjectFinderFilter-todo'); + await toggleFilterPopover(); + await clickFilter('Todo'); await testSubjects.click('savedObjectTitleGarbage'); await testSubjects.moveMouseTo('euiFlyoutCloseButton'); await flyout.ensureClosed('dashboardAddPanel'); diff --git a/test/functional/apps/dashboard/group2/embeddable_library.ts b/test/functional/apps/dashboard/group2/embeddable_library.ts index ca52eaecaf46e..472a2a890c978 100644 --- a/test/functional/apps/dashboard/group2/embeddable_library.ts +++ b/test/functional/apps/dashboard/group2/embeddable_library.ts @@ -17,6 +17,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const dashboardAddPanel = getService('dashboardAddPanel'); const panelActions = getService('dashboardPanelActions'); + const savedObjectsFinder = getService('savedObjectsFinder'); describe('embeddable library', () => { before(async () => { @@ -35,7 +36,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('unlink visualize panel from embeddable library', async () => { // add heatmap panel from library await dashboardAddPanel.clickOpenAddPanel(); - await dashboardAddPanel.filterEmbeddableNames('Rendering Test: heatmap'); + await savedObjectsFinder.filterEmbeddableNames('Rendering Test: heatmap'); await find.clickByButtonText('Rendering Test: heatmap'); await dashboardAddPanel.closeAddPanel(); @@ -51,7 +52,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(libraryActionExists).to.be(false); await dashboardAddPanel.clickOpenAddPanel(); - await dashboardAddPanel.filterEmbeddableNames('Rendering Test: heatmap'); + await savedObjectsFinder.filterEmbeddableNames('Rendering Test: heatmap'); await find.existsByLinkText('Rendering Test: heatmap'); await dashboardAddPanel.closeAddPanel(); }); diff --git a/test/functional/apps/dashboard/group3/panel_replacing.ts b/test/functional/apps/dashboard/group3/panel_replacing.ts index e6ff8c4f940bb..1cb344748594f 100644 --- a/test/functional/apps/dashboard/group3/panel_replacing.ts +++ b/test/functional/apps/dashboard/group3/panel_replacing.ts @@ -80,7 +80,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.dashboard.switchToEditMode(); } await dashboardPanelActions.replacePanelByTitle(AREA_CHART_VIS_NAME); - await dashboardReplacePanel.replaceEmbeddable(replacedSearch, 'search'); + await dashboardReplacePanel.replaceEmbeddable(replacedSearch, 'Saved search'); await PageObjects.header.waitUntilLoadingHasFinished(); await PageObjects.dashboard.waitForRenderComplete(); const panelTitles = await PageObjects.dashboard.getPanelTitles(); diff --git a/test/functional/services/dashboard/add_panel.ts b/test/functional/services/dashboard/add_panel.ts index a29fd8046e7ec..7af97ef7ff32f 100644 --- a/test/functional/services/dashboard/add_panel.ts +++ b/test/functional/services/dashboard/add_panel.ts @@ -5,7 +5,6 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - import { FtrService } from '../../ftr_provider_context'; export class DashboardAddPanelService extends FtrService { @@ -15,6 +14,7 @@ export class DashboardAddPanelService extends FtrService { private readonly flyout = this.ctx.getService('flyout'); private readonly common = this.ctx.getPageObject('common'); private readonly header = this.ctx.getPageObject('header'); + private readonly savedObjectsFinder = this.ctx.getService('savedObjectsFinder'); async clickOpenAddPanel() { this.log.debug('DashboardAddPanel.clickOpenAddPanel'); @@ -77,34 +77,20 @@ export class DashboardAddPanelService extends FtrService { await this.testSubjects.click(`createNew-${type}`); } - async toggleFilterPopover() { - this.log.debug('DashboardAddPanel.toggleFilter'); - await this.testSubjects.click('savedObjectFinderFilterButton'); - } - - async toggleFilter(type: string) { - this.log.debug(`DashboardAddPanel.addToFilter(${type})`); - await this.waitForListLoading(); - await this.toggleFilterPopover(); - await this.testSubjects.click(`savedObjectFinderFilter-${type}`); - await this.toggleFilterPopover(); - } - async addEveryEmbeddableOnCurrentPage() { this.log.debug('addEveryEmbeddableOnCurrentPage'); - const itemList = await this.testSubjects.find('savedObjectFinderItemList'); + const itemList = await this.testSubjects.find('savedObjectsFinderTable'); const embeddableList: string[] = []; await this.retry.try(async () => { - const embeddableRows = await itemList.findAllByCssSelector('li'); + const embeddableListBody = await itemList.findByTagName('tbody'); + const embeddableRows = await embeddableListBody.findAllByCssSelector('tr'); for (let i = 0; i < embeddableRows.length; i++) { - const name = await embeddableRows[i].getVisibleText(); - + const { name, button } = await this.savedObjectsFinder.getRowAtIndex(embeddableRows, i); if (embeddableList.includes(name)) { // already added this one continue; } - - await embeddableRows[i].click(); + await button.click(); await this.common.closeToast(); embeddableList.push(name); } @@ -159,21 +145,21 @@ export class DashboardAddPanelService extends FtrService { } } - async waitForListLoading() { - await this.testSubjects.waitForDeleted('savedObjectFinderLoadingIndicator'); - } - async closeAddPanel() { await this.flyout.ensureClosed('dashboardAddPanel'); } + async filterEmbeddableNames(name: string) { + await this.savedObjectsFinder.filterEmbeddableNames(name); + } + async addEveryVisualization(filter: string) { this.log.debug('DashboardAddPanel.addEveryVisualization'); await this.ensureAddPanelIsShowing(); - await this.toggleFilter('visualization'); if (filter) { await this.filterEmbeddableNames(filter.replace('-', ' ')); } + await this.savedObjectsFinder.waitForFilter('Visualization', 'search'); let morePages = true; const vizList: string[][] = []; while (morePages) { @@ -187,11 +173,11 @@ export class DashboardAddPanelService extends FtrService { async addEverySavedSearch(filter: string) { this.log.debug('DashboardAddPanel.addEverySavedSearch'); await this.ensureAddPanelIsShowing(); - await this.toggleFilter('search'); const searchList = []; if (filter) { await this.filterEmbeddableNames(filter.replace('-', ' ')); } + await this.savedObjectsFinder.waitForFilter('Saved search', 'visualization'); let morePages = true; while (morePages) { searchList.push(await this.addEveryEmbeddableOnCurrentPage()); @@ -222,7 +208,8 @@ export class DashboardAddPanelService extends FtrService { } async addVisualization(vizName: string) { - return this.addEmbeddable(vizName, 'visualization'); + this.log.debug(`DashboardAddPanel.addVisualization, ${vizName}`); + return this.addEmbeddable(vizName, 'Visualization'); } async addEmbeddable(embeddableName: string, embeddableType: string) { @@ -230,25 +217,18 @@ export class DashboardAddPanelService extends FtrService { `DashboardAddPanel.addEmbeddable, name: ${embeddableName}, type: ${embeddableType}` ); await this.ensureAddPanelIsShowing(); - await this.toggleFilter(embeddableType); - await this.filterEmbeddableNames(`"${embeddableName.replace('-', ' ')}"`); + await this.savedObjectsFinder.toggleFilter(embeddableType); + await this.savedObjectsFinder.filterEmbeddableNames(`"${embeddableName.replace('-', ' ')}"`); await this.testSubjects.click(`savedObjectTitle${embeddableName.split(' ').join('-')}`); await this.testSubjects.exists('addObjectToDashboardSuccess'); await this.closeAddPanel(); return embeddableName; } - async filterEmbeddableNames(name: string) { - // The search input field may be disabled while the table is loading so wait for it - await this.waitForListLoading(); - await this.testSubjects.setValue('savedObjectFinderSearchInput', name); - await this.waitForListLoading(); - } - async panelAddLinkExists(name: string) { this.log.debug(`DashboardAddPanel.panelAddLinkExists(${name})`); await this.ensureAddPanelIsShowing(); - await this.filterEmbeddableNames(`"${name}"`); + await this.savedObjectsFinder.filterEmbeddableNames(`"${name}"`); return await this.testSubjects.exists(`savedObjectTitle${name.split(' ').join('-')}`); } } diff --git a/test/functional/services/dashboard/replace_panel.ts b/test/functional/services/dashboard/replace_panel.ts index 8f8f680b839bf..915e65467a7a5 100644 --- a/test/functional/services/dashboard/replace_panel.ts +++ b/test/functional/services/dashboard/replace_panel.ts @@ -12,19 +12,7 @@ export class DashboardReplacePanelService extends FtrService { private readonly log = this.ctx.getService('log'); private readonly testSubjects = this.ctx.getService('testSubjects'); private readonly flyout = this.ctx.getService('flyout'); - - async toggleFilterPopover() { - this.log.debug('DashboardReplacePanel.toggleFilter'); - await this.testSubjects.click('savedObjectFinderFilterButton'); - } - - async toggleFilter(type: string) { - this.log.debug(`DashboardReplacePanel.replaceToFilter(${type})`); - await this.waitForListLoading(); - await this.toggleFilterPopover(); - await this.testSubjects.click(`savedObjectFinderFilter-${type}`); - await this.toggleFilterPopover(); - } + private readonly savedObjectsFinder = this.ctx.getService('savedObjectsFinder'); async isReplacePanelOpen() { this.log.debug('DashboardReplacePanel.isReplacePanelOpen'); @@ -66,10 +54,10 @@ export class DashboardReplacePanelService extends FtrService { `DashboardReplacePanel.replaceEmbeddable, name: ${embeddableName}, type: ${embeddableType}` ); await this.ensureReplacePanelIsShowing(); + await this.filterEmbeddableNames(`"${embeddableName.replace('-', ' ')}"`); if (embeddableType) { - await this.toggleFilter(embeddableType); + await this.savedObjectsFinder.toggleFilter(embeddableType); } - await this.filterEmbeddableNames(`"${embeddableName.replace('-', ' ')}"`); await this.testSubjects.click(`savedObjectTitle${embeddableName.split(' ').join('-')}`); await this.testSubjects.exists('addObjectToDashboardSuccess'); await this.closeReplacePanel(); diff --git a/test/functional/services/index.ts b/test/functional/services/index.ts index 80b80ada9a979..e13cac581ce52 100644 --- a/test/functional/services/index.ts +++ b/test/functional/services/index.ts @@ -55,6 +55,7 @@ import { KibanaSupertestProvider } from './supertest'; import { MenuToggleService } from './menu_toggle'; import { MonacoEditorService } from './monaco_editor'; import { UsageCollectionService } from './usage_collection'; +import { SavedObjectsFinderService } from './saved_objects_finder'; export const services = { ...commonServiceProviders, @@ -100,4 +101,5 @@ export const services = { menuToggle: MenuToggleService, retryOnStale: RetryOnStaleProvider, usageCollection: UsageCollectionService, + savedObjectsFinder: SavedObjectsFinderService, }; diff --git a/test/functional/services/saved_objects_finder.ts b/test/functional/services/saved_objects_finder.ts new file mode 100644 index 0000000000000..12e06fe8a1710 --- /dev/null +++ b/test/functional/services/saved_objects_finder.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import expect from '@kbn/expect'; +import { FtrService } from '../ftr_provider_context'; +import { WebElementWrapper } from './lib/web_element_wrapper'; + +export class SavedObjectsFinderService extends FtrService { + private readonly testSubjects = this.ctx.getService('testSubjects'); + private readonly find = this.ctx.getService('find'); + private readonly log = this.ctx.getService('log'); + private readonly retry = this.ctx.getService('retry'); + + public async toggleFilterPopover() { + this.log.debug('SavedObjectsFinder.toggleFilter'); + const filtersHolder = await this.find.byClassName('euiSearchBar__filtersHolder'); + const filtersButton = await filtersHolder.findByCssSelector('button'); + await filtersButton.click(); + } + + public async toggleFilter(type: string) { + this.log.debug(`SavedObjectsFinder.addToFilter(${type})`); + await this.waitForListLoading(); + await this.toggleFilterPopover(); + const list = await this.testSubjects.find('euiSelectableList'); + const listItems = await list.findAllByCssSelector('li'); + for (let i = 0; i < listItems.length; i++) { + const listItem = await listItems[i].findByClassName('euiSelectableListItem__text'); + const text = await listItem.getVisibleText(); + if (text.includes(type)) { + await listItem.click(); + await this.toggleFilterPopover(); + break; + } + } + } + + public async waitForFilter(type: string, expectCondition: string) { + await this.toggleFilter(type); + const itemList = await this.testSubjects.find('savedObjectsFinderTable'); + await this.retry.try(async () => { + const embeddableListBody = await itemList.findByTagName('tbody'); + const embeddableRows = await embeddableListBody.findAllByCssSelector('tr'); + const { name } = await this.getRowAtIndex(embeddableRows, 0); + expect(name.includes(expectCondition)).to.be(false); + }); + } + + public async filterEmbeddableNames(name: string) { + // The search input field may be disabled while the table is loading so wait for it + await this.waitForListLoading(); + await this.testSubjects.setValue('savedObjectFinderSearchInput', name); + await this.waitForListLoading(); + } + + public async getRowAtIndex(rows: WebElementWrapper[], rowIndex: number) { + const cell = await rows[rowIndex].findByTestSubject('savedObjectFinderTitle'); + const button = await cell.findByTagName('button'); + const name = await button.getVisibleText(); + return { button, name }; + } + + private async waitForListLoading() { + await this.testSubjects.waitForDeleted('savedObjectFinderLoadingIndicator'); + } +} diff --git a/x-pack/plugins/canvas/kibana.jsonc b/x-pack/plugins/canvas/kibana.jsonc index 3ef7326dcd460..c52f6628b4fad 100644 --- a/x-pack/plugins/canvas/kibana.jsonc +++ b/x-pack/plugins/canvas/kibana.jsonc @@ -29,13 +29,16 @@ "presentationUtil", "visualizations", "uiActions", - "share" + "share", + "savedObjectsManagement", + "savedObjectsFinder" ], "optionalPlugins": [ "home", "reporting", "spaces", - "usageCollection" + "usageCollection", + "savedObjects", ], "requiredBundles": [ "discover", @@ -43,9 +46,8 @@ "kibanaUtils", "lens", "maps", - "savedObjects", "visualizations", "fieldFormats" - ] + ], } } diff --git a/x-pack/plugins/canvas/public/components/embeddable_flyout/flyout.component.tsx b/x-pack/plugins/canvas/public/components/embeddable_flyout/flyout.component.tsx index e92c8277488ca..d9c665646e2b4 100644 --- a/x-pack/plugins/canvas/public/components/embeddable_flyout/flyout.component.tsx +++ b/x-pack/plugins/canvas/public/components/embeddable_flyout/flyout.component.tsx @@ -9,7 +9,7 @@ import React, { FC, useCallback } from 'react'; import { EuiFlyout, EuiFlyoutHeader, EuiFlyoutBody, EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SavedObjectFinderUi, SavedObjectMetaData } from '@kbn/saved-objects-plugin/public'; +import { SavedObjectFinder, SavedObjectMetaData } from '@kbn/saved-objects-finder-plugin/public'; import { useEmbeddablesService, usePlatformService } from '../../services'; const strings = { @@ -38,7 +38,7 @@ export const AddEmbeddableFlyout: FC = ({ const embeddablesService = useEmbeddablesService(); const platformService = usePlatformService(); const { getEmbeddableFactories } = embeddablesService; - const { getHttp, getUISettings } = platformService; + const { getHttp, getUISettings, getSavedObjectsManagement } = platformService; const onAddPanel = useCallback( (id: string, savedObjectType: string) => { @@ -77,13 +77,16 @@ export const AddEmbeddableFlyout: FC = ({ - diff --git a/x-pack/plugins/canvas/public/plugin.tsx b/x-pack/plugins/canvas/public/plugin.tsx index 18facb65202f3..20dee0bf5fa75 100644 --- a/x-pack/plugins/canvas/public/plugin.tsx +++ b/x-pack/plugins/canvas/public/plugin.tsx @@ -30,6 +30,7 @@ import { Start as InspectorStart } from '@kbn/inspector-plugin/public'; import { BfetchPublicSetup } from '@kbn/bfetch-plugin/public'; import { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { featureCatalogueEntry } from './feature_catalogue_entry'; import { CanvasAppLocatorDefinition } from '../common/locator'; import { SESSIONSTORAGE_LASTPATH, CANVAS_APP } from '../common/lib/constants'; @@ -67,6 +68,7 @@ export interface CanvasStartDeps { presentationUtil: PresentationUtilPluginStart; visualizations: VisualizationsStart; spaces?: SpacesPluginStart; + savedObjectsManagement: SavedObjectsManagementPluginStart; } /** diff --git a/x-pack/plugins/canvas/public/services/kibana/platform.ts b/x-pack/plugins/canvas/public/services/kibana/platform.ts index 0b51963eeee31..ab5fb175bd6d1 100644 --- a/x-pack/plugins/canvas/public/services/kibana/platform.ts +++ b/x-pack/plugins/canvas/public/services/kibana/platform.ts @@ -46,5 +46,6 @@ export const platformServiceFactory: CanvaPlatformServiceFactory = ({ getSavedObjectsClient: () => coreStart.savedObjects.client, getUISettings: () => coreStart.uiSettings, getHttp: () => coreStart.http, + getSavedObjectsManagement: () => startPlugins.savedObjectsManagement, }; }; diff --git a/x-pack/plugins/canvas/public/services/platform.ts b/x-pack/plugins/canvas/public/services/platform.ts index b436f51bb33f9..77649a8fa0592 100644 --- a/x-pack/plugins/canvas/public/services/platform.ts +++ b/x-pack/plugins/canvas/public/services/platform.ts @@ -17,6 +17,7 @@ import { } from '@kbn/core/public'; import { SpacesPluginStart } from '@kbn/spaces-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; export interface CanvasPlatformService { getBasePath: () => string; @@ -39,4 +40,5 @@ export interface CanvasPlatformService { getSavedObjectsClient: () => SavedObjectsClientContract; getUISettings: () => IUiSettingsClient; getHttp: () => HttpStart; + getSavedObjectsManagement: () => SavedObjectsManagementPluginStart; } diff --git a/x-pack/plugins/canvas/public/services/stubs/platform.ts b/x-pack/plugins/canvas/public/services/stubs/platform.ts index d96599257f9b6..cdb75dc96322b 100644 --- a/x-pack/plugins/canvas/public/services/stubs/platform.ts +++ b/x-pack/plugins/canvas/public/services/stubs/platform.ts @@ -37,4 +37,5 @@ export const platformServiceFactory: CanvasPlatformServiceFactory = () => ({ redirectLegacyUrl: noop, getLegacyUrlConflict: undefined, getHttp: noop, + getSavedObjectsManagement: noop, }); diff --git a/x-pack/plugins/canvas/tsconfig.json b/x-pack/plugins/canvas/tsconfig.json index ef10a58a1e65b..228ae010ddf43 100644 --- a/x-pack/plugins/canvas/tsconfig.json +++ b/x-pack/plugins/canvas/tsconfig.json @@ -45,7 +45,6 @@ "@kbn/kibana-react-plugin", "@kbn/kibana-utils-plugin", "@kbn/presentation-util-plugin", - "@kbn/saved-objects-plugin", "@kbn/ui-actions-plugin", "@kbn/usage-collection-plugin", "@kbn/visualizations-plugin", @@ -79,6 +78,8 @@ "@kbn/shared-ux-router", "@kbn/babel-register", "@kbn/shared-ux-button-toolbar", + "@kbn/saved-objects-finder-plugin", + "@kbn/saved-objects-management-plugin", ], "exclude": [ "target/**/*", From df2869a5fefeec28f1f796630fff85708a59163a Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Wed, 1 Mar 2023 13:33:50 -0800 Subject: [PATCH 101/131] [Security Solution][Exceptions] - Fix export toast message (#152301) ## Summary Addresses https://github.com/elastic/kibana/issues/145680 --- .../exceptions/alerts_table_flow/add_exception.cy.ts | 5 ++++- .../exceptions_management_flow/exceptions_table.cy.ts | 5 ++++- .../components/exceptions_list_card/index.tsx | 2 ++ .../hooks/use_exceptions_list.card/index.tsx | 3 +++ .../exceptions/hooks/use_list_detail_view/index.ts | 2 +- .../public/exceptions/pages/shared_lists/index.tsx | 8 +++++--- .../exceptions/translations/list_details_view.ts | 6 ------ .../public/exceptions/translations/shared_list.ts | 11 +++++------ x-pack/plugins/translations/translations/fr-FR.json | 2 -- x-pack/plugins/translations/translations/ja-JP.json | 2 -- x-pack/plugins/translations/translations/zh-CN.json | 2 -- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/e2e/exceptions/alerts_table_flow/add_exception.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/alerts_table_flow/add_exception.cy.ts index 213ea64fc4ceb..41b190c8ccc0d 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/exceptions/alerts_table_flow/add_exception.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/exceptions/alerts_table_flow/add_exception.cy.ts @@ -86,7 +86,10 @@ describe('Exceptions Table', () => { expectedExportedExceptionList(this.exceptionListResponse) ); - cy.get(TOASTER).should('have.text', 'Exception list export success'); + cy.get(TOASTER).should( + 'have.text', + `Exception list "${getExceptionList1().name}" exported successfully` + ); }); }); diff --git a/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts b/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts index d571d7cd4fae8..99d38ef3c5819 100644 --- a/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts +++ b/x-pack/plugins/security_solution/cypress/e2e/exceptions/exceptions_management_flow/exceptions_table.cy.ts @@ -83,7 +83,10 @@ describe('Exceptions Table', () => { expectedExportedExceptionList(this.exceptionListResponse) ); - cy.get(TOASTER).should('have.text', 'Exception list export success'); + cy.get(TOASTER).should( + 'have.text', + `Exception list "${getExceptionList1().name}" exported successfully` + ); }); }); diff --git a/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx b/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx index 54f2b0cf6c5d3..eb945e18e7761 100644 --- a/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx @@ -50,11 +50,13 @@ interface ExceptionsListCardProps { id, includeExpiredExceptions, listId, + name, namespaceType, }: { id: string; includeExpiredExceptions: boolean; listId: string; + name: string; namespaceType: NamespaceType; }) => () => Promise; readOnly: boolean; diff --git a/x-pack/plugins/security_solution/public/exceptions/hooks/use_exceptions_list.card/index.tsx b/x-pack/plugins/security_solution/public/exceptions/hooks/use_exceptions_list.card/index.tsx index 5a8912a422f5c..d0ccd384156c7 100644 --- a/x-pack/plugins/security_solution/public/exceptions/hooks/use_exceptions_list.card/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/hooks/use_exceptions_list.card/index.tsx @@ -24,6 +24,7 @@ import { checkIfListCannotBeEdited } from '../../utils/list.utils'; interface ExportListAction { id: string; listId: string; + name: string; namespaceType: NamespaceType; includeExpiredExceptions: boolean; } @@ -42,6 +43,7 @@ export const useExceptionsListCard = ({ handleExport: ({ id, listId, + name, namespaceType, includeExpiredExceptions, }: ExportListAction) => () => Promise; @@ -192,6 +194,7 @@ export const useExceptionsListCard = ({ handleExport({ id: exceptionsList.id, listId: exceptionsList.list_id, + name: exceptionsList.name, namespaceType: exceptionsList.namespace_type, includeExpiredExceptions, })(); 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 3359ccb760b05..2494a6c989791 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 @@ -175,7 +175,7 @@ export const useListDetailsView = (exceptionListId: string) => { onError: (error: Error) => handleErrorStatus(error), onSuccess: (blob) => { setExportedList(blob); - toasts?.addSuccess(i18n.EXCEPTION_LIST_EXPORTED_SUCCESSFULLY(list.list_id)); + toasts?.addSuccess(i18n.EXCEPTION_LIST_EXPORTED_SUCCESSFULLY(list.name)); }, }); } catch (error) { diff --git a/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx b/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx index 533f920a0b40c..fe2f2450a3900 100644 --- a/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx @@ -183,9 +183,9 @@ export const SharedLists = React.memo(() => { ); const handleExportSuccess = useCallback( - (listId: string) => + (listId: string, name: string) => (blob: Blob): void => { - addSuccess(i18n.EXCEPTION_EXPORT_SUCCESS); + addSuccess(i18n.EXCEPTION_LIST_EXPORTED_SUCCESSFULLY(name)); setExportDownload({ name: listId, blob }); }, [addSuccess] @@ -202,11 +202,13 @@ export const SharedLists = React.memo(() => { ({ id, listId, + name, namespaceType, includeExpiredExceptions, }: { id: string; listId: string; + name: string; namespaceType: NamespaceType; includeExpiredExceptions: boolean; }) => @@ -217,7 +219,7 @@ export const SharedLists = React.memo(() => { listId, namespaceType, onError: handleExportError, - onSuccess: handleExportSuccess(listId), + onSuccess: handleExportSuccess(listId, name), }); }, [exportExceptionList, handleExportError, handleExportSuccess] diff --git a/x-pack/plugins/security_solution/public/exceptions/translations/list_details_view.ts b/x-pack/plugins/security_solution/public/exceptions/translations/list_details_view.ts index c839089d307a9..d37c5e29b9fc2 100644 --- a/x-pack/plugins/security_solution/public/exceptions/translations/list_details_view.ts +++ b/x-pack/plugins/security_solution/public/exceptions/translations/list_details_view.ts @@ -94,12 +94,6 @@ export const EXCEPTION_ITEM_DELETE_TEXT = (itemName: string) => } ); -export const EXCEPTION_LIST_EXPORTED_SUCCESSFULLY = (listName: string) => - i18n.translate('xpack.securitySolution.exceptions.list.exported_successfully', { - values: { listName }, - defaultMessage: '{listName} exported successfully', - }); - export const EXCEPTION_LIST_DELETED_SUCCESSFULLY = (listName: string) => i18n.translate('xpack.securitySolution.exceptions.list.deleted_successfully', { values: { listName }, diff --git a/x-pack/plugins/security_solution/public/exceptions/translations/shared_list.ts b/x-pack/plugins/security_solution/public/exceptions/translations/shared_list.ts index 7addaeb331247..6ab1ca6df8464 100644 --- a/x-pack/plugins/security_solution/public/exceptions/translations/shared_list.ts +++ b/x-pack/plugins/security_solution/public/exceptions/translations/shared_list.ts @@ -112,12 +112,11 @@ export const NO_LISTS_BODY = i18n.translate( } ); -export const EXCEPTION_EXPORT_SUCCESS = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.all.exceptions.exportSuccess', - { - defaultMessage: 'Exception list export success', - } -); +export const EXCEPTION_LIST_EXPORTED_SUCCESSFULLY = (listName: string) => + i18n.translate('xpack.securitySolution.exceptions.list.export_success', { + values: { listName }, + defaultMessage: 'Exception list "{listName}" exported successfully', + }); export const EXCEPTION_EXPORT_ERROR = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.all.exceptions.exportError', diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index bc8fc835911fb..82a2c51216e42 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -26776,7 +26776,6 @@ "xpack.securitySolution.exceptions.hideCommentsLabel": "Masquer ({comments}) {comments, plural, =1 {commentaire} other {commentaires}}", "xpack.securitySolution.exceptions.list.deleted_successfully": "{listName} supprimée avec succès", "xpack.securitySolution.exceptions.list.exception.item.card.exceptionItemDeleteSuccessText": "\"{itemName}\" supprimé avec succès.", - "xpack.securitySolution.exceptions.list.exported_successfully": "{listName} exporté avec succès", "xpack.securitySolution.exceptions.referenceModalDefaultDescription": "Voulez-vous vraiment SUPPRIMER la liste d'exceptions nommée {listName} ?", "xpack.securitySolution.exceptions.referenceModalDescription": "Cette liste d'exceptions est associée à ({referenceCount}) {referenceCount, plural, =1 {règle} other {règles}}. Le retrait de cette liste d'exceptions supprimera également sa référence des règles associées.", "xpack.securitySolution.exceptions.referenceModalSuccessDescription": "Liste d'exceptions - {listId} - supprimée avec succès.", @@ -28632,7 +28631,6 @@ "xpack.securitySolution.detectionEngine.rules.all.exceptions.deleteError": "Une erreur s'est produite lors de la suppression de la liste d'exceptions", "xpack.securitySolution.detectionEngine.rules.all.exceptions.errorFetching": "Erreur lors de la récupération des listes d'exceptions", "xpack.securitySolution.detectionEngine.rules.all.exceptions.exportError": "Erreur d'exportation de la liste d'exceptions", - "xpack.securitySolution.detectionEngine.rules.all.exceptions.exportSuccess": "Réussite de l'exportation de la liste d'exceptions", "xpack.securitySolution.detectionEngine.rules.all.exceptions.idTitle": "ID de liste", "xpack.securitySolution.detectionEngine.rules.all.exceptions.listName": "Nom", "xpack.securitySolution.detectionEngine.rules.all.exceptions.refresh": "Actualiser", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4bd272febf95a..9f1cb387004e9 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -26749,7 +26749,6 @@ "xpack.securitySolution.exceptions.hideCommentsLabel": "({comments}){comments, plural, other {件のコメント}}を非表示", "xpack.securitySolution.exceptions.list.deleted_successfully": "{listName}が正常に削除されました", "xpack.securitySolution.exceptions.list.exception.item.card.exceptionItemDeleteSuccessText": "\"{itemName}\"が正常に削除されました。", - "xpack.securitySolution.exceptions.list.exported_successfully": "{listName}が正常にエクスポートされました", "xpack.securitySolution.exceptions.referenceModalDefaultDescription": "名前{listName}の例外リストを削除しますか?", "xpack.securitySolution.exceptions.referenceModalDescription": "この例外リストは、({referenceCount}) {referenceCount, plural, other {個のルール}}に関連付けられています。この例外リストを削除すると、関連付けられたルールからの参照も削除されます。", "xpack.securitySolution.exceptions.referenceModalSuccessDescription": "例外リスト{listId}が正常に削除されました。", @@ -28604,7 +28603,6 @@ "xpack.securitySolution.detectionEngine.rules.all.exceptions.deleteError": "例外リストの削除中にエラーが発生しました", "xpack.securitySolution.detectionEngine.rules.all.exceptions.errorFetching": "例外リストの取得エラー", "xpack.securitySolution.detectionEngine.rules.all.exceptions.exportError": "例外リストエクスポートエラー", - "xpack.securitySolution.detectionEngine.rules.all.exceptions.exportSuccess": "例外リストエクスポート成功", "xpack.securitySolution.detectionEngine.rules.all.exceptions.idTitle": "リスト ID", "xpack.securitySolution.detectionEngine.rules.all.exceptions.listName": "名前", "xpack.securitySolution.detectionEngine.rules.all.exceptions.refresh": "更新", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d1d3729f26079..cc3498186a34a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -26784,7 +26784,6 @@ "xpack.securitySolution.exceptions.hideCommentsLabel": "隐藏 ({comments}) 个{comments, plural, other {注释}}", "xpack.securitySolution.exceptions.list.deleted_successfully": "已成功删除 {listName}", "xpack.securitySolution.exceptions.list.exception.item.card.exceptionItemDeleteSuccessText": "已成功删除“{itemName}”。", - "xpack.securitySolution.exceptions.list.exported_successfully": "已成功导出 {listName}", "xpack.securitySolution.exceptions.referenceModalDefaultDescription": "是否确定要删除名为 {listName} 的例外列表?", "xpack.securitySolution.exceptions.referenceModalDescription": "此例外列表与 ({referenceCount}) 个{referenceCount, plural, other {规则}}关联。移除此例外列表还将会删除其对关联规则的引用。", "xpack.securitySolution.exceptions.referenceModalSuccessDescription": "例外列表 - {listId} - 已成功删除。", @@ -28638,7 +28637,6 @@ "xpack.securitySolution.detectionEngine.rules.all.exceptions.deleteError": "删除例外列表时发生错误", "xpack.securitySolution.detectionEngine.rules.all.exceptions.errorFetching": "提取例外列表时出错", "xpack.securitySolution.detectionEngine.rules.all.exceptions.exportError": "例外列表导出错误", - "xpack.securitySolution.detectionEngine.rules.all.exceptions.exportSuccess": "例外列表导出成功", "xpack.securitySolution.detectionEngine.rules.all.exceptions.idTitle": "列表 ID", "xpack.securitySolution.detectionEngine.rules.all.exceptions.listName": "名称", "xpack.securitySolution.detectionEngine.rules.all.exceptions.refresh": "刷新", From 957c0d43c2557d9972aa932243639c94dc74f4ef Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Wed, 1 Mar 2023 13:34:52 -0800 Subject: [PATCH 102/131] [Security Solution][Exceptions] - Fix bulk rule duplicate, exception modal rule count (#152403) ## Summary When user selects to bulk duplicate, a modal pops up asking them how they want to proceed with any rule exceptions. The rule count in this modal is wrong when all rules are selected. Updated so that now the count in the modal matches the actual selected count. --- .../rule_management_ui/components/rules_table/rules_tables.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 dd173faade654..66d9d4bbf4e50 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 @@ -231,6 +231,7 @@ export const RulesTables = React.memo(({ selectedTab }) => { const shouldShowLinearProgress = (isFetched && isRefetching) || isUpgradingSecurityPackages; const shouldShowLoadingOverlay = (!isFetched && isRefetching) || isPreflightInProgress; + const numberOfSelectedRules = isAllSelected ? pagination.total : selectedRuleIds?.length ?? 1; return ( <> @@ -275,7 +276,7 @@ export const RulesTables = React.memo(({ selectedTab }) => { )} {isBulkEditFlyoutVisible && bulkEditActionType !== undefined && ( From b8bae97714815f50848272b6bac969525f571010 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Wed, 1 Mar 2023 16:34:57 -0600 Subject: [PATCH 103/131] skip flaky suite (#148349) --- .../main/components/sidebar/discover_field.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx index 88a5660db3017..eb433bb6ee7c3 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_field.test.tsx @@ -136,7 +136,8 @@ async function getComponent({ return { comp, props }; } -describe('discover sidebar field', function () { +// FLAKY: https://github.com/elastic/kibana/issues/148349 +describe.skip('discover sidebar field', function () { beforeEach(() => { (DetailsUtil.getDetails as jest.Mock).mockClear(); }); From babe0339e39c1cf859edd4d0cc67d5d1b2514531 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 2 Mar 2023 01:00:08 -0500 Subject: [PATCH 104/131] [api-docs] 2023-03-02 Daily api_docs build (#152531) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/264 --- 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.devdocs.json | 32 ++-- 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.devdocs.json | 48 +++--- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/deprecations_by_api.mdx | 8 +- api_docs/deprecations_by_plugin.mdx | 10 +- 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.devdocs.json | 20 +++ api_docs/embeddable.mdx | 4 +- 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_as_data_utils.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 +- .../kbn_core_lifecycle_browser.devdocs.json | 4 - 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 +- ...ore_saved_objects_api_browser.devdocs.json | 20 --- .../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 +- ...kbn_core_saved_objects_common.devdocs.json | 32 ++-- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...cts_migration_server_internal.devdocs.json | 24 +-- ...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.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_expandable_flyout.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_types.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.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.devdocs.json | 3 +- api_docs/observability.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/plugin_directory.mdx | 8 +- 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.devdocs.json | 143 ++++++++++++++++++ api_docs/saved_objects_finder.mdx | 4 +- 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 +- 488 files changed, 725 insertions(+), 583 deletions(-) diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index eb18c12c4c087..d7024294a9f2e 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-03-01 +date: 2023-03-02 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 457c9a044a4f5..9cd1578b94fd8 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-03-01 +date: 2023-03-02 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 a27f9db685c13..90e10a1574cbb 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-03-01 +date: 2023-03-02 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 f05c201efa2b2..105f01841d43c 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-03-01 +date: 2023-03-02 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 da0ef9b627636..176505db76893 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-03-01 +date: 2023-03-02 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 7fedab8ec9cf3..4ae0e43fab501 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-03-01 +date: 2023-03-02 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 ec54a22e05b23..349c11aa7f818 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-03-01 +date: 2023-03-02 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 22ee299448164..14f5425378cb5 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-03-01 +date: 2023-03-02 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 ca31ede36cb35..589bde7d8583c 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-03-01 +date: 2023-03-02 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 6dc629e35d2dc..6f96f0c9560c1 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-03-01 +date: 2023-03-02 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 87cefa21ff0d3..d8983278042a2 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-03-01 +date: 2023-03-02 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 5dd10df91ff20..a4343827f5b7e 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-03-01 +date: 2023-03-02 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 84f7145933da0..cb9fb0099f829 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-03-01 +date: 2023-03-02 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 ffff93a8d3d3c..a1d62d83decbc 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-03-01 +date: 2023-03-02 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 58f563e56b4c0..f2d8d364706e8 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-03-01 +date: 2023-03-02 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 9f76e7a05a1bd..1c9cfd48c4b54 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-03-01 +date: 2023-03-02 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 35ea8b7e28ddc..077424419ae67 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-03-01 +date: 2023-03-02 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 cf0ca55516578..a1249c4b5ba37 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-03-01 +date: 2023-03-02 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 6f4c31dc6eb24..ae450f37bed7c 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-03-01 +date: 2023-03-02 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 217d118b83fd9..cc8dd895b8951 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-03-01 +date: 2023-03-02 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 e4fbf40660418..78208b4775831 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-03-01 +date: 2023-03-02 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 236ea0cd5f1ab..dee012217c67b 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.devdocs.json b/api_docs/data.devdocs.json index 7759142291791..ea8e61e7d1903 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -13729,6 +13729,14 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_view.ts" }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, { "plugin": "unifiedSearch", "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" @@ -13753,14 +13761,6 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, { "plugin": "controls", "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" @@ -21352,6 +21352,14 @@ "plugin": "dataViews", "path": "src/plugins/data_views/common/data_views/data_view.ts" }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, { "plugin": "unifiedSearch", "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" @@ -21376,14 +21384,6 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, { "plugin": "controls", "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" diff --git a/api_docs/data.mdx b/api_docs/data.mdx index a8ff6c781ceec..6545ee735da87 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-03-01 +date: 2023-03-02 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 18f87793f4dad..641d4d68f2dac 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-03-01 +date: 2023-03-02 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 20d3b7417d133..f53eff91b211e 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-03-01 +date: 2023-03-02 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 8401c7e3aa4c0..afb18de3eb68c 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-03-01 +date: 2023-03-02 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 d8f6a38d7d905..895ca68247a5b 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-03-01 +date: 2023-03-02 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 6e13f172d3f04..521c678ffc05d 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.devdocs.json b/api_docs/data_views.devdocs.json index ba7f5aa586f15..45193f697c63e 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -283,6 +283,14 @@ "plugin": "data", "path": "src/plugins/data/public/search/errors/painless_error.tsx" }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, { "plugin": "unifiedSearch", "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" @@ -299,14 +307,6 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, { "plugin": "controls", "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" @@ -8491,6 +8491,14 @@ "plugin": "data", "path": "src/plugins/data/public/search/errors/painless_error.tsx" }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, { "plugin": "unifiedSearch", "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" @@ -8507,14 +8515,6 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, { "plugin": "controls", "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" @@ -15794,6 +15794,14 @@ "plugin": "data", "path": "src/plugins/data/public/search/errors/painless_error.tsx" }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, + { + "plugin": "savedObjectsManagement", + "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" + }, { "plugin": "unifiedSearch", "path": "src/plugins/unified_search/public/autocomplete/providers/value_suggestion_provider.ts" @@ -15810,14 +15818,6 @@ "plugin": "triggersActionsUi", "path": "x-pack/plugins/triggers_actions_ui/public/common/lib/data_apis.ts" }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, - { - "plugin": "savedObjectsManagement", - "path": "src/plugins/saved_objects_management/public/management_section/objects_table/components/flyout.tsx" - }, { "plugin": "controls", "path": "src/plugins/controls/public/services/options_list/options_list_service.ts" diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 2aaecd805c8ae..53cee388cd196 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-03-01 +date: 2023-03-02 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 e4096996b690e..e4fa7ec8e0cbb 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-03-01 +date: 2023-03-02 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 b17477ae78a6f..9639366079728 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -17,9 +17,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Referencing plugin(s) | Remove By | | ---------------|-----------|-----------| | | ml, stackAlerts | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | -| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, data, unifiedSearch, triggersActionsUi, savedObjectsManagement, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, savedObjectsManagement, unifiedSearch, triggersActionsUi, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, dataViews, savedObjectsManagement, unifiedSearch, triggersActionsUi, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover, data | - | +| | @kbn/es-query, securitySolution, timelines, lists, threatIntelligence, data, savedObjectsManagement, unifiedSearch, triggersActionsUi, controls, unifiedFieldList, lens, aiops, ml, infra, visTypeTimeseries, apm, observability, dataVisualizer, fleet, canvas, graph, stackAlerts, synthetics, transform, upgradeAssistant, ux, maps, dataViewManagement, inputControlVis, visDefaultEditor, presentationUtil, visTypeTimelion, visTypeVega, discover | - | | | home, data, esUiShared, spaces, savedObjectsManagement, fleet, observability, ml, apm, enterpriseSearch, indexLifecycleManagement, synthetics, upgradeAssistant, ux, kibanaOverview | - | | | encryptedSavedObjects, actions, data, ml, logstash, securitySolution, cloudChat | - | | | actions, ml, savedObjectsTagging, enterpriseSearch | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 80094a42fb4ef..883246adfda69 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -1176,12 +1176,12 @@ migrates to using the Kibana Privilege model: https://github.com/elastic/kibana/ | | [filter_group.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/filter_group/filter_group.tsx#:~:text=title), [filters_expression_select.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/alerts/monitor_expressions/filters_expression_select.tsx#:~:text=title) | - | | | [stderr_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/synthetics/check_steps/stderr_logs.tsx#:~:text=indexPatternId), [stderr_logs.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/common/components/stderr_logs.tsx#:~:text=indexPatternId) | - | | | [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [alert_messages.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/lib/alert_types/alert_messages.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [uptime_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks), [synthetics_app.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx#:~:text=RedirectAppLinks) | - | -| | [use_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.ts#:~:text=savedObjects), [use_monitor_name.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_config/use_monitor_name.ts#:~:text=savedObjects), [use_location_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/hooks/use_location_monitors.ts#:~:text=savedObjects), [use_locations_api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/hooks/use_locations_api.ts#:~:text=savedObjects), [use_invalid_monitors.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/hooks/use_invalid_monitors.tsx#:~:text=savedObjects), [use_recently_viewed_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts#:~:text=savedObjects), [delete_param.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/global_params/delete_param.tsx#:~:text=savedObjects), [use_location_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.ts#:~:text=savedObjects), [use_locations_api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts#:~:text=savedObjects), [use_monitor_name.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_name.ts#:~:text=savedObjects)+ 1 more | - | -| | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts#:~:text=SavedObjectsClientContract), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts#:~:text=SavedObjectsClientContract), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts#:~:text=SavedObjectsClientContract), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=SavedObjectsClientContract), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=SavedObjectsClientContract), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=SavedObjectsClientContract) | - | -| | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts#:~:text=create), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=create) | - | +| | [use_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.ts#:~:text=savedObjects), [use_monitor_name.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_config/use_monitor_name.ts#:~:text=savedObjects), [use_location_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/hooks/use_location_monitors.ts#:~:text=savedObjects), [use_locations_api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/hooks/use_locations_api.ts#:~:text=savedObjects), [use_invalid_monitors.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/hooks/use_invalid_monitors.tsx#:~:text=savedObjects), [use_recently_viewed_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts#:~:text=savedObjects), [delete_param.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/global_params/delete_param.tsx#:~:text=savedObjects), [use_location_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.ts#:~:text=savedObjects), [use_monitor_name.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_name.ts#:~:text=savedObjects), [plugin.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/plugin.ts#:~:text=savedObjects) | - | +| | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=SavedObjectsClientContract), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=SavedObjectsClientContract), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=SavedObjectsClientContract) | - | +| | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=create) | - | | | [delete_param.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/global_params/delete_param.tsx#:~:text=bulkDelete) | - | | | [use_filters.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.ts#:~:text=find), [use_monitor_name.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_config/use_monitor_name.ts#:~:text=find), [use_location_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/manage_locations/hooks/use_location_monitors.ts#:~:text=find), [use_location_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.ts#:~:text=find), [use_monitor_name.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_name.ts#:~:text=find), [use_filters.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.test.ts#:~:text=find), [use_filters.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/common/monitor_filters/use_filters.test.ts#:~:text=find) | - | -| | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts#:~:text=get), [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=get) | - | +| | [api.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts#:~:text=get) | - | | | [use_invalid_monitors.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/hooks/use_invalid_monitors.tsx#:~:text=bulkResolve), [use_recently_viewed_monitors.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_details/monitor_selector/use_recently_viewed_monitors.ts#:~:text=bulkResolve) | - | | | [synthetics_monitor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/common/types/synthetics_monitor.ts#:~:text=SimpleSavedObject), [synthetics_monitor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/common/types/synthetics_monitor.ts#:~:text=SimpleSavedObject), [synthetics_monitor.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/synthetics/common/types/synthetics_monitor.ts#:~:text=SimpleSavedObject) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 83b680c45c6d5..738aca7a7e31b 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index a5be54c3a993b..304ae62c0106f 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-03-01 +date: 2023-03-02 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 68d7e71d19fcd..17563076bad59 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-03-01 +date: 2023-03-02 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 207042f8c205a..52ccdeefff620 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-03-01 +date: 2023-03-02 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 997bebea4a967..f65e8737f6bbb 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/embeddable.devdocs.json b/api_docs/embeddable.devdocs.json index 9c774d762c515..f0d95e9e1edbd 100644 --- a/api_docs/embeddable.devdocs.json +++ b/api_docs/embeddable.devdocs.json @@ -8174,6 +8174,26 @@ "path": "src/plugins/embeddable/public/plugin.tsx", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "embeddable", + "id": "def-public.EmbeddableStartDependencies.savedObjectsManagement", + "type": "Object", + "tags": [], + "label": "savedObjectsManagement", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsManagement", + "scope": "public", + "docId": "kibSavedObjectsManagementPluginApi", + "section": "def-public.SavedObjectsManagementPluginStart", + "text": "SavedObjectsManagementPluginStart" + } + ], + "path": "src/plugins/embeddable/public/plugin.tsx", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 7dbe14444d9f0..c80efe99fc85f 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.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 | |-------------------|-----------|------------------------|-----------------| -| 538 | 9 | 435 | 4 | +| 539 | 9 | 436 | 4 | ## Client diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 83ae1d0c3da02..6117c6df39dad 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-03-01 +date: 2023-03-02 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 bc81ba849ed3d..dc277f689ef82 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-03-01 +date: 2023-03-02 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 bb071de249983..3e1821034dbd5 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-03-01 +date: 2023-03-02 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 98c959696e829..9d5c5c84ea989 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-03-01 +date: 2023-03-02 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 9f01ece99d2d5..c2f5cac318ca3 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-03-01 +date: 2023-03-02 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 80a488bc472c6..e7718f18bc7f0 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-03-01 +date: 2023-03-02 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 8c666366fc8d6..b630e478cc044 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-03-01 +date: 2023-03-02 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 9fdec0dc8cb79..b4db7b0f3b828 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-03-01 +date: 2023-03-02 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 ec04a0683a4f1..3dbc815880c4a 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-03-01 +date: 2023-03-02 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 d7b940077fb77..4c3a8b11829b2 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-03-01 +date: 2023-03-02 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 a619d11728ba2..a1a701f6ab08d 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-03-01 +date: 2023-03-02 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 30bec93fff3c6..01b55fbf63707 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-03-01 +date: 2023-03-02 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 eeec105f003cc..22ec9b39787cc 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-03-01 +date: 2023-03-02 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 0908cbf569b2b..d74ba9f0b1ee1 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-03-01 +date: 2023-03-02 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 a826b9492c3ea..35e21e3a17c3f 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-03-01 +date: 2023-03-02 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 56f581eff2739..fe87192fe6aaa 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-03-01 +date: 2023-03-02 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 c3ec86cf5b9a8..994784ddab036 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-03-01 +date: 2023-03-02 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 215621e2f70de..1eb3789a95d8a 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-03-01 +date: 2023-03-02 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 9ca0c092ed412..3618e9de943fa 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-03-01 +date: 2023-03-02 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 3cd9a6d0a8187..67b1f2939627f 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-03-01 +date: 2023-03-02 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 60074a15c73e2..9d22d7403800b 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-03-01 +date: 2023-03-02 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 728d3f0f26f7a..aefcd3d2b0047 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-03-01 +date: 2023-03-02 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 c4e44c06c233e..3e398317686ca 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-03-01 +date: 2023-03-02 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 aec2d7668382f..9cf192f9c4f3e 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-03-01 +date: 2023-03-02 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 0c7c522d8cd52..b1896f8199ca0 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-03-01 +date: 2023-03-02 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 12c56be0b77ba..f72c1c07dae47 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-03-01 +date: 2023-03-02 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 5d9f0fa08839e..1361b0c3bbb54 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-03-01 +date: 2023-03-02 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 c5c5a26a41c68..831408669b1c3 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-03-01 +date: 2023-03-02 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 707ae9a95aac6..a2001e302b069 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-03-01 +date: 2023-03-02 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 6e42d9a770f91..a1c917a1d7197 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-03-01 +date: 2023-03-02 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 dfeb32bb9975d..c56a887ea0c31 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-03-01 +date: 2023-03-02 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 d3a18506f2bce..1a2441d2f57f3 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-03-01 +date: 2023-03-02 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 8a11e37afd294..224351c42f871 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-03-01 +date: 2023-03-02 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 adf41779fff68..9aecbf08da449 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-03-01 +date: 2023-03-02 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 efcd3b891dbc6..e3d72fbaa1968 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-03-01 +date: 2023-03-02 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 d1da2608b6daa..d23833d267aac 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-03-01 +date: 2023-03-02 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 7e21ddd11bfd1..c2ecac6ab7a68 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-03-01 +date: 2023-03-02 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 12024f602f215..bacae41837451 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-03-01 +date: 2023-03-02 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 94b33154d07b0..263bad7a01dc3 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts'] --- import kbnAlertsObj from './kbn_alerts.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 8c6a728b96826..9c9ffcd49f74a 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2023-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index e19c88b434998..be08717fd1fbc 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-03-01 +date: 2023-03-02 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 a561d8cd44c93..3efbb27ae6b4c 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-03-01 +date: 2023-03-02 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 6c9c67c02e850..0f590ec71b575 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-03-01 +date: 2023-03-02 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 50a6c08fa198b..7fa02c977ef0f 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-03-01 +date: 2023-03-02 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 e9998ea2c1028..5d1ce84c337fc 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-03-01 +date: 2023-03-02 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 8eaf4e8926976..b5352daa851ae 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-03-01 +date: 2023-03-02 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 cef0978935b54..7f059748811ad 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-03-01 +date: 2023-03-02 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 6b9fb907ac953..643778c571a3f 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-03-01 +date: 2023-03-02 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 ed07b9e5fa4c8..c273ed05035f1 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-03-01 +date: 2023-03-02 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 0649db4100861..f48057fdc63e4 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-03-01 +date: 2023-03-02 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 58f1ad8f586fc..998222ae3142e 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-03-01 +date: 2023-03-02 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 ceb84d0bca94c..df98534f70e2c 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-03-01 +date: 2023-03-02 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 1aecaa5c2de78..8e21de87a558e 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-03-01 +date: 2023-03-02 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 08bdd99ee670e..642195695ef32 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-03-01 +date: 2023-03-02 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 83573b77a2ea3..cae863b3ad48f 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-03-01 +date: 2023-03-02 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 5d002c32c79c1..047e2235c2d02 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-03-01 +date: 2023-03-02 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 08e14a926934e..04d450ae11d4e 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-03-01 +date: 2023-03-02 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 cf1d231ea3a8a..551f02d9542cc 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-03-01 +date: 2023-03-02 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 4927891257687..681ff13ffec2e 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-03-01 +date: 2023-03-02 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 d5477842f3195..5ba8714268011 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-03-01 +date: 2023-03-02 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 f108522506807..a501527e84f43 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-03-01 +date: 2023-03-02 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 79106555bf1b3..306bf1bf3cc04 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-03-01 +date: 2023-03-02 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 c60be8d19bbc4..3eb75ac47f2de 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-03-01 +date: 2023-03-02 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 1d3df732a5c52..1a7154a89ba74 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-03-01 +date: 2023-03-02 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 e9c939110219b..548b1c790d867 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-03-01 +date: 2023-03-02 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 7cb770f30088b..3cd190aefa52b 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-03-01 +date: 2023-03-02 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 502f68f9bafc6..cf2176a083699 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-03-01 +date: 2023-03-02 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 24dd88818d012..ae248ef63ef85 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-03-01 +date: 2023-03-02 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 19be442f12401..53aab7b923e5b 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-03-01 +date: 2023-03-02 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 3cf223d811a50..959fa6d5e4fcb 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-03-01 +date: 2023-03-02 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 15c50b14ddbcc..39cc8d5e65dd7 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-03-01 +date: 2023-03-02 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 949d647c0fb4e..693479a213c6b 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-03-01 +date: 2023-03-02 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 423d3d61683c8..ba1667310138f 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-03-01 +date: 2023-03-02 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 611a4afcf75de..ea4a5288ef4d7 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-03-01 +date: 2023-03-02 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 304c873831fd4..62494fbd712d9 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-03-01 +date: 2023-03-02 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 25efcb0bb8a3a..ed5a63bd6b481 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-03-01 +date: 2023-03-02 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 892c8c76b89b1..0ae948a0f1967 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-03-01 +date: 2023-03-02 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 fd8b79f885895..f388bdba22b0d 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-03-01 +date: 2023-03-02 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 d4b49e2544472..27b3210a296b2 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-03-01 +date: 2023-03-02 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 52e6b016b9574..00d7805a17f85 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-03-01 +date: 2023-03-02 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 ef0f271766eb3..c60a9cea687b8 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-03-01 +date: 2023-03-02 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 6f270b901e057..a8b27d9611a63 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-03-01 +date: 2023-03-02 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 56dd0c4a1e434..4fc1e24faf504 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-03-01 +date: 2023-03-02 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 b2aeca83bc43c..7fa62be774cc5 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-03-01 +date: 2023-03-02 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 365cb851bbd98..daec7cc05a345 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-03-01 +date: 2023-03-02 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 9cc170403d766..8c8951b3d7c37 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-03-01 +date: 2023-03-02 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 588562c1397a9..62ad4d1aa9dc3 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-03-01 +date: 2023-03-02 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 d298d07536f0e..638f292fdb98c 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-03-01 +date: 2023-03-02 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 06c64391d23da..38b47cd1d1fae 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-03-01 +date: 2023-03-02 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 5093d5f89d334..eadd485abc837 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-03-01 +date: 2023-03-02 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 284888ef0efa2..f0a27f2cfa02e 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-03-01 +date: 2023-03-02 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 897aca49852db..6a3fc90b2c703 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-03-01 +date: 2023-03-02 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 c728f1c726c88..11d112819ab49 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-03-01 +date: 2023-03-02 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 3bf75aeb93ca0..aa063965b3ee7 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-03-01 +date: 2023-03-02 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 f39bbcfc2e829..86828fa0fdd9f 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-03-01 +date: 2023-03-02 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 8e0adfa179bd7..04eb2582e72a4 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-03-01 +date: 2023-03-02 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 4fe374fa41898..353bff8c49d62 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-03-01 +date: 2023-03-02 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 2a0d3f8cdcfdc..6aa7969a43b51 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-03-01 +date: 2023-03-02 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 0cb7943689f4c..7bd406d920bc6 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-03-01 +date: 2023-03-02 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 afbe971181a21..722fa3fa285d8 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-03-01 +date: 2023-03-02 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 45246eee42da7..665a262270ea7 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-03-01 +date: 2023-03-02 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 b4333d4f00a98..d9f84f98feb3d 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-03-01 +date: 2023-03-02 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 945ab8c314633..65a8d9b69582b 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-03-01 +date: 2023-03-02 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 2ded9a267e91e..462a0bf5285f3 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-03-01 +date: 2023-03-02 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 9611a707c6dc6..5db940d54a40d 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-03-01 +date: 2023-03-02 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 1aea29fbe68a7..7e9c1a6c6ae2e 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-03-01 +date: 2023-03-02 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 58be39da715ec..261fdab10d421 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-03-01 +date: 2023-03-02 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 30091366a1a87..d6a569a5f4c4b 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-03-01 +date: 2023-03-02 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 54a70b26db85c..4142f67ae6fd8 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-03-01 +date: 2023-03-02 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 50d2412b58338..3f5406f8fc672 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-03-01 +date: 2023-03-02 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 efeac69f19104..649286af18285 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-03-01 +date: 2023-03-02 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 d96d09fa696bd..9266b9941613a 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-03-01 +date: 2023-03-02 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 057a636ae9fe1..2bc3ed1923ee2 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-03-01 +date: 2023-03-02 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 05f8ec97e7a28..a12129bf7ab2f 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-03-01 +date: 2023-03-02 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 22b6049591aa8..cb44e1f6f2a5f 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-03-01 +date: 2023-03-02 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 aea775f4fbbf8..3b12b50d38668 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-03-01 +date: 2023-03-02 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 1bd54e9d84665..c5f3a640b13dc 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-03-01 +date: 2023-03-02 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 d18ea0eb5556b..4fa17b4ed208e 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-03-01 +date: 2023-03-02 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 f4cf588a1fd8b..2f4f45857690a 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-03-01 +date: 2023-03-02 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 5a758ea2d6657..80dc6b3f42667 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-03-01 +date: 2023-03-02 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 c0c4118d6aff2..1ecefa27b6cd3 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-03-01 +date: 2023-03-02 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 c794d34a2c2ed..202214f6b557d 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-03-01 +date: 2023-03-02 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 d9d062fae9ca7..4afc04a60783b 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-03-01 +date: 2023-03-02 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 65e0ad45dffbe..b2ddbf0a9010f 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-03-01 +date: 2023-03-02 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 4acd4a82dab31..474ea66f88224 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-03-01 +date: 2023-03-02 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 f0f05e7622c07..9b5f7fc44fde5 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-03-01 +date: 2023-03-02 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 0408099e8cc8c..442597a23b31c 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-03-01 +date: 2023-03-02 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 d0dfa1fd74e5e..e3e51a50d3922 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-03-01 +date: 2023-03-02 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 85dfa7ad743be..f94d4846c71f8 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-03-01 +date: 2023-03-02 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 22496bc87fb99..ae3c02e387d5d 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-03-01 +date: 2023-03-02 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 b4cad3b542bd7..fdbcf724f249f 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-03-01 +date: 2023-03-02 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 3fc2357f914eb..099083e2d0951 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-03-01 +date: 2023-03-02 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 7ac2f6b11f718..5f3f3669b8801 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-03-01 +date: 2023-03-02 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 f1e3e2fd849bd..f279de0f63180 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-03-01 +date: 2023-03-02 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 85fd6e03831da..d3afd758189df 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-03-01 +date: 2023-03-02 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 aa21951eb20b1..2e64643ebfbbe 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-03-01 +date: 2023-03-02 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 ed909df42d85d..e7a36fd46d9b7 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-03-01 +date: 2023-03-02 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 25e80d604cfcf..f638b954afa2c 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-03-01 +date: 2023-03-02 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 4baa71f0f02b1..4978c2bcf1edc 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-03-01 +date: 2023-03-02 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 389b11f7db33c..af4705eebf0af 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-03-01 +date: 2023-03-02 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 89701f27f330d..b586c524253a4 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-03-01 +date: 2023-03-02 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 a89aa6d00bb67..eeb40f40210db 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-03-01 +date: 2023-03-02 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 5ebbce42719eb..6fb7956371da3 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-03-01 +date: 2023-03-02 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 289f2bdc2d395..f68a4931bbade 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-03-01 +date: 2023-03-02 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 fafb8cc5d0390..0e32141f1eada 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-03-01 +date: 2023-03-02 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 f53885b8e9dac..165f46f6141ee 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-03-01 +date: 2023-03-02 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 1eadd9211d2bc..ca24813984b7b 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-03-01 +date: 2023-03-02 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 54085404b5a38..9df4ebd75e861 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-03-01 +date: 2023-03-02 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 c572a6fa7b685..828d24502d372 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-03-01 +date: 2023-03-02 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.devdocs.json b/api_docs/kbn_core_lifecycle_browser.devdocs.json index 4f364f01dd84f..fa4c32568aba3 100644 --- a/api_docs/kbn_core_lifecycle_browser.devdocs.json +++ b/api_docs/kbn_core_lifecycle_browser.devdocs.json @@ -797,10 +797,6 @@ "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_location_monitors.ts" }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts" - }, { "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_name.ts" diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index aedc842ef153f..e68f69e5b2541 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-03-01 +date: 2023-03-02 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 75b29d3494e6c..47d4140fa4fa3 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-03-01 +date: 2023-03-02 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 1a706abe318b6..eb11dad2ad958 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-03-01 +date: 2023-03-02 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 bbfd13ed51049..b84dcef82884e 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-03-01 +date: 2023-03-02 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 136c12c56ac4b..39c7734369d0a 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-03-01 +date: 2023-03-02 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 4ecb58cdd9906..e1c35d2d1849f 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-03-01 +date: 2023-03-02 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 144ae1d9d1e8c..854f2e1c444f1 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-03-01 +date: 2023-03-02 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 517f631ad858f..be6cd0ddc3609 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-03-01 +date: 2023-03-02 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 e943f5e00a460..1371904a744ae 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-03-01 +date: 2023-03-02 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 fd538cc9343ac..44835e9fa7d13 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-03-01 +date: 2023-03-02 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 8e2b9d0a15b1e..3d18047440579 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-03-01 +date: 2023-03-02 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 853a3c1e872d7..0366bf0bddf29 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-03-01 +date: 2023-03-02 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 d5aee4c7654e0..5653d21b167ea 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-03-01 +date: 2023-03-02 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 24332a70fa701..8641f8766334b 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-03-01 +date: 2023-03-02 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 30db9430b487d..0bf561242359e 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-03-01 +date: 2023-03-02 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 492b442149946..93c4da6e7f8fb 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-03-01 +date: 2023-03-02 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 f7b33406a3820..6e09f365f5ecf 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-03-01 +date: 2023-03-02 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 feb9dc2ab14ec..a40eb40c54868 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-03-01 +date: 2023-03-02 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 c3932ab62690f..d113868c4b205 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-03-01 +date: 2023-03-02 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 9ed261b31e520..701025f3a867f 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-03-01 +date: 2023-03-02 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 53901c99c26eb..46fb2d4432b9f 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-03-01 +date: 2023-03-02 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 7ef2add6594c3..ade4741ff96e4 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-03-01 +date: 2023-03-02 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 c5b2275067509..531d085b34330 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-03-01 +date: 2023-03-02 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 91222ce58d1f3..a6fefddb61000 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-03-01 +date: 2023-03-02 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 9f893da6f4cdb..1b1a4764cfca8 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-03-01 +date: 2023-03-02 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 ac6c24d330cd0..d21b513671928 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-03-01 +date: 2023-03-02 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 c77bdc341cbae..bbe16935a49c7 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-03-01 +date: 2023-03-02 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 ea41b943c5e51..13974d291b540 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-03-01 +date: 2023-03-02 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 26c8e4e5cd2c1..6e1190eaa10d1 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-03-01 +date: 2023-03-02 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 d2a828db81119..c993507dfdb73 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-03-01 +date: 2023-03-02 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 2d0cf533be77e..8b8f56bc6d341 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-03-01 +date: 2023-03-02 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 da0ab5e88b51e..92892c2f4d607 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-03-01 +date: 2023-03-02 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 a7a23df24f99c..b4d2dacecaf42 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-03-01 +date: 2023-03-02 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 14d1c29129edb..11d778cf27954 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-03-01 +date: 2023-03-02 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.devdocs.json b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json index a7830aa795a0b..755eca219cfc1 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json @@ -1278,18 +1278,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/containers/dashboards/utils.ts" }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts" - }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts" - }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts" - }, { "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts" @@ -1558,10 +1546,6 @@ "plugin": "graph", "path": "x-pack/plugins/graph/public/helpers/saved_workspace_utils.ts" }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts" - }, { "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts" @@ -2523,10 +2507,6 @@ "plugin": "monitoring", "path": "x-pack/plugins/monitoring/public/application/pages/elasticsearch/ingest_pipeline_modal.tsx" }, - { - "plugin": "synthetics", - "path": "x-pack/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts" - }, { "plugin": "synthetics", "path": "x-pack/plugins/synthetics/public/legacy_uptime/state/private_locations/api.ts" diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index b234e165f5193..9ab3d991bda82 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-03-01 +date: 2023-03-02 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 5ac110837d25a..42c6a15446502 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-03-01 +date: 2023-03-02 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 a7883f71673c9..2aeeb00ad057c 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-03-01 +date: 2023-03-02 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 6744441152126..8adfa0bfd41b4 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-03-01 +date: 2023-03-02 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 f9423495a45b7..750f6db42d9fc 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-03-01 +date: 2023-03-02 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 e40ed8d0d733d..0e82b824c6b63 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-03-01 +date: 2023-03-02 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 688d1d555bec8..ec4157e9a46e1 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-03-01 +date: 2023-03-02 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 8713804799d47..f57b3dae843dd 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-03-01 +date: 2023-03-02 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 48afdf8837561..0b4311260a777 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-03-01 +date: 2023-03-02 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.devdocs.json b/api_docs/kbn_core_saved_objects_common.devdocs.json index 0c231f1ff4878..62156f3b4dc5a 100644 --- a/api_docs/kbn_core_saved_objects_common.devdocs.json +++ b/api_docs/kbn_core_saved_objects_common.devdocs.json @@ -2800,6 +2800,22 @@ "plugin": "data", "path": "src/plugins/data/common/query/persistable_state.ts" }, + { + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + }, + { + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + }, + { + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + }, + { + "plugin": "savedObjectsTaggingOss", + "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" + }, { "plugin": "embeddable", "path": "src/plugins/embeddable/common/lib/migrate_base_input.ts" @@ -2820,22 +2836,6 @@ "plugin": "embeddable", "path": "src/plugins/embeddable/common/lib/inject.ts" }, - { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" - }, - { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" - }, - { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" - }, - { - "plugin": "savedObjectsTaggingOss", - "path": "src/plugins/saved_objects_tagging_oss/public/api.ts" - }, { "plugin": "visualizations", "path": "src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts" diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index a335192d95087..a7da75722e944 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-03-01 +date: 2023-03-02 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 3f22fd666b55c..7b218a2ad32f0 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-03-01 +date: 2023-03-02 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 539a0fc832619..6c75150030f56 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-03-01 +date: 2023-03-02 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.devdocs.json b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json index 0134af64ddd5c..64a0494b9127c 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.devdocs.json @@ -1771,37 +1771,39 @@ }, { "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", - "id": "def-common.updateTargetMappingsMeta", + "id": "def-common.updateMappings", "type": "Function", "tags": [], - "label": "updateTargetMappingsMeta", + "label": "updateMappings", "description": [ - "\nUpdates an index's mappings _meta information" + "\nUpdates an index's mappings and runs an pickupUpdatedMappings task so that the mapping\nchanges are \"picked up\". Returns a taskId to track progress." ], "signature": [ - "({ client, index, meta, }: ", - "UpdateTargetMappingsMetaParams", + "({ client, index, mappings, }: ", + "UpdateMappingsParams", ") => ", "TaskEither", "<", "RetryableEsClientError", - ", \"update_mappings_meta_succeeded\">" + " | ", + "IncompatibleMappingException", + ", \"update_mappings_succeeded\">" ], - "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.ts", + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/core-saved-objects-migration-server-internal", - "id": "def-common.updateTargetMappingsMeta.$1", + "id": "def-common.updateMappings.$1", "type": "Object", "tags": [], - "label": "{\n client,\n index,\n meta,\n }", + "label": "{\n client,\n index,\n mappings,\n}", "description": [], "signature": [ - "UpdateTargetMappingsMetaParams" + "UpdateMappingsParams" ], - "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_target_mappings_meta.ts", + "path": "packages/core/saved-objects/core-saved-objects-migration-server-internal/src/actions/update_mappings.ts", "deprecated": false, "trackAdoption": false, "isRequired": true 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 9b334a940a32d..898a1e2d4ea8b 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-03-01 +date: 2023-03-02 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 29cea64b32846..b9ef91939e896 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-03-01 +date: 2023-03-02 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 eca87703c355f..d203957246f69 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-03-01 +date: 2023-03-02 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 c8af573bde495..4ab8eecaa1622 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-03-01 +date: 2023-03-02 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 7c2ec8a7a83ee..31fb2ac1d9941 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-03-01 +date: 2023-03-02 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 e210a1228ec23..c1c957a5344ba 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-03-01 +date: 2023-03-02 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 a11aed7d32d8a..7653cf7c2050a 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-03-01 +date: 2023-03-02 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 d7e00df6fc8a3..17c1f3117f330 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-03-01 +date: 2023-03-02 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 cb0d5036718ed..bd694773a5f16 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-03-01 +date: 2023-03-02 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 0a96f49ffa4f6..d5f3d4039a718 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-03-01 +date: 2023-03-02 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 327e3a271a3dd..504c5c613feae 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-03-01 +date: 2023-03-02 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 c96e4fd0af6a1..33443ded64359 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-03-01 +date: 2023-03-02 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 096a5cf9c010d..4f31e6de42168 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-03-01 +date: 2023-03-02 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 fb1f6004cad61..65d472a647d69 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-03-01 +date: 2023-03-02 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 5bdb15b6bf91c..fc0e425c6fd46 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-03-01 +date: 2023-03-02 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 698eacb03771d..0d5e270a9df43 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-03-01 +date: 2023-03-02 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 54165d1e0c654..7353d7a47d85e 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-03-01 +date: 2023-03-02 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 9ef8f2333fe52..f4df154e80c44 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-03-01 +date: 2023-03-02 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 4d0b8b852b174..5edaedd815f0e 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-03-01 +date: 2023-03-02 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 fc433f2993985..65093899ea9b9 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-03-01 +date: 2023-03-02 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 60bdeaf388128..4a1f5feb62f3f 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-03-01 +date: 2023-03-02 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 aba1f92ba7723..135b54ce7e869 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-03-01 +date: 2023-03-02 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 a5e94c54239ea..213dbf4d62c16 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-03-01 +date: 2023-03-02 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 7bb50d06aebc7..0d5ad1eed566d 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-03-01 +date: 2023-03-02 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 3c1d1da90502f..2e81fbb70e4ae 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-03-01 +date: 2023-03-02 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 db46d9394da82..b188b63b47ec9 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-03-01 +date: 2023-03-02 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 253d2892a934b..ed6e1939b36f7 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-03-01 +date: 2023-03-02 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 da766dfd397e6..da52ba5ced2bd 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-03-01 +date: 2023-03-02 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 fd300908ba5ff..878698459b87b 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-03-01 +date: 2023-03-02 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 611326ca0ca1b..fa020d9f7e28a 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-03-01 +date: 2023-03-02 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 b67b17f6a2b76..9d7d13934ab24 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-03-01 +date: 2023-03-02 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 6b16b88b54504..1f710dbf67056 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-03-01 +date: 2023-03-02 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 bcf02b08bbd13..75eabd2444aaf 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-03-01 +date: 2023-03-02 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 9608ba018aa9b..cc58fa1feb24c 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-03-01 +date: 2023-03-02 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 8ae612c0cd7cf..a64f39e0387e7 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-03-01 +date: 2023-03-02 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 a620da438f055..3247d3e925491 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-03-01 +date: 2023-03-02 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 6e9803ca19ca3..a470e64f11a32 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-03-01 +date: 2023-03-02 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 5c26c1f7ae912..0a96000e4bb7d 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-03-01 +date: 2023-03-02 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 92321620ae072..9983ad5184956 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-03-01 +date: 2023-03-02 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 86c05cddc426a..3086015b75ea1 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-03-01 +date: 2023-03-02 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 833dce59d69af..e682604f096df 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-03-01 +date: 2023-03-02 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 b1052fab18d8a..4182480b6429b 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-03-01 +date: 2023-03-02 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 f2edd04564e87..130281480b778 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-03-01 +date: 2023-03-02 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 25691edd038ab..6432d72fe9933 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-03-01 +date: 2023-03-02 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 a775b77d0c03b..da4b187dd9845 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-03-01 +date: 2023-03-02 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 40d30548e2c75..2c7721a298282 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-03-01 +date: 2023-03-02 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 53f09c9a56f21..5a68fd11c6e47 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-03-01 +date: 2023-03-02 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 c755e7e49ec70..e08fd251f331f 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 8cd64f4bf5007..ab9a929a7a38f 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2023-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 882ddbccdafc2..ef0856fc946b1 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-03-01 +date: 2023-03-02 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 9408b6512bfc6..449cae1f26ea8 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-03-01 +date: 2023-03-02 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 7aa6edd01eaed..91d09b17dd4ec 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-03-01 +date: 2023-03-02 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 c96a7fec26b54..65adba923f05f 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-03-01 +date: 2023-03-02 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 41402fb54e395..880e6de629200 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-03-01 +date: 2023-03-02 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 5892aaecb2692..5878786295778 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-03-01 +date: 2023-03-02 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 58903a768057d..9425661e63606 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-03-01 +date: 2023-03-02 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 638f50b6e417a..888f6ded8526c 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-03-01 +date: 2023-03-02 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 f6f8c68a13a53..c22f3d87fbbed 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-03-01 +date: 2023-03-02 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 a89d578374865..a7c40f3fe82b6 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-03-01 +date: 2023-03-02 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 dcd9cecd5658a..86ea86435e56b 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-03-01 +date: 2023-03-02 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 625e6d1fc8700..117c6131cde4a 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-03-01 +date: 2023-03-02 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 d724067993dff..1319962df3f2b 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-03-01 +date: 2023-03-02 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 6d236d56a476c..23a48bca32834 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-03-01 +date: 2023-03-02 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 60f0704834cb7..413243d232272 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-03-01 +date: 2023-03-02 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 901358d2ad029..55386dee3d910 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-03-01 +date: 2023-03-02 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 8be26edb38791..ca19c050cf54f 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-03-01 +date: 2023-03-02 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 7cf30e73b07e4..9172eb25ebd57 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-03-01 +date: 2023-03-02 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 5b32cf0eab32b..31cf48b2c964a 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-03-01 +date: 2023-03-02 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 000ee3800cb54..f0205840574a5 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-03-01 +date: 2023-03-02 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 e0814e0c41bce..d019150acefd2 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-03-01 +date: 2023-03-02 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 28ad3c57ee2b1..a4e1e123ef2a3 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-03-01 +date: 2023-03-02 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 9e6c619a43f72..cf68bcaa4b420 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-03-01 +date: 2023-03-02 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 2b6014f157459..50d3deb0458c8 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-03-01 +date: 2023-03-02 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 82fb3b8156135..3127057ccd8c4 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-03-01 +date: 2023-03-02 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 e22d099c43982..70aa629bdf80b 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-03-01 +date: 2023-03-02 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 7106fef0d31ec..9ef0f2503787d 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-03-01 +date: 2023-03-02 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 da6012691ecbe..36b9c12cf8d9d 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-03-01 +date: 2023-03-02 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 e2ac91904af64..8fa8dfb1d8949 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-03-01 +date: 2023-03-02 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 76e448217a11e..408295f5ee767 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-03-01 +date: 2023-03-02 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 1aaaba5d9d1b1..81bd4a60e0987 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-03-01 +date: 2023-03-02 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 b605bd7a7d0c1..9507eea80b252 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-03-01 +date: 2023-03-02 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 b58e96af08251..7f2f96360ee86 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-03-01 +date: 2023-03-02 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 0b3b1dcbb8d71..438c5d5888eb9 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-03-01 +date: 2023-03-02 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 6b8831494e1fc..317ff8207a0c7 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-03-01 +date: 2023-03-02 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 fefd5513c3a89..421a949c6eae8 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-03-01 +date: 2023-03-02 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 0daafacb70363..7f3b1642e85d7 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-03-01 +date: 2023-03-02 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 135064793ced7..bf6e073992a21 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-03-01 +date: 2023-03-02 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 2e7737d3d09a9..0778f126ccf81 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-03-01 +date: 2023-03-02 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 1b0874efd96a0..4cab2f5a9cf67 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-03-01 +date: 2023-03-02 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 e626443c3a86c..4f57a93db4a55 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-03-01 +date: 2023-03-02 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 97cf561b76dbe..8ffc7c7df9420 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-03-01 +date: 2023-03-02 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 bb83af20d577b..91d1a67494952 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-03-01 +date: 2023-03-02 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 ed3fd24bf1ca0..c28da4d0951a8 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-03-01 +date: 2023-03-02 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 09b2b34589146..72a1e859e649e 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-03-01 +date: 2023-03-02 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 50073a95415d4..31f656256f6e1 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-03-01 +date: 2023-03-02 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 95ddbf97b66e6..a7d43f07fa3d2 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-03-01 +date: 2023-03-02 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 f3b12dba64e8f..9b4a4d1967d67 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-03-01 +date: 2023-03-02 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 8cfec1a146f1f..4265f52b32192 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-03-01 +date: 2023-03-02 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 e2d46df9fa528..bdbe6ca5f7874 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-03-01 +date: 2023-03-02 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 f65f4b5d15f06..d1aba2986d80b 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-03-01 +date: 2023-03-02 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 6db5d2665ed2d..cf9e283e2ce9d 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-03-01 +date: 2023-03-02 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 4fa8e0495146f..3cea3ef0fe53b 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-03-01 +date: 2023-03-02 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 dcf633ba8463d..ae89b69f48690 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-03-01 +date: 2023-03-02 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 24f4035a6e10f..d1526b7f60044 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-03-01 +date: 2023-03-02 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 115cb421ce21e..c2ecb1dbe34d5 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-03-01 +date: 2023-03-02 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 1bdb1d69ada89..6788608bcb84e 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-03-01 +date: 2023-03-02 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 666f7d64dc4c0..2ec3f8381831f 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-03-01 +date: 2023-03-02 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 10a5bd75e918e..0ca59b9fe847c 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-03-01 +date: 2023-03-02 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 4f279c8da7457..3beb7403b600b 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-03-01 +date: 2023-03-02 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 21c514be81803..0ee158f6baaf6 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-03-01 +date: 2023-03-02 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 30d9b478e5fb2..a2d1484550fc9 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-03-01 +date: 2023-03-02 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 a9e0ce333f4ac..a8005a4385573 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-03-01 +date: 2023-03-02 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 b75e7bd174f09..063dd41fd98ff 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-03-01 +date: 2023-03-02 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 4608fd2d9fae0..737057e8c0e05 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-03-01 +date: 2023-03-02 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 dbed2431570ba..b29158d647065 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-03-01 +date: 2023-03-02 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 49369a523c57d..a3a55240b0af9 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-03-01 +date: 2023-03-02 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 de603c176f88d..a56cf6c0bfbc3 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-03-01 +date: 2023-03-02 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 6dc92cb308995..6819d2c072e27 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-03-01 +date: 2023-03-02 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 d18090ddcfca4..8ab84fc256c3c 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-03-01 +date: 2023-03-02 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 d5438a3b81231..95898936e597e 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-03-01 +date: 2023-03-02 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 e7f87b3faead1..7c89c2313936f 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-03-01 +date: 2023-03-02 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 bbc60b7b0930e..409920c862e2f 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-03-01 +date: 2023-03-02 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 f96d798bfdd70..c2e953437d99f 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-03-01 +date: 2023-03-02 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 6ed126b1f0272..5d7124ba4df40 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-03-01 +date: 2023-03-02 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 5059a2104ecc6..349b4336f58e2 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-03-01 +date: 2023-03-02 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 99a891466643c..e0989c1f51cec 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-03-01 +date: 2023-03-02 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 48e442ff2f4a7..8d407169060fc 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-03-01 +date: 2023-03-02 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_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index 9f65fa210e7b8..09dd4674a2d1f 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2023-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index 017044bc1816e..4ea964c495788 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-03-01 +date: 2023-03-02 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 da482330aa69f..f5103df1642ea 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-03-01 +date: 2023-03-02 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 dc7da9fdb3de0..97f45e6f83b2c 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-03-01 +date: 2023-03-02 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 34433ea142c25..f67da8f76056e 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-03-01 +date: 2023-03-02 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 16a4ef53f43e0..5de34430503ce 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-03-01 +date: 2023-03-02 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 cb9dd8a0c0be1..b9c09753d8c3c 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-03-01 +date: 2023-03-02 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 5e2e601161b23..925939b7b3b14 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-03-01 +date: 2023-03-02 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 c721d2065548a..aead1c8075be1 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-03-01 +date: 2023-03-02 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 32ccb3a824df6..467752087fbd1 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-03-01 +date: 2023-03-02 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 449c6cb561b0f..b8e9b22f1f1e7 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-03-01 +date: 2023-03-02 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 8eb428b3ec1fd..18e62b3d81c71 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-03-01 +date: 2023-03-02 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 34cc61f2f9c01..129bdc8d51894 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-03-01 +date: 2023-03-02 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 08aab682ce2e6..09ae4255ca89b 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-03-01 +date: 2023-03-02 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 9824ac22ba569..1fbeb1e9d68db 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-03-01 +date: 2023-03-02 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 cd3c126d99beb..8caedf2cd62ba 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-03-01 +date: 2023-03-02 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 f2df637ff592a..c7bb81745e1b9 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-03-01 +date: 2023-03-02 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 93dda125813c3..5db172a4f79f4 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-03-01 +date: 2023-03-02 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 2c0e1ec941c8d..a26fb1bdd2f0f 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-03-01 +date: 2023-03-02 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 7e2646fc8085a..db19f5d6acdfe 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-03-01 +date: 2023-03-02 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 2ace684381a43..f9d52f03f61e1 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-03-01 +date: 2023-03-02 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 440066e3a8f57..3235db692a3da 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-03-01 +date: 2023-03-02 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 43b990ab9241f..85372208f09f1 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-03-01 +date: 2023-03-02 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 3ba733b898ba3..93ac6e208bfb2 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-03-01 +date: 2023-03-02 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 62b3ffd910949..de7c54411e4da 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-03-01 +date: 2023-03-02 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 2a7caa471b5ac..167415f51c2a2 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-03-01 +date: 2023-03-02 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 77215eafe5c39..c52546abcb1dd 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-03-01 +date: 2023-03-02 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 e123f38fb650b..10c6b0eaa4a86 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-03-01 +date: 2023-03-02 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 7f6765e55f8e4..cfa11b343e00c 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-03-01 +date: 2023-03-02 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 a4a057a5ea50a..81664623edf20 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-03-01 +date: 2023-03-02 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 a957674b23663..dba39c49e42a7 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-03-01 +date: 2023-03-02 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 9614a088a92bc..151f72a73b89f 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-03-01 +date: 2023-03-02 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 c557e001a9435..3751fd6bbc8e7 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-03-01 +date: 2023-03-02 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 25eee237600e1..a3f6b269e3d08 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-03-01 +date: 2023-03-02 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 78ba4948685c5..76fa71100242c 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-03-01 +date: 2023-03-02 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 91cffd61ed3b8..9a28336a7b258 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-03-01 +date: 2023-03-02 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 6a1a4743dd6e1..5868864ad22d9 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-03-01 +date: 2023-03-02 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 aac73b858246a..2cceab118c4e8 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-03-01 +date: 2023-03-02 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 4cc5120445c02..1119cd67540c1 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-03-01 +date: 2023-03-02 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 fca8308cff965..0f7c8eaa8b238 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-03-01 +date: 2023-03-02 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 f6106da7ed875..68900129865df 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-03-01 +date: 2023-03-02 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 75a89bba49dca..768b70d4e2d81 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-03-01 +date: 2023-03-02 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 3ee6c92133ecc..902a7bf6ef8f8 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-03-01 +date: 2023-03-02 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 a5833d2b4ed60..001f3e5200b3d 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-03-01 +date: 2023-03-02 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 85dc335a2bb76..fcfbba697a2d6 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-03-01 +date: 2023-03-02 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 5dc2d050d2806..f4a57359de52a 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-03-01 +date: 2023-03-02 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 f70f533212865..b9ad74d6e1aa8 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-03-01 +date: 2023-03-02 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 3bed1d4269ddb..5a3615f9f57d7 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-03-01 +date: 2023-03-02 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 12c873652a03e..81c6306fdfb45 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-03-01 +date: 2023-03-02 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 01d10baf1cbed..c3bd6e26c3d3e 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-03-01 +date: 2023-03-02 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 3dc29d6ecc73e..5ed7138b508e1 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-03-01 +date: 2023-03-02 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 c7783c09c4649..4e5cb6c23130f 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-03-01 +date: 2023-03-02 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 34117f2a0bb22..5048d4ae336be 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-03-01 +date: 2023-03-02 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 65eee5cb0ce4a..e0af238c7a65f 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-03-01 +date: 2023-03-02 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 98ebb58f999bb..b680dd963f29d 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-03-01 +date: 2023-03-02 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 94eda5f98ae19..4221afac3fc65 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-03-01 +date: 2023-03-02 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 f296fc984ecb4..0135d2c83b89c 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-03-01 +date: 2023-03-02 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 f44c6c7d72960..2ddeb72c315bd 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-03-01 +date: 2023-03-02 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 063b121d33eeb..e49b1eb30ea03 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-03-01 +date: 2023-03-02 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 07694d7e71b2f..3873c26812adc 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-03-01 +date: 2023-03-02 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 60334ad4da977..d40a6cb637bff 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-03-01 +date: 2023-03-02 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 d64152c39b1ac..53d6138aedc32 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-03-01 +date: 2023-03-02 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 cb334f1c5899e..dc6e65ab31771 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-03-01 +date: 2023-03-02 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 cb927160b6980..f91125db2e4b1 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-03-01 +date: 2023-03-02 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 15c641bc7406a..0bc9d3113ffee 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -4552,7 +4552,8 @@ "docId": "kibSpacesPluginApi", "section": "def-public.SpacesApi", "text": "SpacesApi" - } + }, + " | undefined" ], "path": "x-pack/plugins/observability/public/plugin.ts", "deprecated": false, diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 1e474ec45c730..e8133c325a091 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-03-01 +date: 2023-03-02 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 876a6cbb91d01..4fb5bf0000472 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-03-01 +date: 2023-03-02 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 0258630d7d754..329f8fa2a3f3e 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 67878 | 515 | 58596 | 1234 | +| 67884 | 515 | 58602 | 1234 | ## Plugin Directory @@ -64,7 +64,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 97 | 0 | 78 | 7 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | APIs used to assess the quality of data in Elasticsearch indexes | 2 | 0 | 0 | 0 | -| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 538 | 9 | 435 | 4 | +| | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds embeddables service to Kibana | 539 | 9 | 436 | 4 | | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides encryption and decryption utilities for saved objects containing sensitive information. | 51 | 0 | 44 | 0 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | Adds dashboards for discovering and managing Enterprise Search products. | 9 | 0 | 9 | 0 | @@ -138,7 +138,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 258 | 0 | 229 | 13 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 24 | 0 | 19 | 2 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 231 | 2 | 180 | 5 | -| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 39 | 0 | 39 | 0 | +| | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 44 | 0 | 44 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 154 | 0 | 140 | 2 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 79 | 0 | 73 | 3 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 100 | 0 | 52 | 1 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index 10ac8aa29d17d..bd3fea040e1e2 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-03-01 +date: 2023-03-02 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 78f89c756ed1a..55a72a326e1a1 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-03-01 +date: 2023-03-02 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 dad0ad96c8b86..27991d6f57a32 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-03-01 +date: 2023-03-02 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 a163a3e5f48fc..85cd473879d34 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-03-01 +date: 2023-03-02 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 695c084c67059..8acc1623aadc8 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-03-01 +date: 2023-03-02 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 546f47c4b94aa..f1367bb632c47 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-03-01 +date: 2023-03-02 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 300fb2cc0fa5e..40cbcf1dc389a 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-03-01 +date: 2023-03-02 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 0e01a4ef5ae8f..0d20d5d2b96d1 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.devdocs.json b/api_docs/saved_objects_finder.devdocs.json index 71969f4a97a60..08991612ff496 100644 --- a/api_docs/saved_objects_finder.devdocs.json +++ b/api_docs/saved_objects_finder.devdocs.json @@ -3,6 +3,149 @@ "client": { "classes": [], "functions": [ + { + "parentPluginId": "savedObjectsFinder", + "id": "def-public.getSavedObjectFinder", + "type": "Function", + "tags": [], + "label": "getSavedObjectFinder", + "description": [], + "signature": [ + "(uiSettings: ", + { + "pluginId": "@kbn/core-ui-settings-browser", + "scope": "common", + "docId": "kibKbnCoreUiSettingsBrowserPluginApi", + "section": "def-common.IUiSettingsClient", + "text": "IUiSettingsClient" + }, + ", http: ", + { + "pluginId": "@kbn/core-http-browser", + "scope": "common", + "docId": "kibKbnCoreHttpBrowserPluginApi", + "section": "def-common.HttpSetup", + "text": "HttpSetup" + }, + ", savedObjectsManagement: ", + { + "pluginId": "savedObjectsManagement", + "scope": "public", + "docId": "kibSavedObjectsManagementPluginApi", + "section": "def-public.SavedObjectsManagementPluginStart", + "text": "SavedObjectsManagementPluginStart" + }, + ", savedObjectsTagging?: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "public", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-public.SavedObjectsTaggingApi", + "text": "SavedObjectsTaggingApi" + }, + " | undefined) => (props: ", + { + "pluginId": "savedObjectsFinder", + "scope": "public", + "docId": "kibSavedObjectsFinderPluginApi", + "section": "def-public.SavedObjectFinderProps", + "text": "SavedObjectFinderProps" + }, + ") => JSX.Element" + ], + "path": "src/plugins/saved_objects_finder/public/finder/index.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsFinder", + "id": "def-public.getSavedObjectFinder.$1", + "type": "Object", + "tags": [], + "label": "uiSettings", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-ui-settings-browser", + "scope": "common", + "docId": "kibKbnCoreUiSettingsBrowserPluginApi", + "section": "def-common.IUiSettingsClient", + "text": "IUiSettingsClient" + } + ], + "path": "src/plugins/saved_objects_finder/public/finder/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsFinder", + "id": "def-public.getSavedObjectFinder.$2", + "type": "Object", + "tags": [], + "label": "http", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-browser", + "scope": "common", + "docId": "kibKbnCoreHttpBrowserPluginApi", + "section": "def-common.HttpSetup", + "text": "HttpSetup" + } + ], + "path": "src/plugins/saved_objects_finder/public/finder/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsFinder", + "id": "def-public.getSavedObjectFinder.$3", + "type": "Object", + "tags": [], + "label": "savedObjectsManagement", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsManagement", + "scope": "public", + "docId": "kibSavedObjectsManagementPluginApi", + "section": "def-public.SavedObjectsManagementPluginStart", + "text": "SavedObjectsManagementPluginStart" + } + ], + "path": "src/plugins/saved_objects_finder/public/finder/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsFinder", + "id": "def-public.getSavedObjectFinder.$4", + "type": "Object", + "tags": [], + "label": "savedObjectsTagging", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "public", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-public.SavedObjectsTaggingApi", + "text": "SavedObjectsTaggingApi" + }, + " | undefined" + ], + "path": "src/plugins/saved_objects_finder/public/finder/index.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "savedObjectsFinder", "id": "def-public.SavedObjectFinder", diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index 367ab10b93f95..a925f9e7e8d1a 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/k | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 39 | 0 | 39 | 0 | +| 44 | 0 | 44 | 0 | ## Client diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index ab25f08c08353..93eec3c8e2134 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-03-01 +date: 2023-03-02 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 cf634e8bcf4d2..92bed3afdacfe 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-03-01 +date: 2023-03-02 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 58754d7347a9a..5275c2ba2daf3 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-03-01 +date: 2023-03-02 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 d366a5659c2d0..c31edc8a13b0e 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-03-01 +date: 2023-03-02 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 f73392463bf85..3010e7478cb21 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-03-01 +date: 2023-03-02 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 5aeff28137085..3a4777e421cca 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-03-01 +date: 2023-03-02 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 41a4f223df1c3..2b741f7ba9044 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-03-01 +date: 2023-03-02 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 888af88e4afd8..d51910f728a32 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-03-01 +date: 2023-03-02 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 8e622aa8c0fbe..0636e41382b77 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-03-01 +date: 2023-03-02 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 280a9087fffdc..c3d6c6539e557 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-03-01 +date: 2023-03-02 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 23bdf19710ba6..7f6a877f69e9c 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-03-01 +date: 2023-03-02 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 1887661117d27..beb404bc7432d 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-03-01 +date: 2023-03-02 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 d6e565746caed..55a98d19c1ede 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-03-01 +date: 2023-03-02 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 74034e03d1606..f779c26c75c72 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-03-01 +date: 2023-03-02 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 7fcd51007ee22..c22042c62aa79 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-03-01 +date: 2023-03-02 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 25f3f0790c8e5..970b83513b7af 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-03-01 +date: 2023-03-02 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 3b445eef5c9f8..35caf129235d2 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-03-01 +date: 2023-03-02 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 494d687861aef..801e3c0b78b96 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-03-01 +date: 2023-03-02 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 8c43e25170a8a..29a9a59dbc554 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-03-01 +date: 2023-03-02 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 f10c81a6c4bf9..a8f10c08b35ac 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-03-01 +date: 2023-03-02 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 dffa97af77387..4d78358b839ff 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-03-01 +date: 2023-03-02 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 356e1f00b40fe..e5cc4d27c7c71 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-03-01 +date: 2023-03-02 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 25e1f7667b80f..dd5bbd23bd1c1 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-03-01 +date: 2023-03-02 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 af0e4ad1fe0e4..cb576491e68f8 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-03-01 +date: 2023-03-02 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 237e122541d20..a0acb8cefb267 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-03-01 +date: 2023-03-02 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 53e998016795e..e80bd4f23b3f1 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-03-01 +date: 2023-03-02 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 f9421f8e37385..2d968671567c2 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-03-01 +date: 2023-03-02 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 e253a60f45f2f..7ce7f9776a0df 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-03-01 +date: 2023-03-02 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 7b878eafe283c..11bf3eca20206 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-03-01 +date: 2023-03-02 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 823876429efb1..00a2a9c375867 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-03-01 +date: 2023-03-02 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 109cbf52dc582..6ecd92065cad1 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-03-01 +date: 2023-03-02 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 638a8ea29d98e..a384f9f7367b6 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-03-01 +date: 2023-03-02 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 c31cbd33a8736..edd9382b98348 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-03-01 +date: 2023-03-02 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 f5b9dd978f640..659f1fde7adde 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-03-01 +date: 2023-03-02 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 dbc51a17cbeba..205dc8e481f17 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-03-01 +date: 2023-03-02 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 12355ae17b46c..6764e12e55a9b 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-03-01 +date: 2023-03-02 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 a84e017f11233..cb488e139d52e 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-03-01 +date: 2023-03-02 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 87a277e1cd1db..d962ffe6dec17 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-03-01 +date: 2023-03-02 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 c1fc09b66945d..09b5222b7d782 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-03-01 +date: 2023-03-02 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 234f683885678..e2376c3a4225d 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-03-01 +date: 2023-03-02 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 9584fabdc1fb9..a503f4fa09f78 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-03-01 +date: 2023-03-02 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 cfaf9011a3e5e..a95ce8496e401 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-03-01 +date: 2023-03-02 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 b7661a706bb18..22c23857d5ec5 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-03-01 +date: 2023-03-02 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From b3c3461fe10486b7f267191938f71a429944fcf6 Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 2 Mar 2023 08:37:08 +0100 Subject: [PATCH 105/131] [ML] removed orphaned code (#152196) Removes client side `getTimeFieldRange()` code within the data visualizer plugin. The code has been moved to the date picker package in `x-pack/packages/ml/date_picker/src/services/time_field_range.ts`and the duplicate is no longer necessary. --- .../services/time_field_range.ts | 32 ------------------- 1 file changed, 32 deletions(-) delete mode 100644 x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts deleted file mode 100644 index bcf32a7f62bd7..0000000000000 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts +++ /dev/null @@ -1,32 +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 type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { lazyLoadModules } from '../../../lazy_load_bundle'; -import { GetTimeFieldRangeResponse } from '../../../../common/types/time_field_request'; - -export async function getTimeFieldRange({ - index, - timeFieldName, - query, - runtimeMappings, -}: { - index: string; - timeFieldName?: string; - query?: QueryDslQueryContainer; - runtimeMappings?: estypes.MappingRuntimeFields; -}) { - const body = JSON.stringify({ index, timeFieldName, query, runtimeMappings }); - const fileUploadModules = await lazyLoadModules(); - - return await fileUploadModules.getHttp().fetch({ - path: `/internal/file_upload/time_field_range`, - method: 'POST', - body, - }); -} From cb96fea0d9cb1fb59dcc3281d15a1c9d38a7b8cb Mon Sep 17 00:00:00 2001 From: Coen Warmer Date: Thu, 2 Mar 2023 09:04:36 +0100 Subject: [PATCH 106/131] [SLO] Add Auto-Refresh button on SLO List (#152460) --- .../use_fetch_historical_summary.ts | 2 + .../hooks/slo/use_fetch_historical_summary.ts | 12 +++-- .../public/hooks/slo/use_fetch_slo_list.ts | 32 +++++++++++- .../auto_refresh_button.stories.tsx | 36 ++++++++++++++ .../slos/components/auto_refresh_button.tsx | 49 +++++++++++++++++++ .../slos/components/slo_list.stories.tsx | 8 +-- .../public/pages/slos/components/slo_list.tsx | 7 ++- .../pages/slos/components/slo_list_items.tsx | 2 +- .../public/pages/slos/index.test.tsx | 15 ++++++ .../observability/public/pages/slos/index.tsx | 15 +++++- 10 files changed, 165 insertions(+), 13 deletions(-) create mode 100644 x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.stories.tsx create mode 100644 x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.tsx diff --git a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts index fe10d84c4f428..7928dbe51b46d 100644 --- a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts +++ b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_historical_summary.ts @@ -20,6 +20,8 @@ export const useFetchHistoricalSummary = ({ return { isLoading: false, + isInitialLoading: false, + isRefetching: false, isSuccess: false, isError: false, sloHistoricalSummaryResponse: data, diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts index 2037c97df52c1..469d98e63538c 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_historical_summary.ts @@ -10,10 +10,10 @@ import { FetchHistoricalSummaryResponse } from '@kbn/slo-schema'; import { useKibana } from '../../utils/kibana_react'; -const EMPTY_RESPONSE: FetchHistoricalSummaryResponse = {}; - export interface UseFetchHistoricalSummaryResponse { - sloHistoricalSummaryResponse: FetchHistoricalSummaryResponse; + sloHistoricalSummaryResponse: FetchHistoricalSummaryResponse | undefined; + isInitialLoading: boolean; + isRefetching: boolean; isLoading: boolean; isSuccess: boolean; isError: boolean; @@ -49,8 +49,10 @@ export function useFetchHistoricalSummary({ }); return { - sloHistoricalSummaryResponse: isInitialLoading ? EMPTY_RESPONSE : data ?? EMPTY_RESPONSE, - isLoading: isInitialLoading || isLoading || isRefetching, + sloHistoricalSummaryResponse: data, + isLoading, + isRefetching, + isInitialLoading, isSuccess, isError, }; diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts index 648efb5481d31..82e675bcc8437 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts @@ -5,11 +5,13 @@ * 2.0. */ +import { useState } from 'react'; import { QueryObserverResult, RefetchOptions, RefetchQueryFilters, useQuery, + useQueryClient, } from '@tanstack/react-query'; import { FindSLOResponse } from '@kbn/slo-schema'; @@ -20,6 +22,7 @@ interface SLOListParams { page?: number; sortBy?: string; indicatorTypes?: string[]; + shouldRefetch?: boolean; } export interface UseFetchSloListResponse { @@ -33,13 +36,20 @@ export interface UseFetchSloListResponse { ) => Promise>; } +const SHORT_REFETCH_INTERVAL = 1000 * 5; // 5 seconds +const LONG_REFETCH_INTERVAL = 1000 * 60; // 1 minute + export function useFetchSloList({ name = '', page = 1, sortBy = 'name', indicatorTypes = [], + shouldRefetch, }: SLOListParams | undefined = {}): UseFetchSloListResponse { const { http } = useKibana().services; + const queryClient = useQueryClient(); + + const [stateRefetchInterval, setStateRefetchInterval] = useState(SHORT_REFETCH_INTERVAL); const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( { @@ -64,9 +74,29 @@ export function useFetchSloList({ // ignore error } }, - refetchOnWindowFocus: false, keepPreviousData: true, + refetchOnWindowFocus: false, + refetchInterval: shouldRefetch ? stateRefetchInterval : undefined, staleTime: 1000, + onSuccess: ({ results }: FindSLOResponse) => { + if (!shouldRefetch) { + return; + } + + if (results.find((slo) => slo.summary.status === 'NO_DATA')) { + setStateRefetchInterval(SHORT_REFETCH_INTERVAL); + } else { + setStateRefetchInterval(LONG_REFETCH_INTERVAL); + } + + queryClient.invalidateQueries(['fetchHistoricalSummary'], { + exact: false, + }); + + queryClient.invalidateQueries(['fetchActiveAlerts'], { + exact: false, + }); + }, } ); diff --git a/x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.stories.tsx b/x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.stories.tsx new file mode 100644 index 0000000000000..5a5b94401253e --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.stories.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { ComponentStory } from '@storybook/react'; + +import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; +import { AutoRefreshButton as Component } from './auto_refresh_button'; + +export default { + component: Component, + title: 'app/SLO/ListPage/AutoRefreshButton', + decorators: [KibanaReactStorybookDecorator], +}; + +const Template: ComponentStory = () => { + const [isAutoRefreshing, setIsAutoRefreshing] = useState(true); + + const toggleEnabled = () => { + setIsAutoRefreshing(!isAutoRefreshing); + }; + + return ; +}; + +const defaultProps = { + enabled: true, + disabled: false, +}; + +export const AutoRefreshButton = Template.bind({}); +AutoRefreshButton.args = defaultProps; diff --git a/x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.tsx b/x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.tsx new file mode 100644 index 0000000000000..5101a5c1d96ef --- /dev/null +++ b/x-pack/plugins/observability/public/pages/slos/components/auto_refresh_button.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { EuiButtonEmpty } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +interface Props { + isAutoRefreshing: boolean; + dataTestSubj?: string; + disabled?: boolean; + onClick: () => void; +} + +export function AutoRefreshButton({ + dataTestSubj = 'autoRefreshButton', + disabled, + isAutoRefreshing, + onClick, +}: Props) { + return isAutoRefreshing ? ( + + {i18n.translate('xpack.observability.slosPage.stopRefreshingButtonLabel', { + defaultMessage: 'Stop refreshing', + })} + + ) : ( + + {i18n.translate('xpack.observability.slosPage.autoRefreshButtonLabel', { + defaultMessage: 'Auto-refresh', + })} + + ); +} diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list.stories.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list.stories.tsx index 3e6dd1c87d798..244bda63596b7 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list.stories.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list.stories.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { ComponentStory } from '@storybook/react'; import { KibanaReactStorybookDecorator } from '../../../utils/kibana_react.storybook_decorator'; -import { SloList as Component } from './slo_list'; +import { SloList as Component, Props } from './slo_list'; export default { component: Component, @@ -18,9 +18,11 @@ export default { decorators: [KibanaReactStorybookDecorator], }; -const Template: ComponentStory = () => ; +const Template: ComponentStory = (props: Props) => ; -const defaultProps = {}; +const defaultProps = { + autoRefresh: true, +}; export const SloList = Template.bind({}); SloList.args = defaultProps; diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx index 9d5c8515d3403..1ca463c1ff940 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx @@ -18,7 +18,11 @@ import { } from './slo_list_search_filter_sort_bar'; import { SloListItems } from './slo_list_items'; -export function SloList() { +export interface Props { + autoRefresh: boolean; +} + +export function SloList({ autoRefresh }: Props) { const [activePage, setActivePage] = useState(0); const [query, setQuery] = useState(''); @@ -30,6 +34,7 @@ export function SloList() { name: query, sortBy: sort, indicatorTypes: indicatorTypeFilter, + shouldRefetch: autoRefresh, }); const { results = [], total = 0, perPage = 0 } = sloList || {}; diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx index 85ce283c90b18..cf95af3101c13 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list_items.tsx @@ -41,7 +41,7 @@ export function SloListItems({ sloList, loading, error }: Props) { diff --git a/x-pack/plugins/observability/public/pages/slos/index.test.tsx b/x-pack/plugins/observability/public/pages/slos/index.test.tsx index c224accc280ad..cfa07011159e6 100644 --- a/x-pack/plugins/observability/public/pages/slos/index.test.tsx +++ b/x-pack/plugins/observability/public/pages/slos/index.test.tsx @@ -155,6 +155,21 @@ describe('SLOs Page', () => { expect(screen.getByText('Create new SLO')).toBeTruthy(); }); + it('should have an Auto Refresh button', async () => { + useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); + + useFetchHistoricalSummaryMock.mockReturnValue({ + isLoading: false, + sloHistoricalSummaryResponse: historicalSummaryData, + }); + + await act(async () => { + render(, config); + }); + + expect(screen.getByTestId('autoRefreshButton')).toBeTruthy(); + }); + describe('when API has returned results', () => { it('renders the SLO list with SLO items', async () => { useFetchSloListMock.mockReturnValue({ isLoading: false, sloList }); diff --git a/x-pack/plugins/observability/public/pages/slos/index.tsx b/x-pack/plugins/observability/public/pages/slos/index.tsx index 0fd7b51810d5e..25f93561e6ed9 100644 --- a/x-pack/plugins/observability/public/pages/slos/index.tsx +++ b/x-pack/plugins/observability/public/pages/slos/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useState } from 'react'; import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -17,6 +17,7 @@ import { useCapabilities } from '../../hooks/slo/use_capabilities'; import { useFetchSloList } from '../../hooks/slo/use_fetch_slo_list'; import { SloList } from './components/slo_list'; import { SloListWelcomePrompt } from './components/slo_list_welcome_prompt'; +import { AutoRefreshButton } from './components/auto_refresh_button'; import PageNotFound from '../404'; import { paths } from '../../config'; import { isSloFeatureEnabled } from './helpers/is_slo_feature_enabled'; @@ -35,6 +36,8 @@ export function SlosPage() { const { total } = sloList || {}; + const [isAutoRefreshing, setIsAutoRefreshing] = useState(true); + useBreadcrumbs([ { href: basePath.prepend(paths.observability.slos), @@ -48,6 +51,10 @@ export function SlosPage() { navigateToUrl(basePath.prepend(paths.observability.sloCreate)); }; + const handleToggleAutoRefresh = () => { + setIsAutoRefreshing(!isAutoRefreshing); + }; + if (!isSloFeatureEnabled(config)) { return ; } @@ -78,12 +85,16 @@ export function SlosPage() { defaultMessage: 'Create new SLO', })} , + , ], bottomBorder: false, }} data-test-subj="slosPage" > - + ); } From 6dcdabce996ee2582d0e78d7174a70bd033c574d Mon Sep 17 00:00:00 2001 From: Jill Guyonnet Date: Thu, 2 Mar 2023 09:22:45 +0100 Subject: [PATCH 107/131] Add details to Fleet README (#152348) Update the Fleet plugin README --- docs/developer/plugin-list.asciidoc | 2 +- x-pack/plugins/fleet/README.md | 64 +++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 3cdca29fcb49d..f420afb81624d 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -535,7 +535,7 @@ activities. |{kib-repo}blob/{branch}/x-pack/plugins/fleet/README.md[fleet] -|Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.fleet.agents.tlsCheckDisabled=false) +|Fleet needs to have Elasticsearch API keys enabled. |{kib-repo}blob/{branch}/x-pack/plugins/global_search/README.md[globalSearch] diff --git a/x-pack/plugins/fleet/README.md b/x-pack/plugins/fleet/README.md index 9d9c6c9720de4..2881076c7f156 100644 --- a/x-pack/plugins/fleet/README.md +++ b/x-pack/plugins/fleet/README.md @@ -13,7 +13,7 @@ ## Fleet Requirements -Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag `--xpack.fleet.agents.tlsCheckDisabled=false`) +Fleet needs to have Elasticsearch API keys enabled. Also you need to configure the hosts your agent is going to use to comunication with Elasticsearch and Kibana (Not needed if you use Elastic cloud). You can use the following flags: @@ -26,27 +26,53 @@ Also you need to configure the hosts your agent is going to use to comunication ### Getting started -See the Kibana docs for [how to set up your dev environment](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md#setting-up-your-development-environment), [run Elasticsearch](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md#running-elasticsearch), and [start Kibana](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md#running-kibana) +See the [Contributing to Kibana documentation](https://github.com/elastic/kibana/blob/main/CONTRIBUTING.md) or head straight to the [Kibana Developer Guide](https://docs.elastic.dev/kibana-dev-docs/getting-started/welcome) for setting up your dev environment, run Elasticsearch and start Kibana. -One common development workflow is: +This plugin follows the `common`, `server`, `public` structure described in the [Kibana Developer Guide](https://docs.elastic.dev/kibana-dev-docs/key-concepts/platform-intro). Refer to [The anatomy of a plugin](https://docs.elastic.dev/kibana-dev-docs/key-concepts/anatomy-of-a-plugin) in the guide for further details. -- Bootstrap Kibana - ``` - yarn kbn bootstrap +We follow the pattern of developing feature branches under your personal fork of Kibana. Refer to [Set up a Development Environment](https://docs.elastic.dev/kibana-dev-docs/getting-started/setup-dev-env) in the guide for further details. Other best practices including developer principles, standards and style guide can be found under the Contributing section of the guide. + +Note: The plugin was previously named Ingest Manager, it's possible that some variables are still named with that old plugin name. + +#### Dev environment setup + +These are some additional recommendations to the steps detailed in the [Kibana Developer Guide](https://docs.elastic.dev/kibana-dev-docs/getting-started/setup-dev-env). + +1. Create a `config/kibana.dev.yml` file by copying the existing `config/kibana.yml` file. +2. It is recommended to explicitly set a base path for Kibana (refer to [Considerations for basepath](https://www.elastic.co/guide/en/kibana/current/development-basepath.html) for details). To do this, add the following to your `kibana.dev.yml`: + ```yml + server.basePath: / ``` -- Start Elasticsearch in one shell + where `yourPath` is a path of your choice (e.g. your name). +3. Bootstrap Kibana: + ``` + yarn kbn bootstrap + ``` + +#### Running Elasticsearch and Kibana +- Start Elasticsearch in one shell (NB: you might want to add other flags to enable data persistency and/or running Fleet Server locally, see below): ``` yarn es snapshot -E xpack.security.authc.api_key.enabled=true -E xpack.security.authc.token.enabled=true ``` -- Start Kibana in another shell +- Start Kibana in another shell: ``` - yarn start --no-base-path + yarn start ``` + If you don't have a base path set up, add `--no-base-path` to `yarn start`. + +#### Useful tips + +If Kibana fails to start, it is possible that your local setup got corrupted. An easy fix is to run: +``` +yarn kbn clean && yarn kbn bootstrap +``` -This plugin follows the `common`, `server`, `public` structure from the [Architecture Style Guide -](https://github.com/elastic/kibana/blob/main/style_guides/architecture_style_guide.md#file-and-folder-structure). We also follow the pattern of developing feature branches under your personal fork of Kibana. +To avoid losing all your data when you restart Elasticsearch, you can provide a path to store the data when running the `yarn es snapshot ` command, e.g.: +``` +-E path.data=/tmp/es-data +``` -Note: The plugin was previously named Ingest Manager it's possible that some variables are still named with that old plugin name. +Refer to the [Running Elasticsearch during development](https://www.elastic.co/guide/en/kibana/current/running-elasticsearch.html) page of the guide for other options. ### Running Fleet Server Locally in a Container @@ -99,7 +125,7 @@ docker run -e KIBANA_HOST=http://{YOUR-IP}:5601/{BASE-PATH} -e KIBANA_USERNAME=e Ensure you provide the `-p 8220:8220` port mapping to map the Fleet Server container's port `8220` to your local machine's port `8220` in order for Fleet to communicate with Fleet Server. -For the latest version, use `8.0.0-SNAPSHOT`. Otherwise, you can explore the available versions at https://www.docker.elastic.co/r/beats/elastic-agent. +Explore the available versions at https://www.docker.elastic.co/r/beats/elastic-agent. Only released versions are shown by default: tick the `Include snapshots` checkbox to see the latest version, e.g. `8.8.0-SNAPSHOT`. Once the Fleet Server container is running, you should be able to treat it as if it were a local process running on `https://localhost:8220` when configuring Fleet via the UI. You can then run `elastic-agent` on your local machine directly for testing purposes, or with Docker (recommended) see next section. @@ -115,6 +141,18 @@ Once the Fleet Server container is running, you should be able to treat it as if ### Tests +#### Unit tests + +Kibana primarily uses Jest for unit testing. Each plugin or package defines a `jest.config.js` that extends a preset provided by the `@kbn/test` package. Unless you intend to run all unit tests within the project, you should provide the Jest configuration for Fleet. The following command runs all Fleet unit tests: +``` +yarn jest --config x-pack/plugins/fleet/jest.config.js +``` + +You can also run a specific test by passing the filepath as an argument, e.g.: +``` +yarn jest --config x-pack/plugins/fleet/jest.config.js x-pack/plugins/fleet/common/services/validate_package_policy.test.ts +``` + #### API integration tests You need to have `docker` to run ingest manager api integration tests From 0d04fd7a622487d4bf0a9c91108be1d2bca4107d Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 2 Mar 2023 09:46:18 +0000 Subject: [PATCH 108/131] [ML] Removing scss override files for anomaly detection jobs (#152240) Removes the scss files which were being used to override various eui styles or add styles to custom components. Affect the anomaly detection jobs list and wizards. This is not an in-depth refactor of our styles, and so some overrides are still necessary in order to retain an identical UI, in these cases the style overrides have been moved to inline emotion `css`. Part of https://github.com/elastic/kibana/issues/140695 --- .../plugins/ml/public/application/_app.scss | 30 ---- .../plugins/ml/public/application/_hacks.scss | 33 ---- .../plugins/ml/public/application/_index.scss | 12 -- .../anomalies_table/_anomalies_table.scss | 40 ----- .../components/controls/_controls.scss | 16 -- .../components/controls/_index.scss | 2 - .../controls/select_severity/_index.scss | 1 - .../select_severity/_select_severity.scss | 6 - .../components/items_grid/_index.scss | 1 - .../components/items_grid/_items_grid.scss | 3 - .../components/job_messages/job_messages.tsx | 1 - .../components/loading_indicator/_index.scss | 1 - .../loading_indicator/_loading_indicator.scss | 10 -- .../loading_indicator/loading_indicator.tsx | 28 ++-- .../components/ml_embedded_map/_index.scss | 1 - .../ml_embedded_map/_ml_embedded_map.scss | 8 - .../ml_embedded_map/ml_embedded_map.tsx | 9 +- .../components/stats_bar/_index.scss | 2 - .../components/stats_bar/_stat.scss | 3 - .../components/stats_bar/_stats_bar.scss | 6 - .../application/components/stats_bar/stat.tsx | 4 +- .../components/stats_bar/stats_bar.tsx | 7 +- .../explorer_chart_distribution.test.js | 6 +- .../explorer_chart_single_metric.test.js | 6 +- .../ml/public/application/jobs/_index.scss | 3 - .../__snapshots__/editor.test.tsx.snap | 6 - .../custom_url_editor/_custom_url_editor.scss | 19 --- .../components/custom_url_editor/_index.scss | 1 - .../components/custom_url_editor/editor.tsx | 1 - .../application/jobs/jobs_list/_index.scss | 8 - .../jobs/jobs_list/_jobs_list.scss | 3 - .../edit_job_flyout/_edit_job_flyout.scss | 8 - .../components/edit_job_flyout/_index.scss | 1 - .../edit_job_flyout/tabs/custom_urls.tsx | 1 - .../components/job_details/_index.scss | 1 - .../components/job_details/_job_details.scss | 87 ----------- .../job_details/job_details_pane.js | 110 -------------- .../job_details/job_details_pane.tsx | 142 ++++++++++++++++++ .../components/job_filter_bar/_index.scss | 1 - .../job_filter_bar/_job_filter_bar.scss | 23 --- .../job_filter_bar/job_filter_bar.tsx | 1 - .../components/job_group/_index.scss | 1 - .../components/job_group/_job_group.scss | 10 -- .../components/jobs_list_view/_index.scss | 1 - .../jobs_list_view/_jobs_list_view.scss | 10 -- .../jobs_list_view/jobs_list_view.js | 44 +++--- .../components/multi_job_actions/_index.scss | 2 - .../multi_job_actions/_multi_job_actions.scss | 35 ----- .../group_selector/_group_selector.scss | 7 - .../group_selector/_index.scss | 3 - .../group_list/_group_list.scss | 40 ----- .../group_selector/group_list/_index.scss | 1 - .../group_selector/group_list/group_list.js | 2 +- .../group_selector/group_selector.js | 2 +- .../new_group_input/_index.scss | 1 - .../new_group_input/_new_group_input.scss | 3 - .../multi_job_actions/multi_job_actions.js | 17 ++- .../components/custom_urls/description.tsx | 14 +- .../components/custom_urls/index.scss | 12 -- .../public/application/overview/_index.scss | 1 - .../overview/components/_index.scss | 8 - .../analytics_panel/analytics_panel.tsx | 10 +- 62 files changed, 240 insertions(+), 636 deletions(-) delete mode 100644 x-pack/plugins/ml/public/application/_app.scss delete mode 100644 x-pack/plugins/ml/public/application/_hacks.scss delete mode 100644 x-pack/plugins/ml/public/application/components/controls/_controls.scss delete mode 100644 x-pack/plugins/ml/public/application/components/controls/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/components/controls/select_severity/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/components/controls/select_severity/_select_severity.scss delete mode 100644 x-pack/plugins/ml/public/application/components/items_grid/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/components/items_grid/_items_grid.scss delete mode 100644 x-pack/plugins/ml/public/application/components/loading_indicator/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/components/loading_indicator/_loading_indicator.scss delete mode 100644 x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss delete mode 100644 x-pack/plugins/ml/public/application/components/stats_bar/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/components/stats_bar/_stat.scss delete mode 100644 x-pack/plugins/ml/public/application/components/stats_bar/_stats_bar.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/_custom_url_editor.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/_jobs_list.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js create mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.tsx delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_jobs_list_view.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/_multi_job_actions.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/_group_selector.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/group_list/_group_list.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/group_list/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/new_group_input/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/jobs_list/components/multi_job_actions/group_selector/new_group_input/_new_group_input.scss delete mode 100644 x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/index.scss delete mode 100644 x-pack/plugins/ml/public/application/overview/_index.scss delete mode 100644 x-pack/plugins/ml/public/application/overview/components/_index.scss diff --git a/x-pack/plugins/ml/public/application/_app.scss b/x-pack/plugins/ml/public/application/_app.scss deleted file mode 100644 index 6dfae7a8921f3..0000000000000 --- a/x-pack/plugins/ml/public/application/_app.scss +++ /dev/null @@ -1,30 +0,0 @@ -// ML has app specific coloring for it's various warning levels. -// These are used almost everywhere. - -.ml-icon-severity-critical, -.ml-icon-severity-major, -.ml-icon-severity-minor, -.ml-icon-severity-warning, -.ml-icon-severity-unknown { - text-shadow: 1px 1px 1px $euiColorLightShade; -} - -.ml-icon-severity-critical { - color: $mlColorCriticalText; -} - -.ml-icon-severity-major { - color: $mlColorMajorText; -} - -.ml-icon-severity-minor { - color: $mlColorMinorText; -} - -.ml-icon-severity-warning { - color: $mlColorWarningText; -} - -.ml-icon-severity-unknown { - color: $mlColorUnknownText; -} diff --git a/x-pack/plugins/ml/public/application/_hacks.scss b/x-pack/plugins/ml/public/application/_hacks.scss deleted file mode 100644 index 13fabcb8045aa..0000000000000 --- a/x-pack/plugins/ml/public/application/_hacks.scss +++ /dev/null @@ -1,33 +0,0 @@ -.tab-datavisualizer_index_select, -.tab-timeseriesexplorer, -.tab-explorer { - // Make all page background white until More of the pages use EuiPage to wrap in panel-like components - background-color: $euiColorEmptyShade; -} - -// ML specific bootstrap hacks -.button-wrapper { - display: inline; -} - -.button-wrapper.disabled .kuiButton[disabled] { - pointer-events: none; -} - -.button-wrapper.disabled { - cursor: not-allowed; -} - -// SASSTODO: Remove all the floats -.clear, .clearfix { - clear: both; -} - -// Helper class for functional tests to disable anti-aliasing for canvas elements -.mlDisableAntiAliasing { - -webkit-font-smoothing : none; - - * canvas { - image-rendering: pixelated; - } -} diff --git a/x-pack/plugins/ml/public/application/_index.scss b/x-pack/plugins/ml/public/application/_index.scss index 309eea83dd527..ac9e16e5f3e78 100644 --- a/x-pack/plugins/ml/public/application/_index.scss +++ b/x-pack/plugins/ml/public/application/_index.scss @@ -4,30 +4,18 @@ // Protect the rest of Kibana from ML generic namespacing // SASSTODO: Prefix ml selectors instead .ml-app { - // App level - @import 'app'; - // Sub applications @import 'data_frame_analytics/index'; @import 'explorer/index'; // SASSTODO: This file needs to be rewritten - @import 'jobs/index'; // SASSTODO: This collection of sass files has multiple problems - @import 'overview/index'; @import 'timeseriesexplorer/index'; // Components @import 'components/annotations/annotation_description_list/index'; // SASSTODO: This file overwrites EUI directly @import 'components/anomalies_table/index'; // SASSTODO: This file overwrites EUI directly @import 'components/color_range_legend/index'; - @import 'components/controls/index'; @import 'components/entity_cell/index'; @import 'components/influencers_list/index'; - @import 'components/items_grid/index'; @import 'components/job_selector/index'; - @import 'components/loading_indicator/index'; // SASSTODO: This component should be replaced with EuiLoadingSpinner @import 'components/rule_editor/index'; // SASSTODO: This file overwrites EUI directly - @import 'components/stats_bar/index'; - @import 'components/ml_embedded_map/index'; - // Hacks are last so they can overwrite anything above if needed - @import 'hacks'; } diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss b/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss index 06dfacf63a213..4f11115e82712 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/_anomalies_table.scss @@ -1,45 +1,5 @@ // SASSTODO: This file has several direct EUI overwrites that need to be removed .ml-anomalies-table { - .ml-icon-severity-critical, - .ml-icon-severity-major, - .ml-icon-severity-minor, - .ml-icon-severity-warning, - .ml-icon-severity-unknown { - color: inherit; - text-shadow: none; - } - - // SASSTODO: Should only be three options, logic moved to the JS, where EuiIcon accepts a color - .ml-icon-severity-critical { - .euiIcon { - fill: $mlColorCriticalText; - } - } - - .ml-icon-severity-major { - .euiIcon { - fill: $mlColorMajorText; - } - } - - .ml-icon-severity-minor { - .euiIcon { - fill: $mlColorMinorText; - } - } - - .ml-icon-severity-warning { - .euiIcon { - fill: $mlColorWarningText; - } - } - - .ml-icon-severity-unknown { - .euiIcon { - fill: $mlColorUnknownText; - } - } - tr th:first-child, tr td:first-child { width: $euiSizeXL; diff --git a/x-pack/plugins/ml/public/application/components/controls/_controls.scss b/x-pack/plugins/ml/public/application/components/controls/_controls.scss deleted file mode 100644 index d491e88dffa24..0000000000000 --- a/x-pack/plugins/ml/public/application/components/controls/_controls.scss +++ /dev/null @@ -1,16 +0,0 @@ -.ml-table-controls { - label { - font-size: $euiFontSizeXS; - padding: 0 0 $euiSizeXS $euiSizeXS; - } - - .ml-table-controls-element { - display: inline-block; - padding-left: $euiSize; - } - - select { - font-size: $euiFontSizeXS; - font-style: normal; - } -} diff --git a/x-pack/plugins/ml/public/application/components/controls/_index.scss b/x-pack/plugins/ml/public/application/components/controls/_index.scss deleted file mode 100644 index 84c0e21734b89..0000000000000 --- a/x-pack/plugins/ml/public/application/components/controls/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'controls'; -@import 'select_severity/index'; diff --git a/x-pack/plugins/ml/public/application/components/controls/select_severity/_index.scss b/x-pack/plugins/ml/public/application/components/controls/select_severity/_index.scss deleted file mode 100644 index f238b65c9b955..0000000000000 --- a/x-pack/plugins/ml/public/application/components/controls/select_severity/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'select_severity'; \ No newline at end of file diff --git a/x-pack/plugins/ml/public/application/components/controls/select_severity/_select_severity.scss b/x-pack/plugins/ml/public/application/components/controls/select_severity/_select_severity.scss deleted file mode 100644 index 2edfe612183d0..0000000000000 --- a/x-pack/plugins/ml/public/application/components/controls/select_severity/_select_severity.scss +++ /dev/null @@ -1,6 +0,0 @@ -// SASSTODO: Should be removed -.ml-select-severity { - .euiFormControlLayoutClearButton { - display: none; - } -} diff --git a/x-pack/plugins/ml/public/application/components/items_grid/_index.scss b/x-pack/plugins/ml/public/application/components/items_grid/_index.scss deleted file mode 100644 index 243c80da52918..0000000000000 --- a/x-pack/plugins/ml/public/application/components/items_grid/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'items_grid'; \ No newline at end of file diff --git a/x-pack/plugins/ml/public/application/components/items_grid/_items_grid.scss b/x-pack/plugins/ml/public/application/components/items_grid/_items_grid.scss deleted file mode 100644 index c3bd6b115bbd6..0000000000000 --- a/x-pack/plugins/ml/public/application/components/items_grid/_items_grid.scss +++ /dev/null @@ -1,3 +0,0 @@ -.ml-items-grid-page-size-menu { - width: 140px; // SASSTODO: Needs a proper calc -} diff --git a/x-pack/plugins/ml/public/application/components/job_messages/job_messages.tsx b/x-pack/plugins/ml/public/application/components/job_messages/job_messages.tsx index d78f311475501..41b005c7da58b 100644 --- a/x-pack/plugins/ml/public/application/components/job_messages/job_messages.tsx +++ b/x-pack/plugins/ml/public/application/components/job_messages/job_messages.tsx @@ -137,7 +137,6 @@ export const JobMessages: FC = ({ <> = ({ height, label }) => { height = height ? +height : 100; return ( -
    - - {label && ( - <> - -
    {label}
    - - )} -
    + + +
    + + {label && ( + <> + +
    {label}
    + + )} +
    +
    +
    ); }; diff --git a/x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss b/x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss deleted file mode 100644 index 6d0d30dae670e..0000000000000 --- a/x-pack/plugins/ml/public/application/components/ml_embedded_map/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'ml_embedded_map'; diff --git a/x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss b/x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss deleted file mode 100644 index 495fc40ddb27c..0000000000000 --- a/x-pack/plugins/ml/public/application/components/ml_embedded_map/_ml_embedded_map.scss +++ /dev/null @@ -1,8 +0,0 @@ -.mlEmbeddedMapContent { - width: 100%; - height: 100%; - display: flex; - flex: 1 1 100%; - z-index: 1; - min-height: 0; // Absolute must for Firefox to scroll contents -} diff --git a/x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx b/x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx index ae9dbac3c2d02..57d2abe3577b9 100644 --- a/x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx +++ b/x-pack/plugins/ml/public/application/components/ml_embedded_map/ml_embedded_map.tsx @@ -143,7 +143,14 @@ export function MlEmbeddedMapComponent({ return (
    ); diff --git a/x-pack/plugins/ml/public/application/components/stats_bar/_index.scss b/x-pack/plugins/ml/public/application/components/stats_bar/_index.scss deleted file mode 100644 index e8d8e85763eff..0000000000000 --- a/x-pack/plugins/ml/public/application/components/stats_bar/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import 'stat'; -@import 'stats_bar'; diff --git a/x-pack/plugins/ml/public/application/components/stats_bar/_stat.scss b/x-pack/plugins/ml/public/application/components/stats_bar/_stat.scss deleted file mode 100644 index ea570c24f0d7b..0000000000000 --- a/x-pack/plugins/ml/public/application/components/stats_bar/_stat.scss +++ /dev/null @@ -1,3 +0,0 @@ -.stat { - margin-right: $euiSizeS; -} diff --git a/x-pack/plugins/ml/public/application/components/stats_bar/_stats_bar.scss b/x-pack/plugins/ml/public/application/components/stats_bar/_stats_bar.scss deleted file mode 100644 index c433b53789573..0000000000000 --- a/x-pack/plugins/ml/public/application/components/stats_bar/_stats_bar.scss +++ /dev/null @@ -1,6 +0,0 @@ -.mlStatsBar { - // SASSTODO: proper calcs - height: 42px; - padding: 14px; - background-color: $euiColorLightestShade; -} diff --git a/x-pack/plugins/ml/public/application/components/stats_bar/stat.tsx b/x-pack/plugins/ml/public/application/components/stats_bar/stat.tsx index ae04a7a3b2448..2a0e8aad89bf0 100644 --- a/x-pack/plugins/ml/public/application/components/stats_bar/stat.tsx +++ b/x-pack/plugins/ml/public/application/components/stats_bar/stat.tsx @@ -6,6 +6,7 @@ */ import React, { FC } from 'react'; +import { useEuiTheme } from '@elastic/eui'; export interface StatsBarStat { label: string; @@ -18,8 +19,9 @@ interface StatProps { } export const Stat: FC = ({ stat }) => { + const { euiTheme } = useEuiTheme(); return ( - + {stat.label}:{' '} {stat.value} diff --git a/x-pack/plugins/ml/public/application/components/stats_bar/stats_bar.tsx b/x-pack/plugins/ml/public/application/components/stats_bar/stats_bar.tsx index 15324c180e293..535f5708693b0 100644 --- a/x-pack/plugins/ml/public/application/components/stats_bar/stats_bar.tsx +++ b/x-pack/plugins/ml/public/application/components/stats_bar/stats_bar.tsx @@ -6,6 +6,7 @@ */ import React, { FC } from 'react'; +import { useEuiTheme } from '@elastic/eui'; import { Stat, StatsBarStat } from './stat'; interface Stats { @@ -37,9 +38,13 @@ interface StatsBarProps { } export const StatsBar: FC = ({ stats, dataTestSub }) => { + const { euiTheme } = useEuiTheme(); const statsList = Object.keys(stats).map((k) => stats[k as StatsKey]); return ( -
    +
    {statsList .filter((s: StatsBarStat) => s.show) .map((s: StatsBarStat) => ( diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.test.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.test.js index 339925d3f16ee..d77b66b960625 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.test.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.test.js @@ -60,7 +60,7 @@ describe('ExplorerChart', () => { // the directive just ends up being empty. expect(wrapper.isEmptyRender()).toBeTruthy(); expect(wrapper.find('.content-wrapper')).toHaveLength(0); - expect(wrapper.find('.ml-loading-indicator .euiLoadingChart')).toHaveLength(0); + expect(wrapper.find('.euiLoadingChart')).toHaveLength(0); }); test('Loading status active, no chart', () => { @@ -84,7 +84,7 @@ describe('ExplorerChart', () => { // test if the loading indicator is shown // Added span because class appears twice with classNames and Emotion - expect(wrapper.find('.ml-loading-indicator span.euiLoadingChart')).toHaveLength(1); + expect(wrapper.find('span.euiLoadingChart')).toHaveLength(1); }); // For the following tests the directive needs to be rendered in the actual DOM, @@ -121,7 +121,7 @@ describe('ExplorerChart', () => { const wrapper = init(mockChartData); // the loading indicator should not be shown - expect(wrapper.find('.ml-loading-indicator .euiLoadingChart')).toHaveLength(0); + expect(wrapper.find('.euiLoadingChart')).toHaveLength(0); // test if all expected elements are present // need to use getDOMNode() because the chart is not rendered via react itself diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.test.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.test.js index 3748a196e742d..abe8c0c991cc4 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.test.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.test.js @@ -62,7 +62,7 @@ describe('ExplorerChart', () => { // the directive just ends up being empty. expect(wrapper.isEmptyRender()).toBeTruthy(); expect(wrapper.find('.content-wrapper')).toHaveLength(0); - expect(wrapper.find('.ml-loading-indicator .euiLoadingChart')).toHaveLength(0); + expect(wrapper.find('.euiLoadingChart')).toHaveLength(0); }); test('Loading status active, no chart', () => { @@ -87,7 +87,7 @@ describe('ExplorerChart', () => { // test if the loading indicator is shown // Added span because class appears twice with classNames and Emotion - expect(wrapper.find('.ml-loading-indicator span.euiLoadingChart')).toHaveLength(1); + expect(wrapper.find('span.euiLoadingChart')).toHaveLength(1); }); // For the following tests the directive needs to be rendered in the actual DOM, @@ -126,7 +126,7 @@ describe('ExplorerChart', () => { const wrapper = init(mockChartData); // the loading indicator should not be shown - expect(wrapper.find('.ml-loading-indicator .euiLoadingChart')).toHaveLength(0); + expect(wrapper.find('.euiLoadingChart')).toHaveLength(0); // test if all expected elements are present // need to use getDOMNode() because the chart is not rendered via react itself diff --git a/x-pack/plugins/ml/public/application/jobs/_index.scss b/x-pack/plugins/ml/public/application/jobs/_index.scss deleted file mode 100644 index 318ba1d54c082..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/_index.scss +++ /dev/null @@ -1,3 +0,0 @@ -@import 'components/custom_url_editor/index'; -@import 'jobs_list/index'; // SASSTODO: Various EUI overwrites throughout this folder -@import 'new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/index'; diff --git a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/__snapshots__/editor.test.tsx.snap b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/__snapshots__/editor.test.tsx.snap index 6c5d3d473d413..163bad28d8cc2 100644 --- a/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/__snapshots__/editor.test.tsx.snap +++ b/x-pack/plugins/ml/public/application/jobs/components/custom_url_editor/__snapshots__/editor.test.tsx.snap @@ -21,7 +21,6 @@ exports[`CustomUrlEditor renders the editor for a dashboard type URL with a labe data-test-subj="mlJobCustomUrlForm" > = ({ label={ } - className="url-label" error={invalidLabelError} isInvalid={isInvalidLabel} display="rowCompressed" diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/_index.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/_index.scss deleted file mode 100644 index 4af4814be8362..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/_index.scss +++ /dev/null @@ -1,8 +0,0 @@ -@import 'jobs_list'; - -@import 'components/edit_job_flyout/index'; -@import 'components/job_details/index'; // SASSTODO: Dangerous EUI overwrites -@import 'components/job_filter_bar/index'; // SASSTODO: Dangerous EUI overwrites -@import 'components/job_group/index'; -@import 'components/jobs_list_view/index'; -@import 'components/multi_job_actions/index'; // SASSTODO: Dangerous EUI overwrites diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/_jobs_list.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/_jobs_list.scss deleted file mode 100644 index 824f764de3902..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/_jobs_list.scss +++ /dev/null @@ -1,3 +0,0 @@ -.new-job-button-container { - float: right; -} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss deleted file mode 100644 index 7018a991ce1dc..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_edit_job_flyout.scss +++ /dev/null @@ -1,8 +0,0 @@ -.edit-custom-url-panel { - .close-editor-button { - position: relative; - float: right; - top: -$euiSizeXS; - right: 0; - } -} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_index.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_index.scss deleted file mode 100644 index 2fdf5a9671be3..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'edit_job_flyout'; \ No newline at end of file diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx index 9a7508c634c6b..ac6ad4ae70b8b 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/edit_job_flyout/tabs/custom_urls.tsx @@ -268,7 +268,6 @@ class CustomUrlsUI extends Component { defaultMessage: 'Close custom URL editor', } )} - className="close-editor-button" /> {editor} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_index.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_index.scss deleted file mode 100644 index 3930bb1cf73a5..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'job_details'; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss deleted file mode 100644 index fe61be550ecac..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/_job_details.scss +++ /dev/null @@ -1,87 +0,0 @@ -.tab-contents { - margin: -$euiSizeS; - padding: $euiSizeS; - background-color: $euiColorEmptyShade; - - // SASSTODO: Need to remove bootstrap grid - .col-md-6:nth-child(1) { - // SASSTODO: Why is this 7? - padding-right: 7px; - } - - // SASSTODO: Need to remove bootstrap grid - .col-md-6:nth-child(2) { - // SASSTODO: Why is this 7? - padding-left: 7px; - } - - // SASSTODO: This needs to be rewriten. Tons of EUI overwrites - .job-section { - overflow: auto; - padding: 5px 15px; - background-color: $euiColorLightestShade; - border: 1px solid $euiColorLightShade; - border-radius: $euiBorderRadius; - margin: $euiSizeXS 0; - - .euiTable { - background-color: transparent; - - .euiTableRow:first-child { - .euiTableRowCell { - border-top: 0; - } - } - - .euiTableRow:last-child { - .euiTableRowCell { - border-bottom: 0; - } - } - - .euiTableRow { - .euiTableRowCell { - vertical-align: top; - border-bottom: 1px solid $euiColorLightShade; - - .euiTableCellContent__text { - word-wrap: break-word; - } - } - } - - .euiTableRow:hover { - background-color: inherit; - } - } - - .job-item { - font-size: 12px; - } - - .job-item.header { - font-weight: bold; - } - } - - // SASSTODO: This needs a proper calc - .json-textarea { - height: 500px; - } -} - -.job-messages-table { - max-height: 500px; - overflow: auto; - text-align: left; - - tr:last-child { - td { - border-bottom: none; - } - } - - .euiTableRowCell { - background-color: $euiColorEmptyShade; - } -} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js deleted file mode 100644 index c70c049dd7489..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.js +++ /dev/null @@ -1,110 +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 PropTypes from 'prop-types'; -import React, { Component } from 'react'; - -import { - EuiFlexGroup, - EuiFlexItem, - EuiTitle, - EuiTable, - EuiTableBody, - EuiTableRow, - EuiTableRowCell, - EuiSpacer, -} from '@elastic/eui'; - -function SectionItem({ item }) { - return ( - - {item[0] !== '' && ( - - {item[0]} - - )} - - {item[1]} - - - ); -} -SectionItem.propTypes = { - item: PropTypes.array.isRequired, -}; - -function Section({ section }) { - if (section.items.length === 0) { - return
    ; - } - - return ( - - - - -

    {section.title}

    -
    -
    - {section.titleAction} -
    -
    - - - {section.items.map((item, i) => ( - - ))} - - -
    -
    - ); -} -Section.propTypes = { - section: PropTypes.object.isRequired, -}; - -export class JobDetailsPane extends Component { - constructor(props) { - super(props); - this.state = {}; - } - - static getDerivedStateFromProps(props) { - const { sections, time } = props; - return { sections, time }; - } - - render() { - const { sections, time } = this.state; - return ( - - -
    -
    - {sections - .filter((s) => s.position === 'left') - .map((s, i) => ( -
    - ))} -
    -
    - {sections - .filter((s) => s.position === 'right') - .map((s, i) => ( -
    - ))} -
    -
    -
    - ); - } -} -JobDetailsPane.propTypes = { - sections: PropTypes.array.isRequired, - 'data-test-subj': PropTypes.string, -}; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.tsx new file mode 100644 index 0000000000000..9d090425ff4ef --- /dev/null +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_details/job_details_pane.tsx @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; +import { css } from '@emotion/react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiTitle, + EuiTable, + EuiTableBody, + EuiTableRow, + EuiTableRowCell, + EuiSpacer, + useEuiTheme, +} from '@elastic/eui'; + +type Item = [string, string]; + +interface Section { + id: string; + title: string; + titleAction: string; + position: 'left' | 'right'; + items: Item[]; +} + +// fix for the annotation label being hidden inside the bounds of the chart container + +const SectionItem: FC<{ item: Item }> = ({ item }) => { + const { euiTheme } = useEuiTheme(); + const fontSize = euiTheme.size.m; + + return ( + + {item[0] !== '' && ( + + {item[0]} + + )} + + {item[1]} + + + ); +}; + +const Section: FC<{ section: Section }> = ({ section }) => { + const { euiTheme } = useEuiTheme(); + if (section.items.length === 0) { + return
    ; + } + + const cssOverride = css({ + overflow: 'auto', + padding: `${euiTheme.size.xs} ${euiTheme.size.m}`, + backgroundColor: euiTheme.colors.lightestShade, + border: `1px solid ${euiTheme.colors.lightShade}`, + borderRadius: euiTheme.border.radius.medium, + margin: `${euiTheme.size.s} 0`, + + '.euiTable': { + backgroundColor: 'transparent', + }, + + '.euiTableRow:hover': { + backgroundColor: 'inherit', + }, + '.euiTableRow:first-child': { + '.euiTableRowCell': { + borderTop: 0, + }, + }, + '.euiTableRow:last-child': { + '.euiTableRowCell': { + borderBottom: 0, + }, + }, + }); + + return ( + <> + + + + + +

    {section.title}

    +
    +
    + {section.titleAction} +
    +
    + +
    + + + {section.items.map((item, i) => ( + + ))} + + +
    +
    +
    + + ); +}; + +export const JobDetailsPane: FC<{ sections: any[]; 'data-test-subj': string }> = ({ + sections, + ...props +}) => { + return ( + <> + +
    + + + {sections + .filter((s) => s.position === 'left') + .map((s, i) => ( +
    + ))} + + + {sections + .filter((s) => s.position === 'right') + .map((s, i) => ( +
    + ))} + + +
    + + ); +}; diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_index.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_index.scss deleted file mode 100644 index bd0e4ba6a9d45..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'job_filter_bar'; \ No newline at end of file diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss deleted file mode 100644 index ecea309314dce..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/_job_filter_bar.scss +++ /dev/null @@ -1,23 +0,0 @@ -.mlJobFilterBar { - // SASSTODO: Dangerou EUI overwrites - .euiFilterGroup { - .euiPopover .euiPanel { - .group-item { - padding: $euiSizeS $euiSize; - } - - .inline-group { - border: 1px solid $euiColorEmptyShade; - border-radius: $euiBorderRadius; - } - - .euiFilterSelectItem:hover, .euiFilterSelectItem:focus { - text-decoration: none; - .inline-group { - border: 1px solid $euiColorDarkShade; - box-shadow: 0 1px 2px $euiColorMediumShade; - } - } - } - } -} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.tsx b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.tsx index dbc64d082f117..0384b8895dd6c 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.tsx +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_filter_bar/job_filter_bar.tsx @@ -155,7 +155,6 @@ export const JobFilterBar: FC = ({ queryText, setFilters }) = query={queryInstance} filters={filters} onChange={onChange} - className="mlJobFilterBar" /> diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_index.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_index.scss deleted file mode 100644 index 361f78b08fcc9..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'job_group'; \ No newline at end of file diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss deleted file mode 100644 index fc5bce54afb6a..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/job_group/_job_group.scss +++ /dev/null @@ -1,10 +0,0 @@ -.inline-group { - font-size: 12px; - background-color: $euiColorLightShade; - padding: 2px 5px; - border-radius: 2px; - display: inline-block; - margin: 0 3px; - color: $euiColorEmptyShade; - vertical-align: text-top; -} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_index.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_index.scss deleted file mode 100644 index c1d8b70a054a2..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'jobs_list_view'; \ No newline at end of file diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_jobs_list_view.scss b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_jobs_list_view.scss deleted file mode 100644 index ef0fbc358193e..0000000000000 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/_jobs_list_view.scss +++ /dev/null @@ -1,10 +0,0 @@ -// SASSTODO: Proper calcs -.actions-bar { - min-height: 60px; - display: flex; - align-items: center; -} - -.job-management { - padding: 20px; -} diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js index 179d5d48b3fe5..75ada48dbdc4c 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/jobs_list_view/jobs_list_view.js @@ -418,23 +418,33 @@ export class JobsListView extends Component {
    -
    - this.refreshJobSummaryList()} - /> - -
    + + + this.refreshJobSummaryList()} + /> + + + + + + {groups.map((g, index) => (
    this.closePopover()} > -
    +
    0; + return (
    - {jobsSelected && ( + {jobsSelected ? ( -
    +
    @@ -74,7 +83,7 @@ export class MultiJobActions extends Component { /> - )} + ) : null}
    ); } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/description.tsx index cd2156b059f47..f0043ca3ea47b 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/additional_section/components/custom_urls/description.tsx @@ -9,6 +9,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiDescribedFormGroup, EuiFormRow, EuiLink } from '@elastic/eui'; +import { css } from '@emotion/react'; import { useMlKibana } from '../../../../../../../../../contexts/kibana'; export const Description: FC = memo(({ children }) => { @@ -22,10 +23,21 @@ export const Description: FC = memo(({ children }) => { defaultMessage: 'Custom URLs', } ); + + const cssOverride = css({ + '> .euiFlexGroup': { + '> .euiFlexItem': { + '&:last-child': { + flexBasis: '50%', + }, + }, + }, + }); + return ( {title}} description={ .euiFlexGroup { - > .euiFlexItem { - &:first-child { - max-width: 388px; - } - &:last-child { - flex-basis: 50%; - } - } - } -} diff --git a/x-pack/plugins/ml/public/application/overview/_index.scss b/x-pack/plugins/ml/public/application/overview/_index.scss deleted file mode 100644 index 841415620d691..0000000000000 --- a/x-pack/plugins/ml/public/application/overview/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import 'components/index'; diff --git a/x-pack/plugins/ml/public/application/overview/components/_index.scss b/x-pack/plugins/ml/public/application/overview/components/_index.scss deleted file mode 100644 index 10abd3d6a25d5..0000000000000 --- a/x-pack/plugins/ml/public/application/overview/components/_index.scss +++ /dev/null @@ -1,8 +0,0 @@ -.mlOverviewPanel__isLoading { - text-align: center; - padding: 10%; -} - -.mlOverviewPanel__spinner { - display: inline-block; -} diff --git a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx index e5c1bb867bbd9..094693be8787e 100644 --- a/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx +++ b/x-pack/plugins/ml/public/application/overview/components/analytics_panel/analytics_panel.tsx @@ -75,8 +75,6 @@ export const AnalyticsPanel: FC = ({ setLazyJobCount }) => { ); - const panelClass = isInitialized === false ? 'mlOverviewPanel__isLoading' : 'mlOverviewPanel'; - const noDFAJobs = errorMessage === undefined && isInitialized === true && analytics.length === 0; return ( @@ -84,10 +82,14 @@ export const AnalyticsPanel: FC = ({ setLazyJobCount }) => { {noDFAJobs ? ( ) : ( - + {typeof errorMessage !== 'undefined' ? errorDisplay : null} {isInitialized === false && ( - + )} {isInitialized === true && analytics.length > 0 && ( From 1b9b77fd123d4977fa3743b4749016376f5bc6cb Mon Sep 17 00:00:00 2001 From: Walter Rafelsberger Date: Thu, 2 Mar 2023 11:47:24 +0100 Subject: [PATCH 109/131] [ML] Fix regression to skip considering future data on use full data button in ML plugin. (#152435) Fixes a regression where the "Use full data" button in the ML plugin would no longer avoid considering future data. --- x-pack/packages/ml/date_picker/index.ts | 1 + .../components/full_time_range_selector.tsx | 16 +++++++++++--- .../full_time_range_selector_service.ts | 22 ++++++++++++++++++- .../src/services/time_field_range.ts | 8 +++++-- .../components/time_range_step/time_range.tsx | 1 + 5 files changed, 42 insertions(+), 6 deletions(-) diff --git a/x-pack/packages/ml/date_picker/index.ts b/x-pack/packages/ml/date_picker/index.ts index f795d6a4d1f06..1a949a5d1e1d1 100644 --- a/x-pack/packages/ml/date_picker/index.ts +++ b/x-pack/packages/ml/date_picker/index.ts @@ -23,6 +23,7 @@ export { export { getTimeFilterRange, type TimeRange, + type SetFullTimeRangeApiPath, } from './src/services/full_time_range_selector_service'; export { type GetTimeFieldRangeResponse } from './src/services/types'; export { mlTimefilterRefresh$, type Refresh } from './src/services/timefilter_refresh_service'; diff --git a/x-pack/packages/ml/date_picker/src/components/full_time_range_selector.tsx b/x-pack/packages/ml/date_picker/src/components/full_time_range_selector.tsx index bfdd1cb43138d..3ea3c091907ee 100644 --- a/x-pack/packages/ml/date_picker/src/components/full_time_range_selector.tsx +++ b/x-pack/packages/ml/date_picker/src/components/full_time_range_selector.tsx @@ -26,7 +26,10 @@ import type { DataView } from '@kbn/data-plugin/common'; import type { TimefilterContract } from '@kbn/data-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { useDatePickerContext } from '../hooks/use_date_picker_context'; -import { setFullTimeRange } from '../services/full_time_range_selector_service'; +import { + setFullTimeRange, + type SetFullTimeRangeApiPath, +} from '../services/full_time_range_selector_service'; import type { GetTimeFieldRangeResponse } from '../services/types'; import { FROZEN_TIER_PREFERENCE, type FrozenTierPreference } from '../storage'; @@ -64,6 +67,11 @@ export interface FullTimeRangeSelectorProps { * @param value - The time field range response. */ callback?: (value: GetTimeFieldRangeResponse) => void; + /** + * Optional API path. + * @param value - The time field range response. + */ + apiPath?: SetFullTimeRangeApiPath; } /** @@ -83,6 +91,7 @@ export const FullTimeRangeSelector: FC = (props) => query, disabled, callback, + apiPath, } = props; const { http, @@ -98,7 +107,8 @@ export const FullTimeRangeSelector: FC = (props) => toasts, http, query, - frozenDataPreference === FROZEN_TIER_PREFERENCE.EXCLUDE + frozenDataPreference === FROZEN_TIER_PREFERENCE.EXCLUDE, + apiPath ); if (typeof callback === 'function') { callback(fullTimeRange); @@ -113,7 +123,7 @@ export const FullTimeRangeSelector: FC = (props) => ) ); } - }, [callback, dataView, frozenDataPreference, http, query, timefilter, toasts]); + }, [callback, dataView, frozenDataPreference, http, query, timefilter, toasts, apiPath]); const [isPopoverOpen, setPopover] = useState(false); diff --git a/x-pack/packages/ml/date_picker/src/services/full_time_range_selector_service.ts b/x-pack/packages/ml/date_picker/src/services/full_time_range_selector_service.ts index ab8d79292fd26..12cd8c724e96d 100644 --- a/x-pack/packages/ml/date_picker/src/services/full_time_range_selector_service.ts +++ b/x-pack/packages/ml/date_picker/src/services/full_time_range_selector_service.ts @@ -17,6 +17,13 @@ import { addExcludeFrozenToQuery } from '@kbn/ml-query-utils'; import { getTimeFieldRange } from './time_field_range'; import type { GetTimeFieldRangeResponse } from './types'; +/** + * Allowed API paths to be passed to `setFullTimeRange`. + */ +export type SetFullTimeRangeApiPath = + | '/internal/file_upload/time_field_range' + | '/api/ml/fields_service/time_field_range'; + /** * Determines the full available time range of the given Data View and updates * the timefilter accordingly. @@ -27,6 +34,7 @@ import type { GetTimeFieldRangeResponse } from './types'; * @param http - HttpStart * @param query - optional query * @param excludeFrozenData - optional boolean flag + * @param path - optional SetFullTimeRangeApiPath * @returns {GetTimeFieldRangeResponse} */ export async function setFullTimeRange( @@ -35,7 +43,8 @@ export async function setFullTimeRange( toasts: ToastsStart, http: HttpStart, query?: QueryDslQueryContainer, - excludeFrozenData?: boolean + excludeFrozenData?: boolean, + path: SetFullTimeRangeApiPath = '/internal/file_upload/time_field_range' ): Promise { try { const runtimeMappings = dataView.getRuntimeMappings(); @@ -45,6 +54,7 @@ export async function setFullTimeRange( query: excludeFrozenData ? addExcludeFrozenToQuery(query) : query, ...(isPopulatedObject(runtimeMappings) ? { runtimeMappings } : {}), http, + path, }); if (resp.start.epoch && resp.end.epoch) { @@ -52,6 +62,16 @@ export async function setFullTimeRange( from: moment(resp.start.epoch).toISOString(), to: moment(resp.end.epoch).toISOString(), }); + } else if (typeof resp.start === 'number' && typeof resp.end === 'number') { + timefilter.setTime({ + from: moment(resp.start).toISOString(), + to: moment(resp.end).toISOString(), + }); + return { + success: true, + start: { epoch: resp.start, string: moment(resp.start).toISOString() }, + end: { epoch: resp.end, string: moment(resp.end).toISOString() }, + }; } else { toasts.addWarning({ title: i18n.translate('xpack.ml.datePicker.fullTimeRangeSelector.noResults', { diff --git a/x-pack/packages/ml/date_picker/src/services/time_field_range.ts b/x-pack/packages/ml/date_picker/src/services/time_field_range.ts index 3cbf382ecc6c7..117dddc9dfaf3 100644 --- a/x-pack/packages/ml/date_picker/src/services/time_field_range.ts +++ b/x-pack/packages/ml/date_picker/src/services/time_field_range.ts @@ -36,6 +36,10 @@ interface GetTimeFieldRangeOptions { * HTTP client */ http: HttpStart; + /** + * API path ('/internal/file_upload/time_field_range') + */ + path: string; } /** @@ -44,10 +48,10 @@ interface GetTimeFieldRangeOptions { * @returns GetTimeFieldRangeResponse */ export async function getTimeFieldRange(options: GetTimeFieldRangeOptions) { - const { http, ...body } = options; + const { http, path, ...body } = options; return await http.fetch({ - path: `/internal/file_upload/time_field_range`, + path, method: 'POST', body: JSON.stringify(body), }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/time_range_step/time_range.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/time_range_step/time_range.tsx index 4dc7b498144cf..309b751a0da5d 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/time_range_step/time_range.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/time_range_step/time_range.tsx @@ -135,6 +135,7 @@ export const TimeRangeStep: FC = ({ setCurrentStep, isCurrentStep }) disabled={false} callback={fullTimeRangeCallback} timefilter={timefilter} + apiPath="/api/ml/fields_service/time_field_range" /> From 54b2a4affa3a223d9f71b638f6231d01aab9fb87 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 2 Mar 2023 11:57:23 +0000 Subject: [PATCH 110/131] [ML] Fixing wizard input vertical alignment (#152469) Fixes. https://github.com/elastic/kibana/issues/152465 Some description components wrap the children in a `EuiFormRow`, this adds a slight height difference to the inner inputs. This PR adds `EuiFormRow` wrappers to all description components. Before: ![](https://user-images.githubusercontent.com/7405507/222182204-50509b4c-54ad-4947-b73c-f2d6a1fc0818.png) After: ![image](https://user-images.githubusercontent.com/22172091/222194929-43231c45-7213-483a-9031-221b90f8e63b.png) --- .../advanced_section/components/annotations/description.tsx | 6 ++++-- .../components/dedicated_index/description.tsx | 6 ++++-- .../advanced_section/components/model_plot/description.tsx | 6 ++++-- .../categorization_partition_field/description.tsx | 6 ++++-- .../pick_fields_step/components/geo_field/description.tsx | 6 ++++-- .../components/population_field/description.tsx | 6 ++++-- .../pick_fields_step/components/rare_field/description.tsx | 6 ++++-- .../pick_fields_step/components/sparse_data/description.tsx | 6 ++++-- 8 files changed, 32 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/annotations/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/annotations/description.tsx index 0f8a7c70fe207..9cdd208fbfccd 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/annotations/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/annotations/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; export const Description: FC = memo(({ children }) => { const title = i18n.translate( @@ -27,7 +27,9 @@ export const Description: FC = memo(({ children }) => { /> } > - <>{children} + + <>{children} + ); }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/dedicated_index/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/dedicated_index/description.tsx index 6b207928b4c99..daa9ac0ddbc53 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/dedicated_index/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/dedicated_index/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; export const Description: FC = memo(({ children }) => { const title = i18n.translate( @@ -27,7 +27,9 @@ export const Description: FC = memo(({ children }) => { /> } > - <>{children} + + <>{children} + ); }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/model_plot/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/model_plot/description.tsx index 31b9821292758..7cfabf25bad88 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/model_plot/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/job_details_step/components/advanced_section/components/model_plot/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; export const Description: FC = memo(({ children }) => { const title = i18n.translate( @@ -27,7 +27,9 @@ export const Description: FC = memo(({ children }) => { /> } > - <>{children} + + <>{children} + ); }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_partition_field/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_partition_field/description.tsx index 3c329d1c2f092..18c4e419243a9 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_partition_field/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/categorization_partition_field/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; interface Props { children: React.ReactNode; @@ -27,7 +27,9 @@ export const Description: FC = memo(({ children }) => { /> } > - <>{children} + + <>{children} + ); }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_field/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_field/description.tsx index 25b73ed2f5e1c..287a909911605 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_field/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/geo_field/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; export const Description: FC = memo(({ children }) => { const title = i18n.translate('xpack.ml.newJob.wizard.pickFieldsStep.geoField.title', { @@ -24,7 +24,9 @@ export const Description: FC = memo(({ children }) => { /> } > - <>{children} + + <>{children} + ); }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_field/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_field/description.tsx index d27953d2e8e10..48e62fc62051b 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_field/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/population_field/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; export const Description: FC = memo(({ children }) => { const title = i18n.translate('xpack.ml.newJob.wizard.pickFieldsStep.populationField.title', { @@ -24,7 +24,9 @@ export const Description: FC = memo(({ children }) => { /> } > - <>{children} + + <>{children} + ); }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/rare_field/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/rare_field/description.tsx index 78f0f62294da5..15b618386538a 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/rare_field/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/rare_field/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; export const Description: FC = memo(({ children }) => { const title = i18n.translate('xpack.ml.newJob.wizard.pickFieldsStep.splitRareField.title', { @@ -24,7 +24,9 @@ export const Description: FC = memo(({ children }) => { /> } > - <>{children} + + <>{children} + ); }); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/sparse_data/description.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/sparse_data/description.tsx index cf75b9c60852e..8471aba98c636 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/sparse_data/description.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/sparse_data/description.tsx @@ -8,7 +8,7 @@ import React, { memo, FC } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { EuiDescribedFormGroup } from '@elastic/eui'; +import { EuiDescribedFormGroup, EuiFormRow } from '@elastic/eui'; export const Description: FC = memo(({ children }) => { const title = i18n.translate('xpack.ml.newJob.wizard.pickFieldsStep.sparseData.title', { @@ -24,7 +24,9 @@ export const Description: FC = memo(({ children }) => { /> } > - {children} + + <>{children} + ); }); From 7d81cf290f4f1a169fe18c9c29a5be17b0bbfb86 Mon Sep 17 00:00:00 2001 From: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com> Date: Thu, 2 Mar 2023 07:35:03 -0500 Subject: [PATCH 111/131] [Cases] Integrating file service and registering file kinds (#152031) This PR registers three file kinds for cases. One for each instance of cases (stack, observability, and security). Each solution needs separate http tags for the routes that are generated by the file service to implement RBAC. I refactored the logic to remove some duplication across the three plugins since we're essentially registering the same http tags with slightly different names. This PR shouldn't affect any of the current functionality. Notable changes: - I split up the constants.ts file, really the only change is adding the file kinds logic to generate the http tags the rest is copy/paste - Refactored the logic to generate the `api` http tags for each plugin - Registered the three file kinds Issues: https://github.com/elastic/kibana/issues/151780 https://github.com/elastic/kibana/issues/151933 --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../cases/common/constants/application.ts | 31 ++ .../plugins/cases/common/constants/files.ts | 14 + .../{constants.ts => constants/index.ts} | 76 +--- .../cases/common/constants/mime_types.ts | 110 ++++++ .../plugins/cases/common/constants/owners.ts | 50 +++ .../plugins/cases/common/constants/types.ts | 16 + x-pack/plugins/cases/common/index.ts | 1 + .../utils/__snapshots__/api_tags.test.ts.snap | 58 +++ .../cases/common/utils/api_tags.test.ts | 17 + x-pack/plugins/cases/common/utils/api_tags.ts | 26 ++ x-pack/plugins/cases/kibana.jsonc | 3 +- x-pack/plugins/cases/public/files/index.ts | 36 ++ x-pack/plugins/cases/public/plugin.ts | 3 + x-pack/plugins/cases/public/types.ts | 3 + x-pack/plugins/cases/server/features.ts | 16 +- x-pack/plugins/cases/server/files/index.ts | 71 ++++ x-pack/plugins/cases/server/plugin.ts | 5 + x-pack/plugins/cases/tsconfig.json | 2 + x-pack/plugins/observability/kibana.jsonc | 3 +- x-pack/plugins/observability/server/plugin.ts | 22 +- x-pack/plugins/observability/tsconfig.json | 1 + .../security_solution/server/features.ts | 21 +- .../apis/cases/common/users.ts | 6 - .../test/api_integration/apis/cases/files.ts | 365 ++++++++++++++++++ .../test/api_integration/apis/cases/index.ts | 1 + .../common/lib/api/files.ts | 226 +++++++++++ .../common/lib/api/index.ts | 1 + .../common/lib/authentication/index.ts | 44 +-- x-pack/test/tsconfig.json | 2 + 29 files changed, 1115 insertions(+), 115 deletions(-) create mode 100644 x-pack/plugins/cases/common/constants/application.ts create mode 100644 x-pack/plugins/cases/common/constants/files.ts rename x-pack/plugins/cases/common/{constants.ts => constants/index.ts} (73%) create mode 100644 x-pack/plugins/cases/common/constants/mime_types.ts create mode 100644 x-pack/plugins/cases/common/constants/owners.ts create mode 100644 x-pack/plugins/cases/common/constants/types.ts create mode 100644 x-pack/plugins/cases/common/utils/__snapshots__/api_tags.test.ts.snap create mode 100644 x-pack/plugins/cases/common/utils/api_tags.test.ts create mode 100644 x-pack/plugins/cases/common/utils/api_tags.ts create mode 100644 x-pack/plugins/cases/public/files/index.ts create mode 100644 x-pack/plugins/cases/server/files/index.ts create mode 100644 x-pack/test/api_integration/apis/cases/files.ts create mode 100644 x-pack/test/cases_api_integration/common/lib/api/files.ts diff --git a/x-pack/plugins/cases/common/constants/application.ts b/x-pack/plugins/cases/common/constants/application.ts new file mode 100644 index 0000000000000..4b43a17708ab6 --- /dev/null +++ b/x-pack/plugins/cases/common/constants/application.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CASE_VIEW_PAGE_TABS } from '../types'; + +/** + * Application + */ + +export const APP_ID = 'cases' as const; +export const FEATURE_ID = 'generalCases' as const; +export const APP_OWNER = 'cases' as const; +export const APP_PATH = '/app/management/insightsAndAlerting/cases' as const; +export const CASES_CREATE_PATH = '/create' as const; +export const CASES_CONFIGURE_PATH = '/configure' as const; +export const CASE_VIEW_PATH = '/:detailName' as const; +export const CASE_VIEW_COMMENT_PATH = `${CASE_VIEW_PATH}/:commentId` as const; +export const CASE_VIEW_ALERT_TABLE_PATH = + `${CASE_VIEW_PATH}/?tabId=${CASE_VIEW_PAGE_TABS.ALERTS}` as const; +export const CASE_VIEW_TAB_PATH = `${CASE_VIEW_PATH}/?tabId=:tabId` as const; + +/** + * The main Cases application is in the stack management under the + * Alerts and Insights section. To do that, Cases registers to the management + * application. This constant holds the application ID of the management plugin + */ +export const STACK_APP_ID = 'management' as const; diff --git a/x-pack/plugins/cases/common/constants/files.ts b/x-pack/plugins/cases/common/constants/files.ts new file mode 100644 index 0000000000000..7cd7109137976 --- /dev/null +++ b/x-pack/plugins/cases/common/constants/files.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { HttpApiTagOperation, Owner } from './types'; + +export const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 MiB + +export const constructFilesHttpOperationTag = (owner: Owner, operation: HttpApiTagOperation) => { + return `${owner}FilesCases${operation}`; +}; diff --git a/x-pack/plugins/cases/common/constants.ts b/x-pack/plugins/cases/common/constants/index.ts similarity index 73% rename from x-pack/plugins/cases/common/constants.ts rename to x-pack/plugins/cases/common/constants/index.ts index 601599104641b..f837223e6a07c 100644 --- a/x-pack/plugins/cases/common/constants.ts +++ b/x-pack/plugins/cases/common/constants/index.ts @@ -4,34 +4,15 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { CASE_VIEW_PAGE_TABS } from './types'; -import type { CasesFeaturesAllRequired } from './ui/types'; -export const DEFAULT_DATE_FORMAT = 'dateFormat' as const; -export const DEFAULT_DATE_FORMAT_TZ = 'dateFormat:tz' as const; - -/** - * Application - */ +import type { CasesFeaturesAllRequired } from '../ui/types'; -export const APP_ID = 'cases' as const; -export const FEATURE_ID = 'generalCases' as const; -export const APP_OWNER = 'cases' as const; -export const APP_PATH = '/app/management/insightsAndAlerting/cases' as const; -export const CASES_CREATE_PATH = '/create' as const; -export const CASES_CONFIGURE_PATH = '/configure' as const; -export const CASE_VIEW_PATH = '/:detailName' as const; -export const CASE_VIEW_COMMENT_PATH = `${CASE_VIEW_PATH}/:commentId` as const; -export const CASE_VIEW_ALERT_TABLE_PATH = - `${CASE_VIEW_PATH}/?tabId=${CASE_VIEW_PAGE_TABS.ALERTS}` as const; -export const CASE_VIEW_TAB_PATH = `${CASE_VIEW_PATH}/?tabId=:tabId` as const; +export * from './owners'; +export * from './files'; +export * from './application'; -/** - * The main Cases application is in the stack management under the - * Alerts and Insights section. To do that, Cases registers to the management - * application. This constant holds the application ID of the management plugin - */ -export const STACK_APP_ID = 'management' as const; +export const DEFAULT_DATE_FORMAT = 'dateFormat' as const; +export const DEFAULT_DATE_FORMAT_TZ = 'dateFormat:tz' as const; /** * Saved objects @@ -111,37 +92,6 @@ export const CONNECTORS_URL = `${ACTION_URL}/connectors` as const; */ export const MAX_ALERTS_PER_CASE = 1000 as const; -/** - * Owner - */ -export const SECURITY_SOLUTION_OWNER = 'securitySolution' as const; -export const OBSERVABILITY_OWNER = 'observability' as const; -export const GENERAL_CASES_OWNER = APP_ID; - -export const OWNER_INFO = { - [SECURITY_SOLUTION_OWNER]: { - id: SECURITY_SOLUTION_OWNER, - appId: 'securitySolutionUI', - label: 'Security', - iconType: 'logoSecurity', - appRoute: '/app/security', - }, - [OBSERVABILITY_OWNER]: { - id: OBSERVABILITY_OWNER, - appId: 'observability-overview', - label: 'Observability', - iconType: 'logoObservability', - appRoute: '/app/observability', - }, - [GENERAL_CASES_OWNER]: { - id: GENERAL_CASES_OWNER, - appId: 'management', - label: 'Stack', - iconType: 'casesApp', - appRoute: '/app/management/insightsAndAlerting', - }, -} as const; - /** * Searching */ @@ -186,6 +136,20 @@ export const UPDATE_CASES_CAPABILITY = 'update_cases' as const; export const DELETE_CASES_CAPABILITY = 'delete_cases' as const; export const PUSH_CASES_CAPABILITY = 'push_cases' as const; +/** + * Cases API Tags + */ + +/** + * This tag registered for the cases suggest user profiles API + */ +export const SUGGEST_USER_PROFILES_API_TAG = 'casesSuggestUserProfiles'; + +/** + * This tag is registered for the security bulk get API + */ +export const BULK_GET_USER_PROFILES_API_TAG = 'bulkGetUserProfiles'; + /** * User profiles */ diff --git a/x-pack/plugins/cases/common/constants/mime_types.ts b/x-pack/plugins/cases/common/constants/mime_types.ts new file mode 100644 index 0000000000000..9f1f455513dab --- /dev/null +++ b/x-pack/plugins/cases/common/constants/mime_types.ts @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/** + * These were retrieved from https://www.iana.org/assignments/media-types/media-types.xhtml#image + */ +const imageMimeTypes = [ + 'image/aces', + 'image/apng', + 'image/avci', + 'image/avcs', + 'image/avif', + 'image/bmp', + 'image/cgm', + 'image/dicom-rle', + 'image/dpx', + 'image/emf', + 'image/example', + 'image/fits', + 'image/g3fax', + 'image/heic', + 'image/heic-sequence', + 'image/heif', + 'image/heif-sequence', + 'image/hej2k', + 'image/hsj2', + 'image/jls', + 'image/jp2', + 'image/jpeg', + 'image/jph', + 'image/jphc', + 'image/jpm', + 'image/jpx', + 'image/jxr', + 'image/jxrA', + 'image/jxrS', + 'image/jxs', + 'image/jxsc', + 'image/jxsi', + 'image/jxss', + 'image/ktx', + 'image/ktx2', + 'image/naplps', + 'image/png', + 'image/prs.btif', + 'image/prs.pti', + 'image/pwg-raster', + 'image/svg+xml', + 'image/t38', + 'image/tiff', + 'image/tiff-fx', + 'image/vnd.adobe.photoshop', + 'image/vnd.airzip.accelerator.azv', + 'image/vnd.cns.inf2', + 'image/vnd.dece.graphic', + 'image/vnd.djvu', + 'image/vnd.dwg', + 'image/vnd.dxf', + 'image/vnd.dvb.subtitle', + 'image/vnd.fastbidsheet', + 'image/vnd.fpx', + 'image/vnd.fst', + 'image/vnd.fujixerox.edmics-mmr', + 'image/vnd.fujixerox.edmics-rlc', + 'image/vnd.globalgraphics.pgb', + 'image/vnd.microsoft.icon', + 'image/vnd.mix', + 'image/vnd.ms-modi', + 'image/vnd.mozilla.apng', + 'image/vnd.net-fpx', + 'image/vnd.pco.b16', + 'image/vnd.radiance', + 'image/vnd.sealed.png', + 'image/vnd.sealedmedia.softseal.gif', + 'image/vnd.sealedmedia.softseal.jpg', + 'image/vnd.svf', + 'image/vnd.tencent.tap', + 'image/vnd.valve.source.texture', + 'image/vnd.wap.wbmp', + 'image/vnd.xiff', + 'image/vnd.zbrush.pcx', + 'image/webp', + 'image/wmf', +]; + +const textMimeTypes = ['text/plain', 'text/csv', 'text/json', 'application/json']; + +const compressionMimeTypes = [ + 'application/zip', + 'application/gzip', + 'application/x-bzip', + 'application/x-bzip2', + 'application/x-7z-compressed', + 'application/x-tar', +]; + +const pdfMimeTypes = ['application/pdf']; + +export const ALLOWED_MIME_TYPES = [ + ...imageMimeTypes, + ...textMimeTypes, + ...compressionMimeTypes, + ...pdfMimeTypes, +]; + +export const IMAGE_MIME_TYPES = new Set(imageMimeTypes); diff --git a/x-pack/plugins/cases/common/constants/owners.ts b/x-pack/plugins/cases/common/constants/owners.ts new file mode 100644 index 0000000000000..60463fa57a976 --- /dev/null +++ b/x-pack/plugins/cases/common/constants/owners.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { APP_ID } from './application'; +import type { Owner } from './types'; + +/** + * Owner + */ +export const SECURITY_SOLUTION_OWNER = 'securitySolution' as const; +export const OBSERVABILITY_OWNER = 'observability' as const; +export const GENERAL_CASES_OWNER = APP_ID; + +export const OWNERS = [SECURITY_SOLUTION_OWNER, OBSERVABILITY_OWNER, GENERAL_CASES_OWNER] as const; + +interface RouteInfo { + id: Owner; + appId: string; + label: string; + iconType: string; + appRoute: string; +} + +export const OWNER_INFO: Record = { + [SECURITY_SOLUTION_OWNER]: { + id: SECURITY_SOLUTION_OWNER, + appId: 'securitySolutionUI', + label: 'Security', + iconType: 'logoSecurity', + appRoute: '/app/security', + }, + [OBSERVABILITY_OWNER]: { + id: OBSERVABILITY_OWNER, + appId: 'observability-overview', + label: 'Observability', + iconType: 'logoObservability', + appRoute: '/app/observability', + }, + [GENERAL_CASES_OWNER]: { + id: GENERAL_CASES_OWNER, + appId: 'management', + label: 'Stack', + iconType: 'casesApp', + appRoute: '/app/management/insightsAndAlerting', + }, +} as const; diff --git a/x-pack/plugins/cases/common/constants/types.ts b/x-pack/plugins/cases/common/constants/types.ts new file mode 100644 index 0000000000000..27ee99fa95c9a --- /dev/null +++ b/x-pack/plugins/cases/common/constants/types.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { OWNERS } from './owners'; + +export enum HttpApiTagOperation { + Read = 'Read', + Create = 'Create', + Delete = 'Delete', +} + +export type Owner = typeof OWNERS[number]; diff --git a/x-pack/plugins/cases/common/index.ts b/x-pack/plugins/cases/common/index.ts index 8ca2c23c1eb8d..d41de5543654d 100644 --- a/x-pack/plugins/cases/common/index.ts +++ b/x-pack/plugins/cases/common/index.ts @@ -55,3 +55,4 @@ export { StatusAll } from './ui/types'; export { getCreateConnectorUrl, getAllConnectorsUrl } from './utils/connectors_api'; export { createUICapabilities } from './utils/capabilities'; +export { getApiTags } from './utils/api_tags'; diff --git a/x-pack/plugins/cases/common/utils/__snapshots__/api_tags.test.ts.snap b/x-pack/plugins/cases/common/utils/__snapshots__/api_tags.test.ts.snap new file mode 100644 index 0000000000000..ea1ef29e71c59 --- /dev/null +++ b/x-pack/plugins/cases/common/utils/__snapshots__/api_tags.test.ts.snap @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`api_tags getApiTags constructs the https tags for the owner: cases 1`] = ` +Object { + "all": Array [ + "casesSuggestUserProfiles", + "bulkGetUserProfiles", + "casesFilesCasesCreate", + "casesFilesCasesRead", + ], + "delete": Array [ + "casesFilesCasesDelete", + ], + "read": Array [ + "casesSuggestUserProfiles", + "bulkGetUserProfiles", + "casesFilesCasesRead", + ], +} +`; + +exports[`api_tags getApiTags constructs the https tags for the owner: observability 1`] = ` +Object { + "all": Array [ + "casesSuggestUserProfiles", + "bulkGetUserProfiles", + "observabilityFilesCasesCreate", + "observabilityFilesCasesRead", + ], + "delete": Array [ + "observabilityFilesCasesDelete", + ], + "read": Array [ + "casesSuggestUserProfiles", + "bulkGetUserProfiles", + "observabilityFilesCasesRead", + ], +} +`; + +exports[`api_tags getApiTags constructs the https tags for the owner: securitySolution 1`] = ` +Object { + "all": Array [ + "casesSuggestUserProfiles", + "bulkGetUserProfiles", + "securitySolutionFilesCasesCreate", + "securitySolutionFilesCasesRead", + ], + "delete": Array [ + "securitySolutionFilesCasesDelete", + ], + "read": Array [ + "casesSuggestUserProfiles", + "bulkGetUserProfiles", + "securitySolutionFilesCasesRead", + ], +} +`; diff --git a/x-pack/plugins/cases/common/utils/api_tags.test.ts b/x-pack/plugins/cases/common/utils/api_tags.test.ts new file mode 100644 index 0000000000000..61e8e335be2cf --- /dev/null +++ b/x-pack/plugins/cases/common/utils/api_tags.test.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 { OWNERS } from '../constants'; +import { getApiTags } from './api_tags'; + +describe('api_tags', () => { + describe('getApiTags', () => { + it.each(OWNERS)('constructs the https tags for the owner: %s', (owner) => { + expect(getApiTags(owner)).toMatchSnapshot(); + }); + }); +}); diff --git a/x-pack/plugins/cases/common/utils/api_tags.ts b/x-pack/plugins/cases/common/utils/api_tags.ts new file mode 100644 index 0000000000000..707188a0fba33 --- /dev/null +++ b/x-pack/plugins/cases/common/utils/api_tags.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + BULK_GET_USER_PROFILES_API_TAG, + constructFilesHttpOperationTag, + SUGGEST_USER_PROFILES_API_TAG, +} from '../constants'; +import { HttpApiTagOperation } from '../constants/types'; +import type { Owner } from '../constants/types'; + +export const getApiTags = (owner: Owner) => { + const create = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Create); + const deleteTag = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Delete); + const read = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Read); + + return { + all: [SUGGEST_USER_PROFILES_API_TAG, BULK_GET_USER_PROFILES_API_TAG, create, read] as const, + read: [SUGGEST_USER_PROFILES_API_TAG, BULK_GET_USER_PROFILES_API_TAG, read] as const, + delete: [deleteTag] as const, + }; +}; diff --git a/x-pack/plugins/cases/kibana.jsonc b/x-pack/plugins/cases/kibana.jsonc index 94263c383745f..afed1cd7631f8 100644 --- a/x-pack/plugins/cases/kibana.jsonc +++ b/x-pack/plugins/cases/kibana.jsonc @@ -25,7 +25,8 @@ "management", "security", "notifications", - "ruleRegistry" + "ruleRegistry", + "files", ], "optionalPlugins": [ "home", diff --git a/x-pack/plugins/cases/public/files/index.ts b/x-pack/plugins/cases/public/files/index.ts new file mode 100644 index 0000000000000..e06c8eda615a0 --- /dev/null +++ b/x-pack/plugins/cases/public/files/index.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FilesSetup } from '@kbn/files-plugin/public'; +import type { FileKindBrowser } from '@kbn/shared-ux-file-types'; +import { ALLOWED_MIME_TYPES } from '../../common/constants/mime_types'; +import { MAX_FILE_SIZE } from '../../common/constants'; +import type { Owner } from '../../common/constants/types'; +import { APP_ID, OBSERVABILITY_OWNER, SECURITY_SOLUTION_OWNER } from '../../common'; + +const buildFileKind = (owner: Owner): FileKindBrowser => { + return { + id: owner, + allowedMimeTypes: ALLOWED_MIME_TYPES, + maxSizeBytes: MAX_FILE_SIZE, + }; +}; + +/** + * The file kind definition for interacting with the file service for the UI + */ +const CASES_FILE_KINDS: Record = { + [APP_ID]: buildFileKind(APP_ID), + [SECURITY_SOLUTION_OWNER]: buildFileKind(SECURITY_SOLUTION_OWNER), + [OBSERVABILITY_OWNER]: buildFileKind(OBSERVABILITY_OWNER), +}; + +export const registerCaseFileKinds = (filesSetupPlugin: FilesSetup) => { + for (const fileKind of Object.values(CASES_FILE_KINDS)) { + filesSetupPlugin.registerFileKind(fileKind); + } +}; diff --git a/x-pack/plugins/cases/public/plugin.ts b/x-pack/plugins/cases/public/plugin.ts index 51f2ae92e3094..83b0f2fb0f009 100644 --- a/x-pack/plugins/cases/public/plugin.ts +++ b/x-pack/plugins/cases/public/plugin.ts @@ -27,6 +27,7 @@ import { groupAlertsByRule } from './client/helpers/group_alerts_by_rule'; import { getUICapabilities } from './client/helpers/capabilities'; import { ExternalReferenceAttachmentTypeRegistry } from './client/attachment_framework/external_reference_registry'; import { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; +import { registerCaseFileKinds } from './files'; /** * @public @@ -52,6 +53,8 @@ export class CasesUiPlugin const externalReferenceAttachmentTypeRegistry = this.externalReferenceAttachmentTypeRegistry; const persistableStateAttachmentTypeRegistry = this.persistableStateAttachmentTypeRegistry; + registerCaseFileKinds(plugins.files); + if (plugins.home) { plugins.home.featureCatalogue.register({ id: APP_ID, diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts index 732fcfee5f0d6..f430b99ae17f2 100644 --- a/x-pack/plugins/cases/public/types.ts +++ b/x-pack/plugins/cases/public/types.ts @@ -22,6 +22,7 @@ import type { TriggersAndActionsUIPublicPluginStart as TriggersActionsStart } fr import type { DistributiveOmit } from '@elastic/eui'; import type { ApmBase } from '@elastic/apm-rum'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; +import type { FilesSetup, FilesStart } from '@kbn/files-plugin/public'; import type { CasesByAlertId, CasesByAlertIDRequest, @@ -50,6 +51,7 @@ import type { ExternalReferenceAttachmentTypeRegistry } from './client/attachmen import type { PersistableStateAttachmentTypeRegistry } from './client/attachment_framework/persistable_state_registry'; export interface CasesPluginSetup { + files: FilesSetup; security: SecurityPluginSetup; management: ManagementSetup; home?: HomePublicPluginSetup; @@ -58,6 +60,7 @@ export interface CasesPluginSetup { export interface CasesPluginStart { data: DataPublicPluginStart; embeddable: EmbeddableStart; + files: FilesStart; licensing?: LicensingPluginStart; lens: LensPublicStart; storage: Storage; diff --git a/x-pack/plugins/cases/server/features.ts b/x-pack/plugins/cases/server/features.ts index 2573e5f58b3f3..05ee00cb1b037 100644 --- a/x-pack/plugins/cases/server/features.ts +++ b/x-pack/plugins/cases/server/features.ts @@ -8,10 +8,11 @@ import { i18n } from '@kbn/i18n'; import type { KibanaFeatureConfig } from '@kbn/features-plugin/common'; +import { hiddenTypes as filesSavedObjectTypes } from '@kbn/files-plugin/server/saved_objects'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { APP_ID, FEATURE_ID } from '../common/constants'; -import { createUICapabilities } from '../common'; +import { createUICapabilities, getApiTags } from '../common'; /** * The order of appearance in the feature privilege page @@ -23,6 +24,7 @@ const FEATURE_ORDER = 3100; export const getCasesKibanaFeature = (): KibanaFeatureConfig => { const capabilities = createUICapabilities(); + const apiTags = getApiTags(APP_ID); return { id: FEATURE_ID, @@ -38,7 +40,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { cases: [APP_ID], privileges: { all: { - api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], + api: apiTags.all, cases: { create: [APP_ID], read: [APP_ID], @@ -49,13 +51,13 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { insightsAndAlerting: [APP_ID], }, savedObject: { - all: [], - read: [], + all: [...filesSavedObjectTypes], + read: [...filesSavedObjectTypes], }, ui: capabilities.all, }, read: { - api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], + api: apiTags.read, cases: { read: [APP_ID], }, @@ -64,7 +66,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { }, savedObject: { all: [], - read: [], + read: [...filesSavedObjectTypes], }, ui: capabilities.read, }, @@ -79,7 +81,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { groupType: 'independent', privileges: [ { - api: [], + api: apiTags.delete, id: 'cases_delete', name: i18n.translate('xpack.cases.features.deleteSubFeatureDetails', { defaultMessage: 'Delete cases and comments', diff --git a/x-pack/plugins/cases/server/files/index.ts b/x-pack/plugins/cases/server/files/index.ts new file mode 100644 index 0000000000000..fb17fd50fa870 --- /dev/null +++ b/x-pack/plugins/cases/server/files/index.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 type { FileJSON, FileKind } from '@kbn/files-plugin/common'; +import type { FilesSetup } from '@kbn/files-plugin/server'; +import { + APP_ID, + constructFilesHttpOperationTag, + MAX_FILE_SIZE, + OBSERVABILITY_OWNER, + SECURITY_SOLUTION_OWNER, +} from '../../common/constants'; +import type { Owner } from '../../common/constants/types'; +import { HttpApiTagOperation } from '../../common/constants/types'; +import { ALLOWED_MIME_TYPES, IMAGE_MIME_TYPES } from '../../common/constants/mime_types'; + +const buildFileKind = (owner: Owner): FileKind => { + return { + id: owner, + http: fileKindHttpTags(owner), + maxSizeBytes, + allowedMimeTypes: ALLOWED_MIME_TYPES, + }; +}; + +const fileKindHttpTags = (owner: Owner): FileKind['http'] => { + return { + create: buildTag(owner, HttpApiTagOperation.Create), + delete: buildTag(owner, HttpApiTagOperation.Delete), + download: buildTag(owner, HttpApiTagOperation.Read), + getById: buildTag(owner, HttpApiTagOperation.Read), + list: buildTag(owner, HttpApiTagOperation.Read), + }; +}; + +const access = 'access:'; + +const buildTag = (owner: Owner, operation: HttpApiTagOperation) => { + return { + tags: [`${access}${constructFilesHttpOperationTag(owner, operation)}`], + }; +}; + +const MAX_IMAGE_FILE_SIZE = 10 * 1024 * 1024; // 10 MiB + +const maxSizeBytes = (file: FileJSON): number => { + if (file.mimeType != null && IMAGE_MIME_TYPES.has(file.mimeType)) { + return MAX_IMAGE_FILE_SIZE; + } + + return MAX_FILE_SIZE; +}; + +/** + * The file kind definition for interacting with the file service for the backend + */ +const CASES_FILE_KINDS: Record = { + [APP_ID]: buildFileKind(APP_ID), + [SECURITY_SOLUTION_OWNER]: buildFileKind(SECURITY_SOLUTION_OWNER), + [OBSERVABILITY_OWNER]: buildFileKind(OBSERVABILITY_OWNER), +}; + +export const registerCaseFileKinds = (filesSetupPlugin: FilesSetup) => { + for (const fileKind of Object.values(CASES_FILE_KINDS)) { + filesSetupPlugin.registerFileKind(fileKind); + } +}; diff --git a/x-pack/plugins/cases/server/plugin.ts b/x-pack/plugins/cases/server/plugin.ts index a5a1d728311d4..8d2036921d84b 100644 --- a/x-pack/plugins/cases/server/plugin.ts +++ b/x-pack/plugins/cases/server/plugin.ts @@ -14,6 +14,7 @@ import type { CoreStart, } from '@kbn/core/server'; +import type { FilesSetup } from '@kbn/files-plugin/server'; import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/server'; import type { PluginSetupContract as ActionsPluginSetup, @@ -56,11 +57,13 @@ import { PersistableStateAttachmentTypeRegistry } from './attachment_framework/p import { ExternalReferenceAttachmentTypeRegistry } from './attachment_framework/external_reference_registry'; import { UserProfileService } from './services'; import { LICENSING_CASE_ASSIGNMENT_FEATURE } from './common/constants'; +import { registerCaseFileKinds } from './files'; export interface PluginsSetup { actions: ActionsPluginSetup; lens: LensServerPluginSetup; features: FeaturesPluginSetup; + files: FilesSetup; security: SecurityPluginSetup; licensing: LicensingPluginSetup; taskManager?: TaskManagerSetupContract; @@ -104,6 +107,8 @@ export class CasePlugin { )}] and plugins [${Object.keys(plugins)}]` ); + registerCaseFileKinds(plugins.files); + this.securityPluginSetup = plugins.security; this.lensEmbeddableFactory = plugins.lens.lensEmbeddableFactory; diff --git a/x-pack/plugins/cases/tsconfig.json b/x-pack/plugins/cases/tsconfig.json index a1737094134f2..5ba7e85918975 100644 --- a/x-pack/plugins/cases/tsconfig.json +++ b/x-pack/plugins/cases/tsconfig.json @@ -56,6 +56,8 @@ "@kbn/core-saved-objects-base-server-mocks", "@kbn/core-saved-objects-utils-server", "@kbn/shared-ux-router", + "@kbn/files-plugin", + "@kbn/shared-ux-file-types", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/observability/kibana.jsonc b/x-pack/plugins/observability/kibana.jsonc index d49e3ea870a62..4026d9f41088d 100644 --- a/x-pack/plugins/observability/kibana.jsonc +++ b/x-pack/plugins/observability/kibana.jsonc @@ -17,6 +17,7 @@ "data", "dataViews", "features", + "files", "inspector", "ruleRegistry", "triggersActionsUi", @@ -24,7 +25,7 @@ "unifiedSearch", "security", "guidedOnboarding", - "share" + "share", ], "optionalPlugins": [ "discover", diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts index e570fd7887952..4b2e2c722230b 100644 --- a/x-pack/plugins/observability/server/plugin.ts +++ b/x-pack/plugins/observability/server/plugin.ts @@ -13,10 +13,14 @@ import { DEFAULT_APP_CATEGORIES, Logger, } from '@kbn/core/server'; +import { hiddenTypes as filesSavedObjectTypes } from '@kbn/files-plugin/server/saved_objects'; import { PluginSetupContract } from '@kbn/alerting-plugin/server'; import { Dataset, RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; import { PluginSetupContract as FeaturesSetup } from '@kbn/features-plugin/server'; -import { createUICapabilities } from '@kbn/cases-plugin/common'; +import { + createUICapabilities as createCasesUICapabilities, + getApiTags as getCasesApiTags, +} from '@kbn/cases-plugin/common'; import { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; import { experimentalRuleFieldMap } from '@kbn/rule-registry-plugin/common/assets/field_maps/experimental_rule_field_map'; import { ECS_COMPONENT_TEMPLATE_NAME } from '@kbn/alerting-plugin/server'; @@ -64,7 +68,9 @@ export class ObservabilityPlugin implements Plugin { } public setup(core: CoreSetup, plugins: PluginSetup) { - const casesCapabilities = createUICapabilities(); + const casesCapabilities = createCasesUICapabilities(); + const casesApiTags = getCasesApiTags(observabilityFeatureId); + const config = this.initContext.config.get(); plugins.features.registerKibanaFeature({ @@ -79,7 +85,7 @@ export class ObservabilityPlugin implements Plugin { cases: [observabilityFeatureId], privileges: { all: { - api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], + api: casesApiTags.all, app: [casesFeatureId, 'kibana'], catalogue: [observabilityFeatureId], cases: { @@ -89,13 +95,13 @@ export class ObservabilityPlugin implements Plugin { push: [observabilityFeatureId], }, savedObject: { - all: [], - read: [], + all: [...filesSavedObjectTypes], + read: [...filesSavedObjectTypes], }, ui: casesCapabilities.all, }, read: { - api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], + api: casesApiTags.read, app: [casesFeatureId, 'kibana'], catalogue: [observabilityFeatureId], cases: { @@ -103,7 +109,7 @@ export class ObservabilityPlugin implements Plugin { }, savedObject: { all: [], - read: [], + read: [...filesSavedObjectTypes], }, ui: casesCapabilities.read, }, @@ -118,7 +124,7 @@ export class ObservabilityPlugin implements Plugin { groupType: 'independent', privileges: [ { - api: [], + api: casesApiTags.delete, id: 'cases_delete', name: i18n.translate( 'xpack.observability.featureRegistry.deleteSubFeatureDetails', diff --git a/x-pack/plugins/observability/tsconfig.json b/x-pack/plugins/observability/tsconfig.json index eb85b5fb25b26..eadf340054f52 100644 --- a/x-pack/plugins/observability/tsconfig.json +++ b/x-pack/plugins/observability/tsconfig.json @@ -71,6 +71,7 @@ "@kbn/shared-ux-router", "@kbn/alerts-ui-shared", "@kbn/core-application-browser", + "@kbn/files-plugin", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/security_solution/server/features.ts b/x-pack/plugins/security_solution/server/features.ts index 197b9fc926cc7..5f838f76d3bf5 100644 --- a/x-pack/plugins/security_solution/server/features.ts +++ b/x-pack/plugins/security_solution/server/features.ts @@ -7,10 +7,14 @@ import { i18n } from '@kbn/i18n'; +import { hiddenTypes as filesSavedObjectTypes } from '@kbn/files-plugin/server/saved_objects'; import type { KibanaFeatureConfig, SubFeatureConfig } from '@kbn/features-plugin/common'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { DATA_VIEW_SAVED_OBJECT_TYPE } from '@kbn/data-views-plugin/common'; -import { createUICapabilities } from '@kbn/cases-plugin/common'; +import { + createUICapabilities as createCasesUICapabilities, + getApiTags as getCasesApiTags, +} from '@kbn/cases-plugin/common'; import { EXCEPTION_LIST_NAMESPACE_AGNOSTIC } from '@kbn/securitysolution-list-constants'; import { APP_ID, CASES_FEATURE_ID, SERVER_APP_ID } from '../common/constants'; @@ -18,7 +22,8 @@ import { savedObjectTypes } from './saved_objects'; import type { ConfigType } from './config'; export const getCasesKibanaFeature = (): KibanaFeatureConfig => { - const casesCapabilities = createUICapabilities(); + const casesCapabilities = createCasesUICapabilities(); + const casesApiTags = getCasesApiTags(APP_ID); return { id: CASES_FEATURE_ID, @@ -32,7 +37,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { cases: [APP_ID], privileges: { all: { - api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], + api: casesApiTags.all, app: [CASES_FEATURE_ID, 'kibana'], catalogue: [APP_ID], cases: { @@ -42,13 +47,13 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { push: [APP_ID], }, savedObject: { - all: [], - read: [], + all: [...filesSavedObjectTypes], + read: [...filesSavedObjectTypes], }, ui: casesCapabilities.all, }, read: { - api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'], + api: casesApiTags.read, app: [CASES_FEATURE_ID, 'kibana'], catalogue: [APP_ID], cases: { @@ -56,7 +61,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { }, savedObject: { all: [], - read: [], + read: [...filesSavedObjectTypes], }, ui: casesCapabilities.read, }, @@ -71,7 +76,7 @@ export const getCasesKibanaFeature = (): KibanaFeatureConfig => { groupType: 'independent', privileges: [ { - api: [], + api: casesApiTags.delete, id: 'cases_delete', name: i18n.translate( 'xpack.securitySolution.featureRegistry.deleteSubFeatureDetails', diff --git a/x-pack/test/api_integration/apis/cases/common/users.ts b/x-pack/test/api_integration/apis/cases/common/users.ts index 29c14c35a5b76..f37b13b98f31a 100644 --- a/x-pack/test/api_integration/apis/cases/common/users.ts +++ b/x-pack/test/api_integration/apis/cases/common/users.ts @@ -4,12 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.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 { User } from '../../../../cases_api_integration/common/lib/authentication/types'; import { diff --git a/x-pack/test/api_integration/apis/cases/files.ts b/x-pack/test/api_integration/apis/cases/files.ts new file mode 100644 index 0000000000000..95ad400459f02 --- /dev/null +++ b/x-pack/test/api_integration/apis/cases/files.ts @@ -0,0 +1,365 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { APP_ID as CASES_APP_ID } from '@kbn/cases-plugin/common/constants'; +import { APP_ID as SECURITY_SOLUTION_APP_ID } from '@kbn/security-solution-plugin/common/constants'; +import { observabilityFeatureId as OBSERVABILITY_APP_ID } from '@kbn/observability-plugin/common'; +import { Owner } from '@kbn/cases-plugin/common/constants/types'; +import { BaseFilesClient } from '@kbn/shared-ux-file-types'; +import { User } from '../../../cases_api_integration/common/lib/authentication/types'; +import { + createFile, + deleteFiles, + uploadFile, + downloadFile, + createAndUploadFile, + listFiles, + getFileById, + deleteAllFiles, +} from '../../../cases_api_integration/common/lib/api'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { + casesAllUser, + casesNoDeleteUser, + casesReadUser, + obsCasesAllUser, + obsCasesNoDeleteUser, + obsCasesReadUser, + secAllCasesNoDeleteUser, + secAllUser, + secReadCasesReadUser, +} from './common/users'; + +interface TestScenario { + user: User; + owner: Owner; +} + +export default ({ getService }: FtrProviderContext): void => { + const supertestWithoutAuth = getService('supertestWithoutAuth'); + const supertest = getService('supertest'); + + describe('files', () => { + describe('failure requests', () => { + const createFileFailure = async (scenario: TestScenario) => { + await createFile({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + params: { + kind: scenario.owner, + name: 'testFile', + mimeType: 'image/png', + }, + expectedHttpCode: 403, + }); + }; + + const deleteFileFailure = async (scenario: TestScenario) => { + await deleteFiles({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + files: [{ kind: scenario.owner, id: 'abc' }], + expectedHttpCode: 403, + }); + }; + + const uploadFileFailure = async (scenario: TestScenario) => { + await uploadFile({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + data: 'abc', + kind: scenario.owner, + mimeType: 'image/png', + fileId: '123', + expectedHttpCode: 403, + }); + }; + + const listFilesFailure = async (scenario: TestScenario) => { + await listFiles({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + params: { + kind: scenario.owner, + }, + expectedHttpCode: 403, + }); + }; + + const downloadFileFailure = async (scenario: TestScenario) => { + await downloadFile({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + fileId: 'abc', + fileName: '123', + mimeType: 'image/png', + kind: scenario.owner, + expectedHttpCode: 401, + }); + }; + + const getFileByIdFailure = async (scenario: TestScenario) => { + await getFileById({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + id: 'abc', + kind: scenario.owner, + expectedHttpCode: 403, + }); + }; + + describe('user not authorized for a delete operation', () => { + const testScenarios: TestScenario[] = [ + { user: secAllCasesNoDeleteUser, owner: SECURITY_SOLUTION_APP_ID }, + { user: casesNoDeleteUser, owner: CASES_APP_ID }, + { user: obsCasesNoDeleteUser, owner: OBSERVABILITY_APP_ID }, + ]; + + for (const scenario of testScenarios) { + it('should fail to delete a file', async () => { + await deleteFileFailure(scenario); + }); + } + }); + + describe('user not authorized for write operations', () => { + const testScenarios: TestScenario[] = [ + { user: secReadCasesReadUser, owner: SECURITY_SOLUTION_APP_ID }, + { user: casesReadUser, owner: CASES_APP_ID }, + { user: obsCasesReadUser, owner: OBSERVABILITY_APP_ID }, + ]; + + for (const scenario of testScenarios) { + it('should fail to create a file', async () => { + await createFileFailure(scenario); + }); + + it('should fail to upload a file', async () => { + await uploadFileFailure(scenario); + }); + + it('should fail to delete a file', async () => { + await deleteFileFailure(scenario); + }); + } + }); + + describe('user not authorized for file kind', () => { + const testScenarios: TestScenario[] = [ + { user: secAllUser, owner: CASES_APP_ID }, + { + user: casesAllUser, + owner: SECURITY_SOLUTION_APP_ID, + }, + { + user: obsCasesAllUser, + owner: CASES_APP_ID, + }, + ]; + + for (const scenario of testScenarios) { + describe(`scenario user: ${scenario.user.username} owner: ${scenario.owner}`, () => { + it('should fail to create a file', async () => { + await createFileFailure(scenario); + }); + + it('should fail to upload a file', async () => { + await uploadFileFailure(scenario); + }); + + it('should fail to delete a file', async () => { + await deleteFileFailure(scenario); + }); + + it('should fail to list files', async () => { + await listFilesFailure(scenario); + }); + + it('should fail to download a file', async () => { + await downloadFileFailure(scenario); + }); + + it('should fail to get a file by its id', async () => { + await getFileByIdFailure(scenario); + }); + }); + } + }); + }); + + describe('successful requests', () => { + describe('users with read privileges', () => { + const testScenarios: TestScenario[] = [ + { user: secReadCasesReadUser, owner: SECURITY_SOLUTION_APP_ID }, + { user: casesReadUser, owner: CASES_APP_ID }, + { user: obsCasesReadUser, owner: OBSERVABILITY_APP_ID }, + ]; + + for (const scenario of testScenarios) { + describe(`scenario user: ${scenario.user.username} owner: ${scenario.owner}`, () => { + let createdFile: Awaited>; + + beforeEach(async () => { + const { create } = await createAndUploadFile({ + supertest, + data: 'abc', + createFileParams: { + name: 'testFile', + mimeType: 'image/png', + kind: scenario.owner, + }, + }); + createdFile = create; + }); + + afterEach(async () => { + await deleteAllFiles({ + supertest, + kind: scenario.owner, + }); + }); + + it('should list files', async () => { + const files = await listFiles({ + supertest: supertestWithoutAuth, + params: { kind: scenario.owner }, + auth: { user: scenario.user, space: null }, + }); + + expect(files.total).to.be(1); + expect(files.files[0].name).to.be(createdFile.file.name); + }); + + it('should get a file by its id', async () => { + const file = await getFileById({ + supertest: supertestWithoutAuth, + id: createdFile.file.id, + kind: scenario.owner, + auth: { user: scenario.user, space: null }, + }); + + expect(file.file.name).to.be(createdFile.file.name); + }); + }); + } + }); + + describe('users with all privileges', () => { + const testScenarios: TestScenario[] = [ + { user: secAllUser, owner: SECURITY_SOLUTION_APP_ID }, + { user: casesAllUser, owner: CASES_APP_ID }, + { user: obsCasesAllUser, owner: OBSERVABILITY_APP_ID }, + ]; + + for (const scenario of testScenarios) { + describe(`scenario user: ${scenario.user.username} owner: ${scenario.owner}`, () => { + it('should create and delete a file', async () => { + const createResult = await createFile({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + params: { + kind: scenario.owner, + name: 'testFile', + mimeType: 'image/png', + }, + }); + + await deleteFiles({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + files: [{ kind: scenario.owner, id: createResult.file.id }], + }); + }); + + describe('delete created file after test', () => { + afterEach(async () => { + await deleteAllFiles({ + supertest, + kind: scenario.owner, + }); + }); + + it('should list files', async () => { + const { create } = await createAndUploadFile({ + supertest: supertestWithoutAuth, + data: 'abc', + createFileParams: { + name: 'testFile', + mimeType: 'image/png', + kind: scenario.owner, + }, + auth: { user: scenario.user, space: null }, + }); + + const files = await listFiles({ + supertest: supertestWithoutAuth, + params: { kind: scenario.owner }, + auth: { user: scenario.user, space: null }, + }); + + expect(files.total).to.be(1); + expect(files.files[0].name).to.be(create.file.name); + }); + + it('should download a file', async () => { + const { create } = await createAndUploadFile({ + supertest: supertestWithoutAuth, + data: 'abc', + createFileParams: { + name: 'testFile', + mimeType: 'image/png', + kind: scenario.owner, + }, + auth: { user: scenario.user, space: null }, + }); + + const { body: buffer, header } = await downloadFile({ + supertest, + auth: { user: scenario.user, space: null }, + fileId: create.file.id, + kind: scenario.owner, + mimeType: 'image/png', + fileName: 'test.png', + }); + + expect(header['content-type']).to.eql('image/png'); + expect(header['content-disposition']).to.eql('attachment; filename="test.png"'); + expect(buffer.toString('utf8')).to.eql('abc'); + }); + + it('should upload a file', async () => { + const createResult = await createFile({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + params: { + kind: scenario.owner, + name: 'testFile', + mimeType: 'image/png', + }, + }); + + const uploadResult = await uploadFile({ + supertest: supertestWithoutAuth, + auth: { user: scenario.user, space: null }, + data: 'abc', + kind: scenario.owner, + mimeType: 'image/png', + fileId: createResult.file.id, + }); + + expect(uploadResult.ok).to.be(true); + expect(uploadResult.size).to.be(3); + }); + }); + }); + } + }); + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/cases/index.ts b/x-pack/test/api_integration/apis/cases/index.ts index f12e43b34d784..5bce534873f10 100644 --- a/x-pack/test/api_integration/apis/cases/index.ts +++ b/x-pack/test/api_integration/apis/cases/index.ts @@ -34,5 +34,6 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) { loadTestFile(require.resolve('./privileges')); loadTestFile(require.resolve('./suggest_user_profiles')); loadTestFile(require.resolve('./bulk_get_user_profiles')); + loadTestFile(require.resolve('./files')); }); } diff --git a/x-pack/test/cases_api_integration/common/lib/api/files.ts b/x-pack/test/cases_api_integration/common/lib/api/files.ts new file mode 100644 index 0000000000000..05450e9da2cc9 --- /dev/null +++ b/x-pack/test/cases_api_integration/common/lib/api/files.ts @@ -0,0 +1,226 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 from 'supertest'; +import { apiRoutes as fileApiRoutes } from '@kbn/files-plugin/public/files_client/files_client'; +import { BaseFilesClient } from '@kbn/shared-ux-file-types'; +import { superUser } from '../authentication/users'; +import { User } from '../authentication/types'; +import { getSpaceUrlPrefix } from './helpers'; + +export const downloadFile = async ({ + supertest, + fileId, + kind, + mimeType, + fileName, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + fileId: string; + kind: string; + mimeType: string; + fileName: string; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): ReturnType => { + const result = await supertest + .get( + `${getSpaceUrlPrefix(auth.space)}${fileApiRoutes.getDownloadRoute(kind, fileId, fileName)}` + ) + .set('accept', mimeType) + .buffer() + .expect(expectedHttpCode); + + return result; +}; + +export interface FileDescriptor { + kind: string; + id: string; +} + +export const deleteFiles = async ({ + supertest, + files, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + files: FileDescriptor[]; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}) => { + await Promise.all( + files.map(async (fileInfo) => { + return await supertest + .delete( + `${getSpaceUrlPrefix(auth.space)}${fileApiRoutes.getDeleteRoute( + fileInfo.kind, + fileInfo.id + )}` + ) + .set('kbn-xsrf', 'true') + .auth(auth.user.username, auth.user.password) + .send() + .expect(expectedHttpCode); + }) + ); +}; + +export const deleteAllFiles = async ({ + supertest, + kind, + auth = { user: superUser, space: null }, + expectedHttpCode = 200, +}: { + supertest: SuperTest.SuperTest; + kind: string; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}) => { + const files = await listFiles({ supertest, params: { kind }, auth, expectedHttpCode }); + + await deleteFiles({ + supertest, + files: files.files.map((fileInfo) => ({ kind, id: fileInfo.id })), + auth, + expectedHttpCode, + }); +}; + +export const getFileById = async ({ + supertest, + id, + kind, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + id: string; + kind: string; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): ReturnType => { + const { body } = await supertest + .get(`${getSpaceUrlPrefix(auth.space)}${fileApiRoutes.getByIdRoute(kind, id)}`) + .auth(auth.user.username, auth.user.password) + .expect(expectedHttpCode); + + return body; +}; + +export const listFiles = async ({ + supertest, + params, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + params: Parameters[0]; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): ReturnType => { + const { page, perPage, kind, ...rest } = params; + + const { body } = await supertest + .post(`${getSpaceUrlPrefix(auth.space)}${fileApiRoutes.getListRoute(kind)}`) + .auth(auth.user.username, auth.user.password) + .set('kbn-xsrf', 'true') + .query({ page, perPage }) + .send(rest) + .expect(expectedHttpCode); + + return body; +}; + +type CreateFileSchema = Omit[0], 'mimeType'> & { + mimeType: string; +}; + +export const createFile = async ({ + supertest, + params, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + params: CreateFileSchema; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): ReturnType => { + const { kind, ...rest } = params; + const { body } = await supertest + .post(`${getSpaceUrlPrefix(auth.space)}${fileApiRoutes.getCreateFileRoute(kind)}`) + .auth(auth.user.username, auth.user.password) + .set('kbn-xsrf', 'true') + .send(rest) + .expect(expectedHttpCode); + + return body; +}; + +export const uploadFile = async ({ + supertest, + data, + kind, + fileId, + mimeType, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + data: string | object; + kind: string; + fileId: string; + mimeType: string; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}): ReturnType => { + const { body } = await supertest + .put(`${getSpaceUrlPrefix(auth.space)}${fileApiRoutes.getUploadRoute(kind, fileId)}`) + .auth(auth.user.username, auth.user.password) + .set('kbn-xsrf', 'true') + .set('Content-Type', mimeType) + .send(data) + .expect(expectedHttpCode); + + return body; +}; + +export const createAndUploadFile = async ({ + supertest, + data, + createFileParams, + expectedHttpCode = 200, + auth = { user: superUser, space: null }, +}: { + supertest: SuperTest.SuperTest; + data: string | object; + createFileParams: CreateFileSchema; + expectedHttpCode?: number; + auth?: { user: User; space: string | null }; +}) => { + const createFileResult = await createFile({ + supertest, + params: createFileParams, + expectedHttpCode, + auth, + }); + + const uploadFileResult = await uploadFile({ + supertest, + data, + fileId: createFileResult.file.id, + mimeType: createFileParams.mimeType, + kind: createFileParams.kind, + auth, + }); + + return { create: createFileResult, upload: uploadFileResult }; +}; diff --git a/x-pack/test/cases_api_integration/common/lib/api/index.ts b/x-pack/test/cases_api_integration/common/lib/api/index.ts index c15c19232edf6..3bf0c470b9ba2 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/index.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/index.ts @@ -54,6 +54,7 @@ export * from './user_actions'; export * from './user_profiles'; export * from './omit'; export * from './configuration'; +export * from './files'; export { getSpaceUrlPrefix } from './helpers'; function toArray(input: T | T[]): T[] { diff --git a/x-pack/test/cases_api_integration/common/lib/authentication/index.ts b/x-pack/test/cases_api_integration/common/lib/authentication/index.ts index d425eae5a373c..195549561571b 100644 --- a/x-pack/test/cases_api_integration/common/lib/authentication/index.ts +++ b/x-pack/test/cases_api_integration/common/lib/authentication/index.ts @@ -20,9 +20,8 @@ export const getUserInfo = (user: User): UserInfo => ({ export const createSpaces = async (getService: CommonFtrProviderContext['getService']) => { const spacesService = getService('spaces'); - for (const space of spaces) { - await spacesService.create(space); - } + + await Promise.all(spaces.map((space) => spacesService.create(space))); }; /** @@ -51,23 +50,16 @@ export const createUsersAndRoles = async ( }); }; - for (const role of rolesToCreate) { - await createRole(role); - } - - for (const user of usersToCreate) { - await createUser(user); - } + await Promise.all(rolesToCreate.map((role) => createRole(role))); + await Promise.all(usersToCreate.map((user) => createUser(user))); }; export const deleteSpaces = async (getService: CommonFtrProviderContext['getService']) => { const spacesService = getService('spaces'); - for (const space of spaces) { - try { - await spacesService.delete(space.id); - } catch (error) { - // ignore errors because if a migration is run it will delete the .kibana index which remove the spaces and users - } + try { + await Promise.allSettled(spaces.map((space) => spacesService.delete(space.id))); + } catch (error) { + // ignore errors because if a migration is run it will delete the .kibana index which remove the spaces and users } }; @@ -78,20 +70,16 @@ export const deleteUsersAndRoles = async ( ) => { const security = getService('security'); - for (const user of usersToDelete) { - try { - await security.user.delete(user.username); - } catch (error) { - // ignore errors because if a migration is run it will delete the .kibana index which remove the spaces and users - } + try { + await Promise.allSettled(usersToDelete.map((user) => security.user.delete(user.username))); + } catch (error) { + // ignore errors because if a migration is run it will delete the .kibana index which remove the spaces and users } - for (const role of rolesToDelete) { - try { - await security.role.delete(role.name); - } catch (error) { - // ignore errors because if a migration is run it will delete the .kibana index which remove the spaces and users - } + try { + await Promise.allSettled(rolesToDelete.map((role) => security.role.delete(role.name))); + } catch (error) { + // ignore errors because if a migration is run it will delete the .kibana index which remove the spaces and users } }; diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 58a8f285bc9ef..bf4fe75140b6f 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -117,6 +117,8 @@ "@kbn/security-api-integration-helpers", "@kbn/alerts-as-data-utils", "@kbn/discover-plugin", + "@kbn/files-plugin", + "@kbn/shared-ux-file-types", "@kbn/securitysolution-io-ts-alerting-types", ] } From 47ac4c7a4bc85f74215807981b89b3eb9354b2e6 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 2 Mar 2023 12:44:36 +0000 Subject: [PATCH 112/131] [ML] Fixing lens integration for ad hoc data views (#152487) Fixes https://github.com/elastic/kibana/issues/152384 The `isCompatibleVisualizationType` function will now return `false` no layers contain data views. Also improves the incompatible reason to be `Cannot find a date field.` if the layer dimension does not contain a `operation` object, rather than `Cannot read properties of undefined (reading 'dataType')` Also removes an unused aria label which causes a browser console error. --- .../ml/public/application/jobs/new_job/job_from_lens/utils.ts | 2 +- .../jobs/new_job/job_from_lens/visualization_extractor.ts | 4 +++- .../public/embeddables/job_creation/common/create_flyout.tsx | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts index ed0c4639c47c2..aab22b84f8fc6 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts @@ -186,7 +186,7 @@ export async function getVisTypeFactory(lens: LensPublicStart) { export async function isCompatibleVisualizationType(chartInfo: ChartInfo) { return ( chartInfo.visualizationType === COMPATIBLE_VISUALIZATION && - chartInfo.layers.some((l) => l.layerType === layerTypes.DATA) + chartInfo.layers.some((l) => l.layerType === layerTypes.DATA && l.dataView !== undefined) ); } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts index 1128bd5918814..c7f5a02e75d5b 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts @@ -55,7 +55,9 @@ export class VisualizationExtractor { ); } - const timeField = layer.dimensions.find(({ operation }) => operation.dataType === 'date'); + const timeField = layer.dimensions.find( + (dimension) => dimension.operation?.dataType === 'date' + ); if (timeField === undefined || !timeField.operation.fields?.length) { throw Error( i18n.translate('xpack.ml.newJob.fromLens.createJob.error.noDateField', { diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/common/create_flyout.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/common/create_flyout.tsx index c9163b71b057c..1bbf8c18cf25c 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/common/create_flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/common/create_flyout.tsx @@ -70,7 +70,6 @@ export function createFlyout( { 'data-test-subj': 'mlFlyoutLayerSelector', ownFocus: true, - closeButtonAriaLabel: 'jobSelectorFlyout', onClose: onFlyoutClose, // @ts-expect-error should take any number/string compatible with the CSS width attribute size: '35vw', From bdb4f872751db78495b7f887db860cec1573b3ee Mon Sep 17 00:00:00 2001 From: Alexander Wert Date: Thu, 2 Mar 2023 13:47:14 +0100 Subject: [PATCH 113/131] Clean up and align central config for APM Agents (#150414) Clean up and align central config for APM Agents --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../runtime_types/log_ecs_reformatting_rt.ts | 15 ++ .../__snapshots__/index.test.ts.snap | 80 ++++++++++ .../setting_definitions/general_settings.ts | 140 +++++++++++++++++- .../setting_definitions/java_settings.ts | 117 +++++++++++++++ 4 files changed, 344 insertions(+), 8 deletions(-) create mode 100644 x-pack/plugins/apm/common/agent_configuration/runtime_types/log_ecs_reformatting_rt.ts diff --git a/x-pack/plugins/apm/common/agent_configuration/runtime_types/log_ecs_reformatting_rt.ts b/x-pack/plugins/apm/common/agent_configuration/runtime_types/log_ecs_reformatting_rt.ts new file mode 100644 index 0000000000000..cd8777e7ce1d0 --- /dev/null +++ b/x-pack/plugins/apm/common/agent_configuration/runtime_types/log_ecs_reformatting_rt.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as t from 'io-ts'; + +export const logEcsReformattingRt = t.union([ + t.literal('off'), + t.literal('shade'), + t.literal('replace'), + t.literal('override'), +]); diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap index a4bc508856b45..c38f4382e7f40 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/__snapshots__/index.test.ts.snap @@ -24,6 +24,11 @@ Array [ ], "validationName": "durationRt", }, + Object { + "key": "application_packages", + "type": "text", + "validationName": "string", + }, Object { "key": "capture_body", "options": Array [ @@ -72,6 +77,26 @@ Array [ "type": "boolean", "validationName": "(\\"true\\" | \\"false\\")", }, + Object { + "key": "disable_instrumentations", + "type": "text", + "validationName": "string", + }, + Object { + "key": "disable_outgoing_tracecontext_headers", + "type": "boolean", + "validationName": "(\\"true\\" | \\"false\\")", + }, + Object { + "key": "enable_experimental_instrumentations", + "type": "boolean", + "validationName": "(\\"true\\" | \\"false\\")", + }, + Object { + "key": "enable_instrumentations", + "type": "text", + "validationName": "string", + }, Object { "key": "enable_log_correlation", "type": "boolean", @@ -98,6 +123,29 @@ Array [ "type": "text", "validationName": "string", }, + Object { + "key": "log_ecs_reformatting", + "options": Array [ + Object { + "text": "off", + "value": "off", + }, + Object { + "text": "shade", + "value": "shade", + }, + Object { + "text": "replace", + "value": "replace", + }, + Object { + "text": "override", + "value": "override", + }, + ], + "type": "select", + "validationName": "(\\"off\\" | \\"shade\\" | \\"replace\\" | \\"override\\")", + }, Object { "key": "log_level", "options": Array [ @@ -133,6 +181,16 @@ Array [ "type": "select", "validationName": "(\\"trace\\" | \\"debug\\" | \\"info\\" | \\"warning\\" | \\"error\\" | \\"critical\\" | \\"off\\")", }, + Object { + "key": "log_sending", + "type": "boolean", + "validationName": "(\\"true\\" | \\"false\\")", + }, + Object { + "key": "mongodb_capture_statement_commands", + "type": "boolean", + "validationName": "(\\"true\\" | \\"false\\")", + }, Object { "key": "profiling_inferred_spans_enabled", "type": "boolean", @@ -230,6 +288,28 @@ Array [ ], "validationName": "durationRt", }, + Object { + "key": "span_min_duration", + "min": "0ms", + "type": "duration", + "units": Array [ + "ms", + "s", + "m", + ], + "validationName": "durationRt", + }, + Object { + "key": "span_stack_trace_min_duration", + "min": "-1ms", + "type": "duration", + "units": Array [ + "ms", + "s", + "m", + ], + "validationName": "durationRt", + }, Object { "key": "stack_trace_limit", "max": undefined, diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts index 4e0f37fc76f3b..4dc7a6bb35da4 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/general_settings.ts @@ -8,6 +8,7 @@ import { i18n } from '@kbn/i18n'; import { captureBodyRt } from '../runtime_types/capture_body_rt'; import { logLevelRt } from '../runtime_types/log_level_rt'; +import { logEcsReformattingRt } from '../runtime_types/log_ecs_reformatting_rt'; import { traceContinuationStrategyRt } from '../runtime_types/trace_continuation_strategy_rt'; import { RawSettingDefinition } from './types'; @@ -93,7 +94,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'The defaults end with a wildcard so that content types like `text/plain; charset=utf-8` are captured as well.', } ), - includeAgents: ['java'], + includeAgents: ['java', 'dotnet'], }, // Capture headers @@ -135,6 +136,53 @@ export const generalSettings: RawSettingDefinition[] = [ includeAgents: ['java'], }, + { + key: 'disable_instrumentations', + type: 'text', + defaultValue: '', + label: i18n.translate( + 'xpack.apm.agentConfig.disableInstrumentations.label', + { + defaultMessage: 'Disable instrumentations', + } + ), + description: i18n.translate( + 'xpack.apm.agentConfig.disableInstrumentations.description', + { + defaultMessage: + 'Comma-separated list of modules to disable instrumentation for.\n' + + 'When instrumentation is disabled for a module, no spans will be collected for that module.\n' + + '\n' + + 'The up-to-date list of modules for which instrumentation can be disabled is language specific ' + + 'and can be found under the following links: ' + + '[Java](https://www.elastic.co/guide/en/apm/agent/java/current/config-core.html#config-disable-instrumentations)', + } + ), + includeAgents: ['java'], + }, + + { + key: 'disable_outgoing_tracecontext_headers', + type: 'boolean', + defaultValue: 'true', + label: i18n.translate( + 'xpack.apm.agentConfig.disableOutgoingTracecontextHeaders.label', + { + defaultMessage: 'Disable outgoing tracecontext headers', + } + ), + description: i18n.translate( + 'xpack.apm.agentConfig.disableOutgoingTracecontextHeaders.description', + { + defaultMessage: + 'Use this option to disable `tracecontext` headers injection to any outgoing communication.\n' + + '\n' + + 'WARNING: Disabling `tracecontext` headers injection means that distributed tracing will not work on downstream services.', + } + ), + includeAgents: ['java'], + }, + { key: 'exit_span_min_duration', type: 'duration', @@ -152,7 +200,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'NOTE: If a span propagates distributed tracing ids, it will not be ignored, even if it is shorter than the configured threshold. This is to ensure that no broken traces are recorded.', } ), - includeAgents: ['java'], + includeAgents: ['java', 'dotnet', 'nodejs', 'python'], }, { @@ -172,6 +220,32 @@ export const generalSettings: RawSettingDefinition[] = [ 'When set, sends-to and receives-from the specified queues/topic will be ignored.', } ), + includeAgents: ['java', 'dotnet', 'nodejs'], + }, + + { + key: 'log_ecs_reformatting', + validation: logEcsReformattingRt, + type: 'select', + defaultValue: 'off', + label: i18n.translate('xpack.apm.agentConfig.logEcsReformatting.label', { + defaultMessage: 'Log ECS reformatting', + }), + description: i18n.translate( + 'xpack.apm.agentConfig.logEcsReformatting.description', + { + defaultMessage: + 'Specifying whether and how the agent should automatically reformat application logs into ' + + '[ECS-compatible JSON](https://www.elastic.co/guide/en/ecs-logging/overview/master/intro.html), ' + + 'suitable for ingestion into Elasticsearch for further Log analysis.', + } + ), + options: [ + { text: 'off', value: 'off' }, + { text: 'shade', value: 'shade' }, + { text: 'replace', value: 'replace' }, + { text: 'override', value: 'override' }, + ], includeAgents: ['java'], }, @@ -199,6 +273,30 @@ export const generalSettings: RawSettingDefinition[] = [ includeAgents: ['dotnet', 'ruby', 'java', 'python', 'nodejs', 'go', 'php'], }, + { + key: 'mongodb_capture_statement_commands', + type: 'boolean', + defaultValue: 'false', + label: i18n.translate( + 'xpack.apm.agentConfig.mongodbCaptureStatementCommands.label', + { + defaultMessage: 'MongoDB capture statement commands', + } + ), + description: i18n.translate( + 'xpack.apm.agentConfig.mongodbCaptureStatementCommands.description', + { + defaultMessage: + 'MongoDB command names for which the command document will be captured, limited to common read-only operations by default. ' + + 'Set to `""` (empty) to disable capture, and `*` to capture all (which is discouraged as it may lead to sensitive information capture).\n' + + '\n' + + 'This option supports the wildcard `*`, which matches zero or more characters. Examples: `/foo/*/bar/*/baz*`, `*foo*`. ' + + 'Matching is case insensitive by default. Prepending an element with `(?-i)` makes the matching case sensitive.', + } + ), + includeAgents: ['java'], + }, + // Recording { key: 'recording', @@ -250,7 +348,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'Span compression reduces the collection, processing, and storage overhead, and removes clutter from the UI. The tradeoff is that some information such as DB statements of all the compressed spans will not be collected.', } ), - includeAgents: ['java'], + includeAgents: ['java', 'dotnet', 'python'], }, { @@ -271,7 +369,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'Consecutive spans that are exact match and that are under this threshold will be compressed into a single composite span. This option does not apply to composite spans. This reduces the collection, processing, and storage overhead, and removes clutter from the UI. The tradeoff is that the DB statements of all the compressed spans will not be collected.', } ), - includeAgents: ['java'], + includeAgents: ['java', 'dotnet', 'python'], }, { key: 'span_compression_same_kind_max_duration', @@ -291,7 +389,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'Consecutive spans to the same destination that are under this threshold will be compressed into a single composite span. This option does not apply to composite spans. This reduces the collection, processing, and storage overhead, and removes clutter from the UI. The tradeoff is that the DB statements of all the compressed spans will not be collected.', } ), - includeAgents: ['java'], + includeAgents: ['java', 'dotnet', 'python'], }, // SPAN_FRAMES_MIN_DURATION @@ -307,12 +405,38 @@ export const generalSettings: RawSettingDefinition[] = [ 'xpack.apm.agentConfig.spanFramesMinDuration.description', { defaultMessage: - 'In its default settings, the APM agent will collect a stack trace with every recorded span.\nWhile this is very helpful to find the exact place in your code that causes the span, collecting this stack trace does have some overhead. \nWhen setting this option to a negative value, like `-1ms`, stack traces will be collected for all spans. Setting it to a positive value, e.g. `5ms`, will limit stack trace collection to spans with durations equal to or longer than the given value, e.g. 5 milliseconds.\n\nTo disable stack trace collection for spans completely, set the value to `0ms`.', + '(Deprecated, use `span_stack_trace_min_duration` instead!) In its default settings, the APM agent will collect a stack trace with every recorded span.\nWhile this is very helpful to find the exact place in your code that causes the span, collecting this stack trace does have some overhead. \nWhen setting this option to a negative value, like `-1ms`, stack traces will be collected for all spans. Setting it to a positive value, e.g. `5ms`, will limit stack trace collection to spans with durations equal to or longer than the given value, e.g. 5 milliseconds.\n\nTo disable stack trace collection for spans completely, set the value to `0ms`.', } ), excludeAgents: ['js-base', 'rum-js', 'nodejs', 'php'], }, + { + key: 'span_stack_trace_min_duration', + type: 'duration', + min: '-1ms', + defaultValue: '5ms', + label: i18n.translate( + 'xpack.apm.agentConfig.spanStackTraceMinDuration.label', + { + defaultMessage: 'Span stack trace minimum duration', + } + ), + description: i18n.translate( + 'xpack.apm.agentConfig.spanStackTraceMinDuration.description', + { + defaultMessage: + 'While this is very helpful to find the exact place in your code that causes the span, ' + + 'collecting this stack trace does have some overhead. When setting this option to the value `0ms`, ' + + 'stack traces will be collected for all spans. Setting it to a positive value, e.g. `5ms`, will limit ' + + 'stack trace collection to spans with durations equal to or longer than the given value, e.g. 5 milliseconds.\n' + + '\n' + + 'To disable stack trace collection for spans completely, set the value to `-1ms`.', + } + ), + includeAgents: ['java', 'dotnet', 'nodejs', 'python'], + }, + // STACK_TRACE_LIMIT { key: 'stack_trace_limit', @@ -328,7 +452,7 @@ export const generalSettings: RawSettingDefinition[] = [ 'Setting it to 0 will disable stack trace collection. Any positive integer value will be used as the maximum number of frames to collect. Setting it -1 means that all frames will be collected.', } ), - includeAgents: ['java', 'dotnet', 'go'], + includeAgents: ['java', 'dotnet', 'go', 'python'], }, { @@ -366,7 +490,7 @@ export const generalSettings: RawSettingDefinition[] = [ { text: 'restart', value: 'restart' }, { text: 'restart_external', value: 'restart_external' }, ], - includeAgents: ['java'], + includeAgents: ['java', 'nodejs', 'python'], }, // Transaction max spans diff --git a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts index 694eef7885b31..45abfb43edb00 100644 --- a/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts +++ b/x-pack/plugins/apm/common/agent_configuration/setting_definitions/java_settings.ts @@ -9,6 +9,28 @@ import { i18n } from '@kbn/i18n'; import { RawSettingDefinition } from './types'; export const javaSettings: RawSettingDefinition[] = [ + { + key: 'application_packages', + type: 'text', + defaultValue: '', + label: i18n.translate('xpack.apm.agentConfig.applicationPackages.label', { + defaultMessage: 'Application packages', + }), + description: i18n.translate( + 'xpack.apm.agentConfig.applicationPackages.description', + { + defaultMessage: + 'Used to determine whether a stack trace frame is an in-app frame or a library frame. ' + + 'This allows the APM app to collapse the stack frames of library code, and highlight the stack frames that originate from your application. ' + + 'Multiple root packages can be set as a comma-separated list; there’s no need to configure sub-packages. ' + + 'Because this setting helps determine which classes to scan on startup, setting this option can also improve startup time.\n' + + '\n' + + 'You must set this option in order to use the API annotations `@CaptureTransaction` and `@CaptureSpan`.', + } + ), + includeAgents: ['java'], + }, + // ENABLE_LOG_CORRELATION { key: 'enable_log_correlation', @@ -47,6 +69,101 @@ export const javaSettings: RawSettingDefinition[] = [ ), includeAgents: ['java'], }, + + { + key: 'enable_experimental_instrumentations', + type: 'boolean', + defaultValue: 'false', + label: i18n.translate( + 'xpack.apm.agentConfig.enableExperimentalInstrumentations.label', + { + defaultMessage: 'Enable experimental instrumentations', + } + ), + description: i18n.translate( + 'xpack.apm.agentConfig.enableExperimentalInstrumentations.description', + { + defaultMessage: + 'Whether to apply experimental instrumentations.\n' + + '\n' + + 'NOTE: Changing this value at runtime can slow down the application temporarily. ' + + 'Setting to true will enable instrumentations in the experimental group.', + } + ), + includeAgents: ['java'], + }, + + { + key: 'enable_instrumentations', + type: 'text', + defaultValue: '', + label: i18n.translate( + 'xpack.apm.agentConfig.enableInstrumentations.label', + { + defaultMessage: 'Disable instrumentations', + } + ), + description: i18n.translate( + 'xpack.apm.agentConfig.enableInstrumentations.description', + { + defaultMessage: + 'A list of instrumentations which should be selectively enabled. ' + + 'Valid options are listed in the ' + + '[Java APM Agent documentation](https://www.elastic.co/guide/en/apm/agent/java/current/config-core.html#config-disable-instrumentations).\n' + + '\n' + + 'When set to non-empty value, only listed instrumentations will be enabled ' + + 'if they are not disabled through `disable_instrumentations`or `enable_experimental_instrumentations`.\n' + + 'When not set or empty (default), all instrumentations enabled by default will be enabled ' + + 'unless they are disabled through `disable_instrumentations` or `enable_experimental_instrumentations`.', + } + ), + includeAgents: ['java'], + }, + + { + key: 'log_sending', + type: 'boolean', + defaultValue: 'false', + label: i18n.translate('xpack.apm.agentConfig.logSending.label', { + defaultMessage: 'Log sending (experimental)', + }), + description: i18n.translate( + 'xpack.apm.agentConfig.logSending.description', + { + defaultMessage: + 'Experimental, requires latest version of the Java agent.\n' + + '\n' + + 'If set to `true`,\n' + + 'agent will send logs directly to APM server.', + } + ), + includeAgents: ['java'], + }, + + { + key: 'span_min_duration', + type: 'duration', + defaultValue: '0ms', + min: '0ms', + label: i18n.translate('xpack.apm.agentConfig.spanMinDuration.label', { + defaultMessage: 'Span minimum duration', + }), + description: i18n.translate( + 'xpack.apm.agentConfig.spanMinDuration.description', + { + defaultMessage: + 'Sets the minimum duration of spans. Spans that execute faster than this threshold are attempted to be discarded.\n' + + '\n' + + 'The attempt fails if they lead up to a span that can’t be discarded. Spans that propagate the trace context to ' + + 'downstream services, such as outgoing HTTP requests, can’t be discarded. Additionally, spans that lead to an error ' + + 'or that may be a parent of an async operation can’t be discarded.\n' + + '\n' + + 'However, external calls that don’t propagate context, such as calls to a database, can be discarded using this threshold.', + } + ), + includeAgents: ['java'], + }, + { key: 'stress_monitor_gc_stress_threshold', label: i18n.translate( From e772fa18c104a2f2e5317a40010ebc6dd3c852d9 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 2 Mar 2023 13:04:51 +0000 Subject: [PATCH 114/131] [Logs UI] Support inline Log Views in routes (#151760) ## Summary Closes https://github.com/elastic/kibana/issues/151489 This is the server side portion of support for transient / inline Log Views. Alerting and ML based functionality is scoped to the persisted type only, as we won't be supporting inline Log Views in those contexts. In terms of UI, changes have been made as close to the edge / boundary to the server (e.g. where we actually make network requests) as possible. This is because the bulk of the UI changes will come in https://github.com/elastic/kibana/issues/142840. ## Testing This is predominantly a type-driven refactoring (the best kind), so we should be relatively safe here (especially since inline views aren't in the UI yet). But, a quick test of each page and a high level functional test would still be good. --- .../alerting/logs/log_threshold/types.ts | 4 +-- .../http_api/log_alerts/chart_preview_data.ts | 3 +- .../results/log_entry_anomalies.ts | 5 ++-- .../results/log_entry_anomalies_datasets.ts | 5 ++-- .../results/log_entry_categories.ts | 5 ++-- .../results/log_entry_category_datasets.ts | 6 ++-- .../results/log_entry_category_examples.ts | 5 ++-- .../results/log_entry_examples.ts | 5 ++-- .../common/http_api/log_entries/highlights.ts | 3 +- .../common/http_api/log_entries/summary.ts | 3 +- .../plugins/infra/common/log_views/types.ts | 12 +++++++- .../log_entries/log_entries.ts | 4 +-- .../log_entries/log_entry.ts | 3 +- .../components/expression_editor/editor.tsx | 18 ++++++------ .../hooks/use_chart_preview_data.tsx | 2 +- .../infra/public/containers/logs/log_entry.ts | 5 +++- .../log_highlights/log_entry_highlights.tsx | 2 +- .../log_highlights/log_summary_highlights.ts | 2 +- .../log_stream/use_fetch_log_entries_after.ts | 2 +- .../use_fetch_log_entries_before.ts | 2 +- .../logs/log_summary/log_summary.test.tsx | 4 +-- .../logs/log_summary/log_summary.tsx | 2 +- .../get_log_entry_category_datasets.ts | 2 +- .../get_log_entry_category_examples.ts | 2 +- .../get_top_log_entry_categories.ts | 2 +- .../service_calls/get_log_entry_anomalies.ts | 2 +- .../get_log_entry_anomalies_datasets.ts | 2 +- .../service_calls/get_log_entry_examples.ts | 2 +- .../inventory_metric_threshold_executor.ts | 5 +++- .../log_threshold/log_threshold_executor.ts | 2 +- .../log_entries_domain/log_entries_domain.ts | 19 +++++++------ .../lib/log_analysis/log_entry_anomalies.ts | 28 +++++++++---------- .../log_entry_categories_analysis.ts | 14 +++++----- .../log_analysis/log_entry_rate_analysis.ts | 4 +-- .../routes/log_alerts/chart_preview_data.ts | 4 +-- .../results/log_entry_anomalies.ts | 4 +-- .../results/log_entry_anomalies_datasets.ts | 4 +-- .../results/log_entry_categories.ts | 4 +-- .../results/log_entry_category_datasets.ts | 4 +-- .../results/log_entry_category_examples.ts | 6 ++-- .../results/log_entry_examples.ts | 6 ++-- .../server/routes/log_entries/highlights.ts | 6 ++-- .../server/routes/log_entries/summary.ts | 4 +-- .../routes/log_entries/summary_highlights.ts | 4 +-- .../infra/server/routes/snapshot/index.ts | 5 +++- .../log_entries_search_strategy.test.ts | 6 ++-- .../log_entries_search_strategy.ts | 2 +- .../log_entry_search_strategy.test.ts | 15 ++++++++-- .../log_entries/log_entry_search_strategy.ts | 2 +- .../log_views/log_views_client.mock.ts | 5 +++- .../services/log_views/log_views_client.ts | 8 ++++-- .../infra/server/services/log_views/types.ts | 3 +- .../apis/metrics_ui/log_entry_highlights.ts | 8 +++--- .../apis/metrics_ui/log_summary.ts | 2 +- 54 files changed, 167 insertions(+), 121 deletions(-) diff --git a/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts b/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts index d697770d24a04..c0ad0af7e69fe 100644 --- a/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts +++ b/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import * as rt from 'io-ts'; -import { logViewReferenceRT } from '../../../log_views'; +import { persistedLogViewReferenceRT } from '../../../log_views'; import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; export const LOG_DOCUMENT_COUNT_RULE_TYPE_ID = 'logs.alert.document.count'; @@ -181,7 +181,7 @@ const RequiredRuleParamsRT = rt.type({ count: ThresholdRT, timeUnit: timeUnitRT, timeSize: timeSizeRT, - logView: logViewReferenceRT, // In future, this should be a union of logViewReferenceRT and inlineLogViewRT + logView: persistedLogViewReferenceRT, // Alerts are only compatible with persisted Log Views }); const partialRequiredRuleParamsRT = rt.partial(RequiredRuleParamsRT.props); diff --git a/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts b/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts index 5f488dd532285..15f0df5222e7d 100644 --- a/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts +++ b/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts @@ -13,6 +13,7 @@ import { timeSizeRT, groupByRT, } from '../../alerting/logs/log_threshold/types'; +import { persistedLogViewReferenceRT } from '../../log_views'; export const LOG_ALERTS_CHART_PREVIEW_DATA_PATH = '/api/infra/log_alerts/chart_preview_data'; @@ -81,7 +82,7 @@ export type GetLogAlertsChartPreviewDataAlertParamsSubset = rt.TypeOf< export const getLogAlertsChartPreviewDataRequestPayloadRT = rt.type({ data: rt.type({ - sourceId: rt.string, + logView: persistedLogViewReferenceRT, alertParams: getLogAlertsChartPreviewDataAlertParamsSubsetRT, buckets: rt.number, }), diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts index b48e5dc3c6d81..b8b39197e5acf 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies.ts @@ -7,6 +7,7 @@ import * as rt from 'io-ts'; +import { persistedLogViewReferenceRT } from '../../../log_views'; import { timeRangeRT, routeTimingMetadataRT } from '../../shared'; import { logEntryAnomalyRT, @@ -51,8 +52,8 @@ export type GetLogEntryAnomaliesSuccessResponsePayload = rt.TypeOf< export const getLogEntryAnomaliesRequestPayloadRT = rt.type({ data: rt.intersection([ rt.type({ - // the ID of the source configuration - sourceId: rt.string, + // log view + logView: persistedLogViewReferenceRT, // the time range to fetch the log entry anomalies from timeRange: timeRangeRT, }), diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies_datasets.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies_datasets.ts index 397e0ac936ece..94d1b25e4d9c2 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies_datasets.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_anomalies_datasets.ts @@ -6,6 +6,7 @@ */ import * as rt from 'io-ts'; +import { persistedLogViewReferenceRT } from '../../../log_views'; import { badRequestErrorRT, @@ -23,8 +24,8 @@ export const LOG_ANALYSIS_GET_LOG_ENTRY_ANOMALIES_DATASETS_PATH = export const getLogEntryAnomaliesDatasetsRequestPayloadRT = rt.type({ data: rt.type({ - // the id of the source configuration - sourceId: rt.string, + // log view + logView: persistedLogViewReferenceRT, // the time range to fetch the anomalies datasets from timeRange: timeRangeRT, }), diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts index 308ee41f39d17..85829b7ebb00c 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_categories.ts @@ -7,6 +7,7 @@ import * as rt from 'io-ts'; +import { persistedLogViewReferenceRT } from '../../../log_views'; import { badRequestErrorRT, forbiddenErrorRT, @@ -38,8 +39,8 @@ export const getLogEntryCategoriesRequestPayloadRT = rt.type({ rt.type({ // the number of categories to fetch categoryCount: rt.number, - // the id of the source configuration - sourceId: rt.string, + // log view + logView: persistedLogViewReferenceRT, // the time range to fetch the categories from timeRange: timeRangeRT, // a list of histograms to create diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_datasets.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_datasets.ts index afeda0c1fff29..cb3ad4363f243 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_datasets.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_datasets.ts @@ -13,7 +13,7 @@ import { timeRangeRT, routeTimingMetadataRT, } from '../../shared'; - +import { persistedLogViewReferenceRT } from '../../../log_views'; export const LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORY_DATASETS_PATH = '/api/infra/log_analysis/results/log_entry_category_datasets'; @@ -23,8 +23,8 @@ export const LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORY_DATASETS_PATH = export const getLogEntryCategoryDatasetsRequestPayloadRT = rt.type({ data: rt.type({ - // the id of the source configuration - sourceId: rt.string, + // log view + logView: persistedLogViewReferenceRT, // the time range to fetch the category datasets from timeRange: timeRangeRT, }), diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts index 256dc4fb97bfd..c6c349830e833 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_category_examples.ts @@ -7,6 +7,7 @@ import * as rt from 'io-ts'; +import { persistedLogViewReferenceRT } from '../../../log_views'; import { badRequestErrorRT, forbiddenErrorRT, @@ -28,8 +29,8 @@ export const getLogEntryCategoryExamplesRequestPayloadRT = rt.type({ categoryId: rt.number, // the number of examples to fetch exampleCount: rt.number, - // the id of the source configuration - sourceId: rt.string, + // log view + logView: persistedLogViewReferenceRT, // the time range to fetch the category examples from timeRange: timeRangeRT, }), diff --git a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts index 2879991e18578..3aeba96058907 100644 --- a/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts +++ b/x-pack/plugins/infra/common/http_api/log_analysis/results/log_entry_examples.ts @@ -6,6 +6,7 @@ */ import * as rt from 'io-ts'; +import { persistedLogViewReferenceRT } from '../../../log_views'; import { logEntryExampleRT } from '../../../log_analysis'; import { badRequestErrorRT, @@ -28,8 +29,8 @@ export const getLogEntryExamplesRequestPayloadRT = rt.type({ dataset: rt.string, // the number of examples to fetch exampleCount: rt.number, - // the id of the source configuration - sourceId: rt.string, + // logView + logView: persistedLogViewReferenceRT, // the time range to fetch the log rate examples from timeRange: timeRangeRT, }), diff --git a/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts b/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts index ec3a6b8a2d2ec..a863d35d5b491 100644 --- a/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts +++ b/x-pack/plugins/infra/common/http_api/log_entries/highlights.ts @@ -8,12 +8,13 @@ import * as rt from 'io-ts'; import { logEntryCursorRT, logEntryRT } from '../../log_entry'; import { logViewColumnConfigurationRT } from '../../log_views'; +import { logViewReferenceRT } from '../../log_views'; export const LOG_ENTRIES_HIGHLIGHTS_PATH = '/api/log_entries/highlights'; export const logEntriesHighlightsBaseRequestRT = rt.intersection([ rt.type({ - sourceId: rt.string, + logView: logViewReferenceRT, startTimestamp: rt.number, endTimestamp: rt.number, highlightTerms: rt.array(rt.string), diff --git a/x-pack/plugins/infra/common/http_api/log_entries/summary.ts b/x-pack/plugins/infra/common/http_api/log_entries/summary.ts index 64b40004230df..6303c06ac3698 100644 --- a/x-pack/plugins/infra/common/http_api/log_entries/summary.ts +++ b/x-pack/plugins/infra/common/http_api/log_entries/summary.ts @@ -6,11 +6,12 @@ */ import * as rt from 'io-ts'; +import { logViewReferenceRT } from '../../log_views'; export const LOG_ENTRIES_SUMMARY_PATH = '/api/log_entries/summary'; export const logEntriesSummaryRequestRT = rt.type({ - sourceId: rt.string, + logView: logViewReferenceRT, startTimestamp: rt.number, endTimestamp: rt.number, bucketSize: rt.number, diff --git a/x-pack/plugins/infra/common/log_views/types.ts b/x-pack/plugins/infra/common/log_views/types.ts index ed42fe82862bc..5bf9585bb1c2f 100644 --- a/x-pack/plugins/infra/common/log_views/types.ts +++ b/x-pack/plugins/infra/common/log_views/types.ts @@ -103,9 +103,19 @@ export const logViewStatusRT = rt.strict({ }); export type LogViewStatus = rt.TypeOf; -export const logViewReferenceRT = rt.type({ +export const persistedLogViewReferenceRT = rt.type({ logViewId: rt.string, type: rt.literal('log-view-reference'), }); +export type PersistedLogViewReference = rt.TypeOf; + +export const inlineLogViewReferenceRT = rt.type({ + type: rt.literal('log-view-inline'), + id: rt.string, + attributes: logViewAttributesRT, +}); + +export const logViewReferenceRT = rt.union([persistedLogViewReferenceRT, inlineLogViewReferenceRT]); + export type LogViewReference = rt.TypeOf; diff --git a/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts b/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts index 65bcec8c98e6a..f8daaa1b9227b 100644 --- a/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts +++ b/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts @@ -13,7 +13,7 @@ import { logEntryCursorRT, logEntryRT, } from '../../log_entry'; -import { logViewColumnConfigurationRT } from '../../log_views'; +import { logViewColumnConfigurationRT, logViewReferenceRT } from '../../log_views'; import { jsonObjectRT } from '../../typed_json'; import { searchStrategyErrorRT } from '../common/errors'; @@ -21,7 +21,7 @@ export const LOG_ENTRIES_SEARCH_STRATEGY = 'infra-log-entries'; const logEntriesBaseSearchRequestParamsRT = rt.intersection([ rt.type({ - sourceId: rt.string, + logView: logViewReferenceRT, startTimestamp: rt.number, endTimestamp: rt.number, size: rt.number, diff --git a/x-pack/plugins/infra/common/search_strategies/log_entries/log_entry.ts b/x-pack/plugins/infra/common/search_strategies/log_entries/log_entry.ts index 2dc182c4ba0e2..6d2a7891264d1 100644 --- a/x-pack/plugins/infra/common/search_strategies/log_entries/log_entry.ts +++ b/x-pack/plugins/infra/common/search_strategies/log_entries/log_entry.ts @@ -7,12 +7,13 @@ import * as rt from 'io-ts'; import { logEntryCursorRT, logEntryFieldRT } from '../../log_entry'; +import { logViewReferenceRT } from '../../log_views'; import { searchStrategyErrorRT } from '../common/errors'; export const LOG_ENTRY_SEARCH_STRATEGY = 'infra-log-entry'; export const logEntrySearchRequestParamsRT = rt.type({ - sourceId: rt.string, + logView: logViewReferenceRT, logEntryId: rt.string, }); diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx index c6b18bebc98b3..1c38dca829aef 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx @@ -13,7 +13,7 @@ import { ForLastExpression, RuleTypeParamsExpressionProps, } from '@kbn/triggers-actions-ui-plugin/public'; -import { LogViewReference, ResolvedLogViewField } from '../../../../../common/log_views'; +import { PersistedLogViewReference, ResolvedLogViewField } from '../../../../../common/log_views'; import { Comparator, isOptimizableGroupedThreshold, @@ -54,7 +54,7 @@ const DEFAULT_BASE_EXPRESSION = { const DEFAULT_FIELD = 'log.level'; -const createLogViewReference = (logViewId: string): LogViewReference => ({ +const createLogViewReference = (logViewId: string): PersistedLogViewReference => ({ logViewId, type: 'log-view-reference', }); @@ -69,7 +69,7 @@ const createDefaultCriterion = ( const createDefaultCountRuleParams = ( availableFields: ResolvedLogViewField[], - logView: LogViewReference + logView: PersistedLogViewReference ): PartialCountRuleParams => ({ ...DEFAULT_BASE_EXPRESSION, logView, @@ -82,7 +82,7 @@ const createDefaultCountRuleParams = ( const createDefaultRatioRuleParams = ( availableFields: ResolvedLogViewField[], - logView: LogViewReference + logView: PersistedLogViewReference ): PartialRatioRuleParams => ({ ...DEFAULT_BASE_EXPRESSION, logView, @@ -226,11 +226,11 @@ export const Editor: React.FC createLogViewReference(logViewId), [logViewId]); + const logViewReference = useMemo(() => createLogViewReference(logViewId), [logViewId]); const defaultCountAlertParams = useMemo( - () => createDefaultCountRuleParams(supportedFields, logViewReferemnce), - [supportedFields, logViewReferemnce] + () => createDefaultCountRuleParams(supportedFields, logViewReference), + [supportedFields, logViewReference] ); const updateType = useCallback( @@ -238,12 +238,12 @@ export const Editor: React.FC { diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx index 9b9dc501e1591..0b99cea2fd7c9 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/hooks/use_chart_preview_data.tsx @@ -73,7 +73,7 @@ export const callGetChartPreviewDataAPI = async ( body: JSON.stringify( getLogAlertsChartPreviewDataRequestPayloadRT.encode({ data: { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, alertParams, buckets, }, diff --git a/x-pack/plugins/infra/public/containers/logs/log_entry.ts b/x-pack/plugins/infra/public/containers/logs/log_entry.ts index b9f95f3db6ab0..958097fc3baa5 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_entry.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_entry.ts @@ -30,7 +30,10 @@ export const useLogEntry = ({ return !!logEntryId && !!sourceId ? { request: { - params: logEntrySearchRequestParamsRT.encode({ sourceId, logEntryId }), + params: logEntrySearchRequestParamsRT.encode({ + logView: { type: 'log-view-reference', logViewId: sourceId }, + logEntryId, + }), }, options: { strategy: LOG_ENTRY_SEARCH_STRATEGY }, } diff --git a/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx b/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx index fc1026243a7e0..d9f7ab078ae0b 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_highlights/log_entry_highlights.tsx @@ -37,7 +37,7 @@ export const useLogEntryHighlights = ( return await fetchLogEntriesHighlights( { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, startTimestamp, endTimestamp, center: centerPoint, diff --git a/x-pack/plugins/infra/public/containers/logs/log_highlights/log_summary_highlights.ts b/x-pack/plugins/infra/public/containers/logs/log_highlights/log_summary_highlights.ts index 59abb716f6cb3..e994e2a013bb7 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_highlights/log_summary_highlights.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_highlights/log_summary_highlights.ts @@ -39,7 +39,7 @@ export const useLogSummaryHighlights = ( return await fetchLogSummaryHighlights( { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, startTimestamp, endTimestamp, bucketSize, diff --git a/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_after.ts b/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_after.ts index 1e9e1dd48a47b..3ee39fbda3d49 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_after.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_after.ts @@ -58,7 +58,7 @@ export const useLogEntriesAfterRequest = ({ highlightPhrase, query: query as JsonObject, size: params.size, - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, startTimestamp, }), }, diff --git a/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_before.ts b/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_before.ts index 6e72fce5a1d2b..581d31a28a8c5 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_before.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_stream/use_fetch_log_entries_before.ts @@ -58,7 +58,7 @@ export const useLogEntriesBeforeRequest = ({ highlightPhrase, query: query as JsonObject, size: params.size, - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, startTimestamp: params.extendTo ?? startTimestamp, }), }, diff --git a/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.test.tsx b/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.test.tsx index 25e02101984f4..fe02367e4b1ff 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.test.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.test.tsx @@ -62,7 +62,7 @@ describe('useLogSummary hook', () => { expect(fetchLogSummaryMock).toHaveBeenCalledTimes(1); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( expect.objectContaining({ - sourceId: 'INITIAL_SOURCE_ID', + logView: { logViewId: 'INITIAL_SOURCE_ID', type: 'log-view-reference' }, }), expect.anything() ); @@ -74,7 +74,7 @@ describe('useLogSummary hook', () => { expect(fetchLogSummaryMock).toHaveBeenCalledTimes(2); expect(fetchLogSummaryMock).toHaveBeenLastCalledWith( expect.objectContaining({ - sourceId: 'CHANGED_SOURCE_ID', + logView: { logViewId: 'CHANGED_SOURCE_ID', type: 'log-view-reference' }, }), expect.anything() ); diff --git a/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.tsx b/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.tsx index b3e7f8235ace7..c4b933ab04cd0 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_summary/log_summary.tsx @@ -35,7 +35,7 @@ export const useLogSummary = ( pushLogSummaryBucketsArgs([ { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, startTimestamp, endTimestamp, bucketSize, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_datasets.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_datasets.ts index 51d4a69ada295..34358b983e12b 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_datasets.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_datasets.ts @@ -31,7 +31,7 @@ export const callGetLogEntryCategoryDatasetsAPI = async ( body: JSON.stringify( getLogEntryCategoryDatasetsRequestPayloadRT.encode({ data: { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_examples.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_examples.ts index 90727fd6f0853..e3b99750af715 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_examples.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_log_entry_category_examples.ts @@ -35,7 +35,7 @@ export const callGetLogEntryCategoryExamplesAPI = async ( data: { categoryId, exampleCount, - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts index 9472991e15c66..93e9daf0b9cb6 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_categories/service_calls/get_top_log_entry_categories.ts @@ -36,7 +36,7 @@ export const callGetTopLogEntryCategoriesAPI = async ( body: JSON.stringify( getLogEntryCategoriesRequestPayloadRT.encode({ data: { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts index 5f0f95a3e7976..7916cad0f1e07 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies.ts @@ -30,7 +30,7 @@ export const callGetLogEntryAnomaliesAPI = async (requestArgs: RequestArgs, fetc body: JSON.stringify( getLogEntryAnomaliesRequestPayloadRT.encode({ data: { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies_datasets.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies_datasets.ts index 9b560845186f7..16a8092f290f8 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies_datasets.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_anomalies_datasets.ts @@ -29,7 +29,7 @@ export const callGetLogEntryAnomaliesDatasetsAPI = async ( body: JSON.stringify( getLogEntryAnomaliesDatasetsRequestPayloadRT.encode({ data: { - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_examples.ts b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_examples.ts index 5844e00ebfe4e..0e44e5b02feb7 100644 --- a/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_examples.ts +++ b/x-pack/plugins/infra/public/pages/logs/log_entry_rate/service_calls/get_log_entry_examples.ts @@ -32,7 +32,7 @@ export const callGetLogEntryExamplesAPI = async (requestArgs: RequestArgs, fetch data: { dataset, exampleCount, - sourceId, + logView: { type: 'log-view-reference', logViewId: sourceId }, timeRange: { startTime, endTime, diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index e62fd9291fc33..bd033b5285b3e 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -158,7 +158,10 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) = const [, , { logViews }] = await libs.getStartServices(); const logQueryFields: LogQueryFields | undefined = await logViews .getClient(savedObjectsClient, esClient) - .getResolvedLogView(sourceId) + .getResolvedLogView({ + type: 'log-view-reference', + logViewId: sourceId, + }) .then( ({ indices }) => ({ indexPattern: indices }), () => undefined diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index 37eb4698ff089..1d0470c244fd1 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -188,7 +188,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) => const { indices, timestampField, runtimeMappings } = await logViews .getClient(savedObjectsClient, scopedClusterClient.asCurrentUser) - .getResolvedLogView(validatedParams.logView.logViewId); + .getResolvedLogView(validatedParams.logView); if (!isRatioRuleParams(validatedParams)) { await executeAlert( diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts index 1e0daad376a1a..fcda9b30b0dac 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -15,6 +15,7 @@ import { LogColumn, LogEntry, LogEntryCursor } from '../../../../common/log_entr import { LogViewColumnConfiguration, logViewFieldColumnConfigurationRT, + LogViewReference, ResolvedLogView, } from '../../../../common/log_views'; import { decodeOrThrow } from '../../../../common/runtime_types'; @@ -66,7 +67,7 @@ export class InfraLogEntriesDomain { public async getLogEntriesAround( requestContext: InfraPluginRequestHandlerContext, - sourceId: string, + logView: LogViewReference, params: LogEntriesAroundParams, columnOverrides?: LogViewColumnConfiguration[] ): Promise<{ entries: LogEntry[]; hasMoreBefore?: boolean; hasMoreAfter?: boolean }> { @@ -84,7 +85,7 @@ export class InfraLogEntriesDomain { const { entries: entriesBefore, hasMoreBefore } = await this.getLogEntries( requestContext, - sourceId, + logView, { startTimestamp, endTimestamp, @@ -110,7 +111,7 @@ export class InfraLogEntriesDomain { const { entries: entriesAfter, hasMoreAfter } = await this.getLogEntries( requestContext, - sourceId, + logView, { startTimestamp, endTimestamp, @@ -126,7 +127,7 @@ export class InfraLogEntriesDomain { public async getLogEntries( requestContext: InfraPluginRequestHandlerContext, - sourceId: string, + logView: LogViewReference, params: LogEntriesParams, columnOverrides?: LogViewColumnConfiguration[] ): Promise<{ entries: LogEntry[]; hasMoreBefore?: boolean; hasMoreAfter?: boolean }> { @@ -134,7 +135,7 @@ export class InfraLogEntriesDomain { const { savedObjects, elasticsearch } = await requestContext.core; const resolvedLogView = await logViews .getClient(savedObjects.client, elasticsearch.client.asCurrentUser) - .getResolvedLogView(sourceId); + .getResolvedLogView(logView); const columnDefinitions = columnOverrides ?? resolvedLogView.columns; const messageFormattingRules = compileFormattingRules( @@ -184,7 +185,7 @@ export class InfraLogEntriesDomain { public async getLogSummaryBucketsBetween( requestContext: InfraPluginRequestHandlerContext, - sourceId: string, + logView: LogViewReference, start: number, end: number, bucketSize: number, @@ -194,7 +195,7 @@ export class InfraLogEntriesDomain { const { savedObjects, elasticsearch } = await requestContext.core; const resolvedLogView = await logViews .getClient(savedObjects.client, elasticsearch.client.asCurrentUser) - .getResolvedLogView(sourceId); + .getResolvedLogView(logView); const dateRangeBuckets = await this.adapter.getContainedLogSummaryBuckets( requestContext, resolvedLogView, @@ -208,7 +209,7 @@ export class InfraLogEntriesDomain { public async getLogSummaryHighlightBucketsBetween( requestContext: InfraPluginRequestHandlerContext, - sourceId: string, + logView: LogViewReference, startTimestamp: number, endTimestamp: number, bucketSize: number, @@ -219,7 +220,7 @@ export class InfraLogEntriesDomain { const { savedObjects, elasticsearch } = await requestContext.core; const resolvedLogView = await logViews .getClient(savedObjects.client, elasticsearch.client.asCurrentUser) - .getResolvedLogView(sourceId); + .getResolvedLogView(logView); const messageFormattingRules = compileFormattingRules( getBuiltinRules(resolvedLogView.messageField) ); diff --git a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts index 22bf5466ee3b4..b17afa68d2d4d 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts @@ -16,7 +16,7 @@ import { logEntryRateJobTypes, Pagination, } from '../../../common/log_analysis'; -import { ResolvedLogView } from '../../../common/log_views'; +import { PersistedLogViewReference, ResolvedLogView } from '../../../common/log_views'; import { startTracingSpan, TracingSpan } from '../../../common/performance_tracing'; import { decodeOrThrow } from '../../../common/runtime_types'; import type { @@ -54,11 +54,11 @@ interface MappedAnomalyHit { async function getCompatibleAnomaliesJobIds( spaceId: string, - sourceId: string, + logViewId: string, mlAnomalyDetectors: MlAnomalyDetectors ) { - const logRateJobId = getJobId(spaceId, sourceId, logEntryRateJobTypes[0]); - const logCategoriesJobId = getJobId(spaceId, sourceId, logEntryCategoriesJobTypes[0]); + const logRateJobId = getJobId(spaceId, logViewId, logEntryRateJobTypes[0]); + const logCategoriesJobId = getJobId(spaceId, logViewId, logEntryCategoriesJobTypes[0]); const jobIds: string[] = []; let jobSpans: TracingSpan[] = []; @@ -99,7 +99,7 @@ export async function getLogEntryAnomalies( context: InfraPluginRequestHandlerContext & { infra: Promise>; }, - sourceId: string, + logView: PersistedLogViewReference, startTime: number, endTime: number, sort: AnomaliesSort, @@ -114,7 +114,7 @@ export async function getLogEntryAnomalies( timing: { spans: jobSpans }, } = await getCompatibleAnomaliesJobIds( infraContext.spaceId, - sourceId, + logView.logViewId, infraContext.mlAnomalyDetectors ); @@ -155,7 +155,7 @@ export async function getLogEntryAnomalies( const logEntryCategoriesCountJobId = getJobId( infraContext.spaceId, - sourceId, + logView.logViewId, logEntryCategoriesJobTypes[0] ); @@ -331,7 +331,7 @@ export async function getLogEntryExamples( context: InfraPluginRequestHandlerContext & { infra: Promise>; }, - sourceId: string, + logView: PersistedLogViewReference, startTime: number, endTime: number, dataset: string, @@ -345,7 +345,7 @@ export async function getLogEntryExamples( const jobId = getJobId( infraContext.spaceId, - sourceId, + logView.logViewId, categoryId != null ? logEntryCategoriesJobTypes[0] : logEntryRateJobTypes[0] ); @@ -370,7 +370,7 @@ export async function getLogEntryExamples( timing: { spans: fetchLogEntryExamplesSpans }, } = await fetchLogEntryExamples( context, - sourceId, + logView, indices, runtimeMappings, timestampField, @@ -397,7 +397,7 @@ export async function fetchLogEntryExamples( context: InfraPluginRequestHandlerContext & { infra: Promise>; }, - sourceId: string, + logView: PersistedLogViewReference, indices: string, runtimeMappings: estypes.MappingRuntimeFields, timestampField: string, @@ -420,7 +420,7 @@ export async function fetchLogEntryExamples( const logEntryCategoriesCountJobId = getJobId( infraContext.spaceId, - sourceId, + logView.logViewId, logEntryCategoriesJobTypes[0] ); @@ -483,7 +483,7 @@ export async function getLogEntryAnomaliesDatasets( spaceId: string; }; }, - sourceId: string, + logView: PersistedLogViewReference, startTime: number, endTime: number ) { @@ -492,7 +492,7 @@ export async function getLogEntryAnomaliesDatasets( timing: { spans: jobSpans }, } = await getCompatibleAnomaliesJobIds( context.infra.spaceId, - sourceId, + logView.logViewId, context.infra.mlAnomalyDetectors ); diff --git a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts index 9152945002e2a..d8eb18e4890b5 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts @@ -15,7 +15,7 @@ import { logEntryCategoriesJobTypes, } from '../../../common/log_analysis'; import { LogEntryContext } from '../../../common/log_entry'; -import { ResolvedLogView } from '../../../common/log_views'; +import { PersistedLogViewReference, ResolvedLogView } from '../../../common/log_views'; import { startTracingSpan } from '../../../common/performance_tracing'; import { decodeOrThrow } from '../../../common/runtime_types'; import type { MlAnomalyDetectors, MlSystem } from '../../types'; @@ -47,7 +47,7 @@ export async function getTopLogEntryCategories( spaceId: string; }; }, - sourceId: string, + logView: PersistedLogViewReference, startTime: number, endTime: number, categoryCount: number, @@ -59,7 +59,7 @@ export async function getTopLogEntryCategories( const logEntryCategoriesCountJobId = getJobId( context.infra.spaceId, - sourceId, + logView.logViewId, logEntryCategoriesJobTypes[0] ); @@ -119,13 +119,13 @@ export async function getLogEntryCategoryDatasets( spaceId: string; }; }, - sourceId: string, + logView: PersistedLogViewReference, startTime: number, endTime: number ) { const logEntryCategoriesCountJobId = getJobId( context.infra.spaceId, - sourceId, + logView.logViewId, logEntryCategoriesJobTypes[0] ); @@ -143,7 +143,7 @@ export async function getLogEntryCategoryExamples( spaceId: string; }; }, - sourceId: string, + logView: PersistedLogViewReference, startTime: number, endTime: number, categoryId: number, @@ -154,7 +154,7 @@ export async function getLogEntryCategoryExamples( const logEntryCategoriesCountJobId = getJobId( context.infra.spaceId, - sourceId, + logView.logViewId, logEntryCategoriesJobTypes[0] ); diff --git a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_rate_analysis.ts b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_rate_analysis.ts index 7da6298fff76a..1e043fed0986a 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_rate_analysis.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_rate_analysis.ts @@ -24,13 +24,13 @@ export async function getLogEntryRateBuckets( spaceId: string; }; }, - sourceId: string, + logViewId: string, startTime: number, endTime: number, bucketDuration: number, datasets?: string[] ) { - const logRateJobId = getJobId(context.infra.spaceId, sourceId, 'log-entry-rate'); + const logRateJobId = getJobId(context.infra.spaceId, logViewId, 'log-entry-rate'); let mlModelPlotBuckets: LogRateModelPlotBucket[] = []; let afterLatestBatchKey: CompositeTimestampPartitionKey | undefined; diff --git a/x-pack/plugins/infra/server/routes/log_alerts/chart_preview_data.ts b/x-pack/plugins/infra/server/routes/log_alerts/chart_preview_data.ts index 95b0c8320559e..fbc530397f4e3 100644 --- a/x-pack/plugins/infra/server/routes/log_alerts/chart_preview_data.ts +++ b/x-pack/plugins/infra/server/routes/log_alerts/chart_preview_data.ts @@ -29,11 +29,11 @@ export const initGetLogAlertsChartPreviewDataRoute = ({ }, framework.router.handleLegacyErrors(async (requestContext, request, response) => { const { - data: { sourceId, buckets, alertParams }, + data: { logView, buckets, alertParams }, } = request.body; const [, , { logViews }] = await getStartServices(); - const resolvedLogView = await logViews.getScopedClient(request).getResolvedLogView(sourceId); + const resolvedLogView = await logViews.getScopedClient(request).getResolvedLogView(logView); try { const { series } = await getChartPreviewData( diff --git a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts index dd6254cf560e2..13df82f8fe343 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies.ts @@ -31,7 +31,7 @@ export const initGetLogEntryAnomaliesRoute = ({ framework }: InfraBackendLibs) = framework.router.handleLegacyErrors(async (requestContext, request, response) => { const { data: { - sourceId, + logView, timeRange: { startTime, endTime }, sort: sortParam, pagination: paginationParam, @@ -51,7 +51,7 @@ export const initGetLogEntryAnomaliesRoute = ({ framework }: InfraBackendLibs) = timing, } = await getLogEntryAnomalies( infraMlContext, - sourceId, + logView, startTime, endTime, sort, diff --git a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies_datasets.ts b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies_datasets.ts index 1d1f620063b2e..5f7aec90376af 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies_datasets.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_anomalies_datasets.ts @@ -29,7 +29,7 @@ export const initGetLogEntryAnomaliesDatasetsRoute = ({ framework }: InfraBacken framework.router.handleLegacyErrors(async (requestContext, request, response) => { const { data: { - sourceId, + logView, timeRange: { startTime, endTime }, }, } = request.body; @@ -39,7 +39,7 @@ export const initGetLogEntryAnomaliesDatasetsRoute = ({ framework }: InfraBacken const { datasets, timing } = await getLogEntryAnomaliesDatasets( { infra: await infraMlContext.infra }, - sourceId, + logView, startTime, endTime ); diff --git a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_categories.ts b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_categories.ts index 6e2e8e8a6c2ad..1a484a0662e05 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_categories.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_categories.ts @@ -31,7 +31,7 @@ export const initGetLogEntryCategoriesRoute = ({ framework }: InfraBackendLibs) data: { categoryCount, histograms, - sourceId, + logView, timeRange: { startTime, endTime }, datasets, sort, @@ -43,7 +43,7 @@ export const initGetLogEntryCategoriesRoute = ({ framework }: InfraBackendLibs) const { data: topLogEntryCategories, timing } = await getTopLogEntryCategories( { infra: await infraMlContext.infra }, - sourceId, + logView, startTime, endTime, categoryCount, diff --git a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_datasets.ts b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_datasets.ts index de5ac9dac4b07..92f0cd576a0f8 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_datasets.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_datasets.ts @@ -29,7 +29,7 @@ export const initGetLogEntryCategoryDatasetsRoute = ({ framework }: InfraBackend framework.router.handleLegacyErrors(async (requestContext, request, response) => { const { data: { - sourceId, + logView, timeRange: { startTime, endTime }, }, } = request.body; @@ -39,7 +39,7 @@ export const initGetLogEntryCategoryDatasetsRoute = ({ framework }: InfraBackend const { data: logEntryCategoryDatasets, timing } = await getLogEntryCategoryDatasets( { infra: await infraMlContext.infra }, - sourceId, + logView, startTime, endTime ); diff --git a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_examples.ts b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_examples.ts index b51aed45b7e11..40de491c1673f 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_examples.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_category_examples.ts @@ -34,20 +34,20 @@ export const initGetLogEntryCategoryExamplesRoute = ({ data: { categoryId, exampleCount, - sourceId, + logView, timeRange: { startTime, endTime }, }, } = request.body; const [, , { logViews }] = await getStartServices(); - const resolvedLogView = await logViews.getScopedClient(request).getResolvedLogView(sourceId); + const resolvedLogView = await logViews.getScopedClient(request).getResolvedLogView(logView); try { const infraMlContext = await assertHasInfraMlPlugins(requestContext); const { data: logEntryCategoryExamples, timing } = await getLogEntryCategoryExamples( { infra: await infraMlContext.infra, core: await infraMlContext.core }, - sourceId, + logView, startTime, endTime, categoryId, diff --git a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_examples.ts b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_examples.ts index fb82a2cd90df5..23ba1072a60fc 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_examples.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/results/log_entry_examples.ts @@ -34,21 +34,21 @@ export const initGetLogEntryExamplesRoute = ({ data: { dataset, exampleCount, - sourceId, + logView, timeRange: { startTime, endTime }, categoryId, }, } = request.body; const [, , { logViews }] = await getStartServices(); - const resolvedLogView = await logViews.getScopedClient(request).getResolvedLogView(sourceId); + const resolvedLogView = await logViews.getScopedClient(request).getResolvedLogView(logView); try { const infraMlContext = await assertHasInfraMlPlugins(requestContext); const { data: logEntryExamples, timing } = await getLogEntryExamples( infraMlContext, - sourceId, + logView, startTime, endTime, dataset, diff --git a/x-pack/plugins/infra/server/routes/log_entries/highlights.ts b/x-pack/plugins/infra/server/routes/log_entries/highlights.ts index bb7c615358c0e..aa8876951ee6c 100644 --- a/x-pack/plugins/infra/server/routes/log_entries/highlights.ts +++ b/x-pack/plugins/infra/server/routes/log_entries/highlights.ts @@ -38,14 +38,14 @@ export const initLogEntriesHighlightsRoute = ({ framework, logEntries }: InfraBa fold(throwErrors(Boom.badRequest), identity) ); - const { startTimestamp, endTimestamp, sourceId, query, size, highlightTerms } = payload; + const { startTimestamp, endTimestamp, logView, query, size, highlightTerms } = payload; let entriesPerHighlightTerm; if ('center' in payload) { entriesPerHighlightTerm = await Promise.all( highlightTerms.map((highlightTerm) => - logEntries.getLogEntriesAround(requestContext, sourceId, { + logEntries.getLogEntriesAround(requestContext, logView, { startTimestamp, endTimestamp, query: parseFilterQuery(query), @@ -65,7 +65,7 @@ export const initLogEntriesHighlightsRoute = ({ framework, logEntries }: InfraBa entriesPerHighlightTerm = await Promise.all( highlightTerms.map((highlightTerm) => - logEntries.getLogEntries(requestContext, sourceId, { + logEntries.getLogEntries(requestContext, logView, { startTimestamp, endTimestamp, query: parseFilterQuery(query), diff --git a/x-pack/plugins/infra/server/routes/log_entries/summary.ts b/x-pack/plugins/infra/server/routes/log_entries/summary.ts index 3ff0ded8a7c24..dd48c21a590ae 100644 --- a/x-pack/plugins/infra/server/routes/log_entries/summary.ts +++ b/x-pack/plugins/infra/server/routes/log_entries/summary.ts @@ -37,11 +37,11 @@ export const initLogEntriesSummaryRoute = ({ framework, logEntries }: InfraBacke logEntriesSummaryRequestRT.decode(request.body), fold(throwErrors(Boom.badRequest), identity) ); - const { sourceId, startTimestamp, endTimestamp, bucketSize, query } = payload; + const { logView, startTimestamp, endTimestamp, bucketSize, query } = payload; const buckets = await logEntries.getLogSummaryBucketsBetween( requestContext, - sourceId, + logView, startTimestamp, endTimestamp, bucketSize, diff --git a/x-pack/plugins/infra/server/routes/log_entries/summary_highlights.ts b/x-pack/plugins/infra/server/routes/log_entries/summary_highlights.ts index ca219cac41e2b..206e02bc57278 100644 --- a/x-pack/plugins/infra/server/routes/log_entries/summary_highlights.ts +++ b/x-pack/plugins/infra/server/routes/log_entries/summary_highlights.ts @@ -39,11 +39,11 @@ export const initLogEntriesSummaryHighlightsRoute = ({ logEntriesSummaryHighlightsRequestRT.decode(request.body), fold(throwErrors(Boom.badRequest), identity) ); - const { sourceId, startTimestamp, endTimestamp, bucketSize, query, highlightTerms } = payload; + const { logView, startTimestamp, endTimestamp, bucketSize, query, highlightTerms } = payload; const bucketsPerHighlightTerm = await logEntries.getLogSummaryHighlightBucketsBetween( requestContext, - sourceId, + logView, startTimestamp, endTimestamp, bucketSize, diff --git a/x-pack/plugins/infra/server/routes/snapshot/index.ts b/x-pack/plugins/infra/server/routes/snapshot/index.ts index 27c49032c03f4..0c893171b5b67 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/index.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/index.ts @@ -43,7 +43,10 @@ export const initSnapshotRoute = (libs: InfraBackendLibs) => { const [, , { logViews }] = await libs.getStartServices(); const logQueryFields: LogQueryFields | undefined = await logViews .getScopedClient(request) - .getResolvedLogView(snapshotRequest.sourceId) + .getResolvedLogView({ + type: 'log-view-reference', + logViewId: snapshotRequest.sourceId, + }) .then( ({ indices }) => ({ indexPattern: indices }), () => undefined diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts index 99579c5a588c6..bb21053cfe9d8 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts @@ -57,7 +57,7 @@ describe('LogEntries search strategy', () => { logEntriesSearchStrategy.search( { params: { - sourceId: 'SOURCE_ID', + logView: { type: 'log-view-reference', logViewId: 'SOURCE_ID' }, startTimestamp: 100, endTimestamp: 200, size: 3, @@ -143,7 +143,7 @@ describe('LogEntries search strategy', () => { { id: requestId, params: { - sourceId: 'SOURCE_ID', + logView: { type: 'log-view-reference', logViewId: 'SOURCE_ID' }, startTimestamp: 100, endTimestamp: 200, size: 3, @@ -223,7 +223,7 @@ describe('LogEntries search strategy', () => { { id: logEntriesSearchRequestStateRT.encode({ esRequestId: 'UNKNOWN_ID' }), params: { - sourceId: 'SOURCE_ID', + logView: { type: 'log-view-reference', logViewId: 'SOURCE_ID' }, startTimestamp: 100, endTimestamp: 200, size: 3, diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts index 81ef319828be1..f0f5c6304d615 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts @@ -72,7 +72,7 @@ export const logEntriesSearchStrategyProvider = ({ const request = decodeOrThrow(asyncRequestRT)(rawRequest); const resolvedLogView$ = defer(() => - logViews.getScopedClient(dependencies.request).getResolvedLogView(request.params.sourceId) + logViews.getScopedClient(dependencies.request).getResolvedLogView(request.params.logView) ).pipe(take(1), shareReplay(1)); const messageFormattingRules$ = defer(() => diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts index d2d28174490c8..19d5345122374 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts @@ -56,7 +56,10 @@ describe('LogEntry search strategy', () => { const response = await lastValueFrom( logEntrySearchStrategy.search( { - params: { sourceId: 'SOURCE_ID', logEntryId: 'LOG_ENTRY_ID' }, + params: { + logView: { type: 'log-view-reference', logViewId: 'SOURCE_ID' }, + logEntryId: 'LOG_ENTRY_ID', + }, }, {}, mockDependencies @@ -141,7 +144,10 @@ describe('LogEntry search strategy', () => { logEntrySearchStrategy.search( { id: requestId, - params: { sourceId: 'SOURCE_ID', logEntryId: 'LOG_ENTRY_ID' }, + params: { + logView: { type: 'log-view-reference', logViewId: 'SOURCE_ID' }, + logEntryId: 'LOG_ENTRY_ID', + }, }, {}, mockDependencies @@ -193,7 +199,10 @@ describe('LogEntry search strategy', () => { const response = logEntrySearchStrategy.search( { id: logEntrySearchRequestStateRT.encode({ esRequestId: 'UNKNOWN_ID' }), - params: { sourceId: 'SOURCE_ID', logEntryId: 'LOG_ENTRY_ID' }, + params: { + logView: { type: 'log-view-reference', logViewId: 'SOURCE_ID' }, + logEntryId: 'LOG_ENTRY_ID', + }, }, {}, mockDependencies diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts index 714e0b792c612..1d558094e351d 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts @@ -48,7 +48,7 @@ export const logEntrySearchStrategyProvider = ({ const request = decodeOrThrow(asyncRequestRT)(rawRequest); const resolvedLogView$ = defer(() => - logViews.getScopedClient(dependencies.request).getResolvedLogView(request.params.sourceId) + logViews.getScopedClient(dependencies.request).getResolvedLogView(request.params.logView) ).pipe(take(1), shareReplay(1)); const recoveredRequest$ = of(request).pipe( diff --git a/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts b/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts index 5c20297b82c65..5738c94c8aa40 100644 --- a/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts +++ b/x-pack/plugins/infra/server/services/log_views/log_views_client.mock.ts @@ -5,12 +5,15 @@ * 2.0. */ +import { LogViewReference } from '../../../common/log_views'; import { createResolvedLogViewMock } from '../../../common/log_views/resolved_log_view.mock'; import { ILogViewsClient } from './types'; export const createLogViewsClientMock = (): jest.Mocked => ({ getLogView: jest.fn(), - getResolvedLogView: jest.fn((logViewId: string) => Promise.resolve(createResolvedLogViewMock())), + getResolvedLogView: jest.fn((logViewReference: LogViewReference) => + Promise.resolve(createResolvedLogViewMock()) + ), putLogView: jest.fn(), resolveLogView: jest.fn(), }); diff --git a/x-pack/plugins/infra/server/services/log_views/log_views_client.ts b/x-pack/plugins/infra/server/services/log_views/log_views_client.ts index 9f43cee871f73..3f832c6770717 100644 --- a/x-pack/plugins/infra/server/services/log_views/log_views_client.ts +++ b/x-pack/plugins/infra/server/services/log_views/log_views_client.ts @@ -19,7 +19,9 @@ import { LogIndexReference, LogView, LogViewAttributes, + LogViewReference, LogViewsStaticConfig, + persistedLogViewReferenceRT, ResolvedLogView, resolveLogView, } from '../../../common/log_views'; @@ -65,8 +67,10 @@ export class LogViewsClient implements ILogViewsClient { ); } - public async getResolvedLogView(logViewId: string): Promise { - const logView = await this.getLogView(logViewId); + public async getResolvedLogView(logViewReference: LogViewReference): Promise { + const logView = persistedLogViewReferenceRT.is(logViewReference) + ? await this.getLogView(logViewReference.logViewId) + : logViewReference; const resolvedLogView = await this.resolveLogView(logView.id, logView.attributes); return resolvedLogView; } diff --git a/x-pack/plugins/infra/server/services/log_views/types.ts b/x-pack/plugins/infra/server/services/log_views/types.ts index 50b4e65cf7548..b5f91cb3587b4 100644 --- a/x-pack/plugins/infra/server/services/log_views/types.ts +++ b/x-pack/plugins/infra/server/services/log_views/types.ts @@ -16,6 +16,7 @@ import { PluginStart as DataViewsServerPluginStart } from '@kbn/data-views-plugi import { LogView, LogViewAttributes, + LogViewReference, LogViewsStaticConfig, ResolvedLogView, } from '../../../common/log_views'; @@ -44,7 +45,7 @@ export interface LogViewsServiceStart { export interface ILogViewsClient { getLogView(logViewId: string): Promise; - getResolvedLogView(logViewId: string): Promise; + getResolvedLogView(logView: LogViewReference): Promise; putLogView(logViewId: string, logViewAttributes: Partial): Promise; resolveLogView(logViewId: string, logViewAttributes: LogViewAttributes): Promise; } diff --git a/x-pack/test/api_integration/apis/metrics_ui/log_entry_highlights.ts b/x-pack/test/api_integration/apis/metrics_ui/log_entry_highlights.ts index aba182274c9a3..2e328e91f8c25 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/log_entry_highlights.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/log_entry_highlights.ts @@ -54,7 +54,7 @@ export default function ({ getService }: FtrProviderContext) { .set(COMMON_HEADERS) .send( logEntriesHighlightsRequestRT.encode({ - sourceId: 'default', + logView: { type: 'log-view-reference', logViewId: 'default' }, startTimestamp: KEY_BEFORE_START.time, endTimestamp: KEY_AFTER_END.time, highlightTerms: ['some string that does not exist'], @@ -82,7 +82,7 @@ export default function ({ getService }: FtrProviderContext) { .set(COMMON_HEADERS) .send( logEntriesHighlightsRequestRT.encode({ - sourceId: 'default', + logView: { type: 'log-view-reference', logViewId: 'default' }, startTimestamp: KEY_BEFORE_START.time, endTimestamp: KEY_AFTER_END.time, highlightTerms: ['message of document 0'], @@ -130,7 +130,7 @@ export default function ({ getService }: FtrProviderContext) { .set(COMMON_HEADERS) .send( logEntriesHighlightsRequestRT.encode({ - sourceId: 'default', + logView: { type: 'log-view-reference', logViewId: 'default' }, startTimestamp: KEY_BEFORE_START.time, endTimestamp: KEY_AFTER_END.time, highlightTerms: ['generate_test_data/simple_logs'], @@ -166,7 +166,7 @@ export default function ({ getService }: FtrProviderContext) { .set(COMMON_HEADERS) .send( logEntriesHighlightsRequestRT.encode({ - sourceId: 'default', + logView: { type: 'log-view-reference', logViewId: 'default' }, startTimestamp: KEY_BEFORE_START.time, endTimestamp: KEY_AFTER_END.time, query: JSON.stringify({ diff --git a/x-pack/test/api_integration/apis/metrics_ui/log_summary.ts b/x-pack/test/api_integration/apis/metrics_ui/log_summary.ts index 4ac098f95764d..3ccfc4c267c7b 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/log_summary.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/log_summary.ts @@ -49,7 +49,7 @@ export default function ({ getService }: FtrProviderContext) { .set(COMMON_HEADERS) .send( logEntriesSummaryRequestRT.encode({ - sourceId: 'default', + logView: { type: 'log-view-reference', logViewId: 'default' }, startTimestamp, endTimestamp, bucketSize, From e2f0f59993c50a7b54daa4addfe1d9c3f60af288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Thu, 2 Mar 2023 14:34:39 +0100 Subject: [PATCH 115/131] [Security Solution][Endpoint] Hide policy link from artifacts flyout when no policy management privileges (#152330) ## Summary It hides the policy details link from artifacts form flyout when user does not have policy management privileges. ### 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: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../effected_policy_select.test.tsx | 43 +++++++++++++++++++ .../effected_policy_select.tsx | 18 ++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.test.tsx b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.test.tsx index 41eb4c3be7912..174496f1f3d21 100644 --- a/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.test.tsx @@ -13,6 +13,10 @@ import { fireEvent, act } from '@testing-library/react'; import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; import type { AppContextTestRender } from '../../../common/mock/endpoint'; import { createAppRootMockRenderer } from '../../../common/mock/endpoint'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; +import { initialUserPrivilegesState } from '../../../common/components/user_privileges/user_privileges_context'; + +jest.mock('../../../common/components/user_privileges'); describe('when using EffectedPolicySelect component', () => { const generator = new EndpointDocGenerator('effected-policy-select'); @@ -161,5 +165,44 @@ describe('when using EffectedPolicySelect component', () => { selectPerPolicy(); expect(queryByTestId('loading-spinner')).not.toBeNull(); }); + + it('should hide policy link when no policy management privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + endpointPrivileges: { + loading: false, + canWritePolicyManagement: false, + canReadPolicyManagement: false, + }, + }); + const { queryByTestId } = render({ isGlobal: false }); + expect(queryByTestId('test-policyLink')).toBeNull(); + }); + + it('should show policy link when all policy management privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + endpointPrivileges: { + loading: false, + canWritePolicyManagement: true, + canReadPolicyManagement: true, + }, + }); + const { getByTestId } = render({ isGlobal: false }); + expect(getByTestId('test-policyLink')); + }); + + it('should show policy link when read policy management privileges', () => { + (useUserPrivileges as jest.Mock).mockReturnValue({ + ...initialUserPrivilegesState(), + endpointPrivileges: { + loading: false, + canWritePolicyManagement: false, + canReadPolicyManagement: true, + }, + }); + const { getByTestId } = render({ isGlobal: false }); + expect(getByTestId('test-policyLink')); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx index da5c1c1f68535..079ea01492dcc 100644 --- a/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx +++ b/x-pack/plugins/security_solution/public/management/components/effected_policy_select/effected_policy_select.tsx @@ -22,6 +22,7 @@ import { i18n } from '@kbn/i18n'; import type { EuiSelectableOption } from '@elastic/eui/src/components/selectable/selectable_option'; import { FormattedMessage } from '@kbn/i18n-react'; import styled from 'styled-components'; +import { useUserPrivileges } from '../../../common/components/user_privileges'; import type { PolicyData } from '../../../../common/endpoint/types'; import { LinkToApp } from '../../../common/components/endpoint/link_to_app'; import { getPolicyDetailPath } from '../../common/routing'; @@ -104,6 +105,7 @@ export const EffectedPolicySelect = memo( ...otherSelectableProps }) => { const { getAppUrl } = useAppUrl(); + const { canReadPolicyManagement } = useUserPrivileges().endpointPrivileges; const getTestId = useTestIdGenerator(dataTestSubj); @@ -145,25 +147,35 @@ export const EffectedPolicySelect = memo( data-test-subj={`policy-${policy.id}-checkbox`} /> ), - append: ( + append: canReadPolicyManagement ? ( - ), + ) : null, policy, checked: isPolicySelected.has(policy.id) ? 'on' : undefined, disabled: isGlobal || !isPlatinumPlus || disabled, 'data-test-subj': `policy-${policy.id}`, })) .sort(({ label: labelA }, { label: labelB }) => labelA.localeCompare(labelB)); - }, [disabled, getAppUrl, isGlobal, isPlatinumPlus, options, selected]); + }, [ + canReadPolicyManagement, + disabled, + getAppUrl, + getTestId, + isGlobal, + isPlatinumPlus, + options, + selected, + ]); const handleOnPolicySelectChange = useCallback< Required>['onChange'] From dc1717d53cee332180657620efa90564c281cb25 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Mar 2023 14:38:20 +0100 Subject: [PATCH 116/131] Update dependency react-hook-form to ^7.43.2 (main) (#152420) --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a363b2c162e56..fab59387cb39d 100644 --- a/package.json +++ b/package.json @@ -856,7 +856,7 @@ "react-fast-compare": "^2.0.4", "react-focus-on": "^3.7.0", "react-grid-layout": "^1.3.4", - "react-hook-form": "^7.43.1", + "react-hook-form": "^7.43.2", "react-intl": "^2.8.0", "react-is": "^17.0.2", "react-markdown": "^6.0.3", diff --git a/yarn.lock b/yarn.lock index 5dbae5b6a72b2..99077868338aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23984,10 +23984,10 @@ react-grid-layout@^1.3.4: react-draggable "^4.0.0" react-resizable "^3.0.4" -react-hook-form@^7.43.1: - version "7.43.1" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.43.1.tgz#0d0d7822f3f7fc05ffc41d5f012b49b90fcfa0f0" - integrity sha512-+s3+s8LLytRMriwwuSqeLStVjRXFGxgjjx2jED7Z+wz1J/88vpxieRQGvJVvzrzVxshZ0BRuocFERb779m2kNg== +react-hook-form@^7.43.2: + version "7.43.2" + resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.43.2.tgz#d8ff71956dc3de258dce19d4b1c7e1c6a0188e67" + integrity sha512-NvD3Oe2Y9hhqo2R4I4iJigDzSLpdMnzUpNMxlnzTbdiT7NT3BW0GxWCzEtwPudZMUPbZhNcSy1EcGAygyhDORg== react-input-autosize@^3.0.0: version "3.0.0" From f22b297bd6765c3de74253dc065111dd3333615f Mon Sep 17 00:00:00 2001 From: Cleydyr Bezerra de Albuquerque Date: Thu, 2 Mar 2023 14:55:38 +0100 Subject: [PATCH 117/131] add loading state to delete data streams modal (#152444) ## Summary Add a loading state to the `DeleteDataStreamConfirmationModal` component to inform users that the action is being performed. When running the linter, it changed the file formatting completely. Let me know if I should bypass the lint hook and send the PR again. Fixes #152439 --- .../delete_data_stream_confirmation_modal.tsx | 92 ++++++++++--------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/delete_data_stream_confirmation_modal/delete_data_stream_confirmation_modal.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/delete_data_stream_confirmation_modal/delete_data_stream_confirmation_modal.tsx index f10718788eeab..bdf3958c79ca7 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/delete_data_stream_confirmation_modal/delete_data_stream_confirmation_modal.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/delete_data_stream_confirmation_modal/delete_data_stream_confirmation_modal.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { Fragment } from 'react'; +import React, { Fragment, useState } from 'react'; import { EuiCallOut, EuiConfirmModal, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -25,60 +25,65 @@ export const DeleteDataStreamConfirmationModal: React.FunctionComponent = dataStreams: string[]; onClose: (data?: { hasDeletedDataStreams: boolean }) => void; }) => { + const [isLoading, setLoading] = useState(false); + const dataStreamsCount = dataStreams.length; const handleDeleteDataStreams = () => { - deleteDataStreams(dataStreams).then(({ data: { dataStreamsDeleted, errors }, error }) => { - const hasDeletedDataStreams = dataStreamsDeleted && dataStreamsDeleted.length; + setLoading(true); + + deleteDataStreams(dataStreams) + .then(({ data: { dataStreamsDeleted, errors }, error }) => { + const hasDeletedDataStreams = dataStreamsDeleted && dataStreamsDeleted.length; + + if (hasDeletedDataStreams) { + const successMessage = + dataStreamsDeleted.length === 1 + ? i18n.translate( + 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.successDeleteSingleNotificationMessageText', + { + defaultMessage: "Deleted data stream '{dataStreamName}'", + values: { dataStreamName: dataStreams[0] }, + } + ) + : i18n.translate( + 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.successDeleteMultipleNotificationMessageText', + { + defaultMessage: + 'Deleted {numSuccesses, plural, one {# data stream} other {# data streams}}', + values: { numSuccesses: dataStreamsDeleted.length }, + } + ); - if (hasDeletedDataStreams) { - const successMessage = - dataStreamsDeleted.length === 1 + onClose({ hasDeletedDataStreams }); + notificationService.showSuccessToast(successMessage); + } + + if (error || (errors && errors.length)) { + const hasMultipleErrors = + (errors && errors.length > 1) || (error && dataStreams.length > 1); + + const errorMessage = hasMultipleErrors ? i18n.translate( - 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.successDeleteSingleNotificationMessageText', + 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.multipleErrorsNotificationMessageText', { - defaultMessage: "Deleted data stream '{dataStreamName}'", - values: { dataStreamName: dataStreams[0] }, + defaultMessage: 'Error deleting {count} data streams', + values: { + count: (errors && errors.length) || dataStreams.length, + }, } ) : i18n.translate( - 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.successDeleteMultipleNotificationMessageText', + 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.errorNotificationMessageText', { - defaultMessage: - 'Deleted {numSuccesses, plural, one {# data stream} other {# data streams}}', - values: { numSuccesses: dataStreamsDeleted.length }, + defaultMessage: "Error deleting data stream '{name}'", + values: { name: (errors && errors[0].name) || dataStreams[0] }, } ); - - onClose({ hasDeletedDataStreams }); - notificationService.showSuccessToast(successMessage); - } - - if (error || (errors && errors.length)) { - const hasMultipleErrors = - (errors && errors.length > 1) || (error && dataStreams.length > 1); - - const errorMessage = hasMultipleErrors - ? i18n.translate( - 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.multipleErrorsNotificationMessageText', - { - defaultMessage: 'Error deleting {count} data streams', - values: { - count: (errors && errors.length) || dataStreams.length, - }, - } - ) - : i18n.translate( - 'xpack.idxMgmt.deleteDataStreamsConfirmationModal.errorNotificationMessageText', - { - defaultMessage: "Error deleting data stream '{name}'", - values: { name: (errors && errors[0].name) || dataStreams[0] }, - } - ); - - notificationService.showDangerToast(errorMessage); - } - }); + notificationService.showDangerToast(errorMessage); + } + }) + .finally(() => setLoading(false)); }; return ( @@ -107,6 +112,7 @@ export const DeleteDataStreamConfirmationModal: React.FunctionComponent = values={{ dataStreamsCount }} /> } + isLoading={isLoading} > Date: Thu, 2 Mar 2023 07:45:27 -0700 Subject: [PATCH 118/131] Update babel to ^7.21.2 (main) (#152569) 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.21.1` -> `^7.21.2`](https://renovatebot.com/diffs/npm/@babel%2fparser/7.21.2/7.21.2) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.2/compatibility-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2fparser/7.21.2/confidence-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/traverse](https://babel.dev/docs/en/next/babel-traverse) ([source](https://togithub.com/babel/babel)) | [`^7.21.0` -> `^7.21.2`](https://renovatebot.com/diffs/npm/@babel%2ftraverse/7.21.2/7.21.2) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.2/compatibility-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2ftraverse/7.21.2/confidence-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | | [@babel/types](https://babel.dev/docs/en/next/babel-types) ([source](https://togithub.com/babel/babel)) | [`^7.21.0` -> `^7.21.2`](https://renovatebot.com/diffs/npm/@babel%2ftypes/7.21.2/7.21.2) | [![age](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.2/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.2/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.2/compatibility-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/@babel%2ftypes/7.21.2/confidence-slim/7.21.2)](https://docs.renovatebot.com/merge-confidence/) | --- ### 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 these updates 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> --- package.json | 6 +++--- yarn.lock | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index fab59387cb39d..af678557e64ed 100644 --- a/package.json +++ b/package.json @@ -942,7 +942,7 @@ "@babel/eslint-plugin": "^7.19.1", "@babel/generator": "^7.21.1", "@babel/helper-plugin-utils": "^7.20.2", - "@babel/parser": "^7.21.1", + "@babel/parser": "^7.21.2", "@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", @@ -954,8 +954,8 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.0", "@babel/register": "^7.21.0", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2", "@bazel/ibazel": "^0.16.2", "@bazel/typescript": "4.6.2", "@cypress/code-coverage": "^3.10.0", diff --git a/yarn.lock b/yarn.lock index 99077868338aa..40dd3c35c1259 100644 --- a/yarn.lock +++ b/yarn.lock @@ -393,7 +393,7 @@ 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.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.1", "@babel/parser@^7.21.2": +"@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.7", "@babel/parser@^7.21.0", "@babel/parser@^7.21.2": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.2.tgz#dacafadfc6d7654c3051a66d6fe55b6cb2f2a0b3" integrity sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ== From 5250d859f427d3e553bf5c625dd83241c6e7dcaa Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Thu, 2 Mar 2023 18:48:24 +0400 Subject: [PATCH 119/131] [Enterprise Search] Change Azure Cloud Storage to Azure Blob Storage (#152566) ## Summary This fixes the name we'd used for our Azure connector: it's Azure Blob Storage, not Azure Cloud Storage. --- .../source_icons/{azure_cloud.svg => azure_blob.svg} | 0 .../plugins/enterprise_search/server/integrations.ts | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) rename x-pack/plugins/enterprise_search/public/assets/source_icons/{azure_cloud.svg => azure_blob.svg} (100%) diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/azure_cloud.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/azure_blob.svg similarity index 100% rename from x-pack/plugins/enterprise_search/public/assets/source_icons/azure_cloud.svg rename to x-pack/plugins/enterprise_search/public/assets/source_icons/azure_blob.svg diff --git a/x-pack/plugins/enterprise_search/server/integrations.ts b/x-pack/plugins/enterprise_search/server/integrations.ts index b7d1516764187..94b12b35d4120 100644 --- a/x-pack/plugins/enterprise_search/server/integrations.ts +++ b/x-pack/plugins/enterprise_search/server/integrations.ts @@ -617,14 +617,14 @@ export const registerEnterpriseSearchIntegrations = ( }); customIntegrations.registerCustomIntegration({ - id: 'azure_cloud_storage', - title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.azureCloud', { - defaultMessage: 'Azure Cloud Storage', + id: 'azure_blob_storage', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.azureBlob', { + defaultMessage: 'Azure Blob Storage', }), description: i18n.translate( - 'xpack.enterpriseSearch.workplaceSearch.integrations.azureCloudDescription', + 'xpack.enterpriseSearch.workplaceSearch.integrations.azureBlobDescription', { - defaultMessage: 'Search over your content on Azure Cloud Storage with Enterprise Search.', + defaultMessage: 'Search over your content on Azure Blob Storage with Enterprise Search.', } ), categories: ['enterprise_search', 'elastic_stack', 'custom'], @@ -632,7 +632,7 @@ export const registerEnterpriseSearchIntegrations = ( icons: [ { type: 'svg', - src: http.basePath.prepend('/plugins/enterpriseSearch/assets/source_icons/azure_cloud.svg'), + src: http.basePath.prepend('/plugins/enterpriseSearch/assets/source_icons/azure_blob.svg'), }, ], shipper: 'enterprise_search', From 35008c955ee677efaed0b1977826f0221eb55f75 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Thu, 2 Mar 2023 09:49:14 -0500 Subject: [PATCH 120/131] [APM] Adds service map dsl to synthtrace (#152526) Adds `serviceMap` helper to generate transaction and spans in synthtrace by defining a set of traces from which a service map can be rendered. This can be considered a follow-up to https://github.com/elastic/kibana/pull/149900 where synthtrace was used to generate service maps for api integration tests. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-apm-synthtrace-client/index.ts | 1 + .../src/lib/dsl/service_map.test.ts | 278 ++++++++++++++++++ .../src/lib/dsl/service_map.ts | 156 ++++++++++ .../src/types/agent_names.ts | 37 +++ .../src/scenarios/service_map.ts | 153 ++++------ packages/kbn-apm-synthtrace/tsconfig.json | 1 - .../service_maps_kuery_filter.spec.ts | 45 ++- 7 files changed, 548 insertions(+), 123 deletions(-) create mode 100644 packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.test.ts create mode 100644 packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.ts create mode 100644 packages/kbn-apm-synthtrace-client/src/types/agent_names.ts diff --git a/packages/kbn-apm-synthtrace-client/index.ts b/packages/kbn-apm-synthtrace-client/index.ts index 82f8efe28b40a..1868cb188582e 100644 --- a/packages/kbn-apm-synthtrace-client/index.ts +++ b/packages/kbn-apm-synthtrace-client/index.ts @@ -20,6 +20,7 @@ export type { } from './src/lib/apm/mobile_device'; export { httpExitSpan } from './src/lib/apm/span'; export { DistributedTrace } from './src/lib/dsl/distributed_trace_client'; +export { serviceMap } from './src/lib/dsl/service_map'; export type { Fields } from './src/lib/entity'; export type { Serializable } from './src/lib/serializable'; export { timerange } from './src/lib/timerange'; diff --git a/packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.test.ts b/packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.test.ts new file mode 100644 index 0000000000000..90078f584c172 --- /dev/null +++ b/packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.test.ts @@ -0,0 +1,278 @@ +/* + * Copyright 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 { pick } from 'lodash'; +import { ApmFields } from '../apm/apm_fields'; +import { BaseSpan } from '../apm/base_span'; +import { serviceMap, ServiceMapOpts } from './service_map'; + +describe('serviceMap', () => { + const TIMESTAMP = 1677693600000; + + describe('Basic definition', () => { + const BASIC_SERVICE_MAP_OPTS: ServiceMapOpts = { + services: [ + 'frontend-rum', + 'frontend-node', + 'advertService', + 'checkoutService', + 'cartService', + 'paymentService', + 'productCatalogService', + ], + definePaths([rum, node, adv, chk, cart, pay, prod]) { + return [ + [rum, node, adv, 'elasticsearch'], + [rum, node, cart, 'redis'], + [rum, node, chk, pay], + [chk, cart, 'redis'], + [rum, node, prod, 'elasticsearch'], + [chk, prod], + ]; + }, + }; + + it('should create an accurate set of trace paths', () => { + const serviceMapGenerator = serviceMap(BASIC_SERVICE_MAP_OPTS); + const transactions = serviceMapGenerator(TIMESTAMP); + expect(transactions.map(getTracePathLabel)).toMatchInlineSnapshot(` + Array [ + "frontend-rum → frontend-node → advertService → elasticsearch", + "frontend-rum → frontend-node → cartService → redis", + "frontend-rum → frontend-node → checkoutService → paymentService", + "checkoutService → cartService → redis", + "frontend-rum → frontend-node → productCatalogService → elasticsearch", + "checkoutService → productCatalogService", + ] + `); + }); + + it('should use a default agent name if not defined', () => { + const serviceMapGenerator = serviceMap(BASIC_SERVICE_MAP_OPTS); + const transactions = serviceMapGenerator(TIMESTAMP); + const traceDocs = transactions.flatMap(getTraceDocsSubset); + for (const doc of traceDocs) { + expect(doc).toHaveProperty(['agent.name'], 'nodejs'); + } + }); + + it('should use a default transaction/span names if not defined', () => { + const serviceMapGenerator = serviceMap(BASIC_SERVICE_MAP_OPTS); + const transactions = serviceMapGenerator(TIMESTAMP); + const traceDocs = transactions.map(getTraceDocsSubset); + for (let i = 0; i < traceDocs.length; i++) { + for (const doc of traceDocs[i]) { + const serviceName = doc['service.name']; + if (doc['processor.event'] === 'transaction') { + expect(doc).toHaveProperty(['transaction.name'], `GET /api/${serviceName}/${i}`); + } + if (doc['processor.event'] === 'span') { + if (doc['span.type'] === 'db') { + switch (doc['span.subtype']) { + case 'elasticsearch': + expect(doc).toHaveProperty(['span.name'], `GET ad-*/_search`); + break; + case 'redis': + expect(doc).toHaveProperty(['span.name'], `INCR item:i012345:count`); + break; + case 'sqlite': + expect(doc).toHaveProperty(['span.name'], `SELECT * FROM items`); + break; + } + } else { + expect(doc).toHaveProperty(['span.name'], `GET /api/${serviceName}/${i}`); + } + } + } + } + }); + + it('should create one parent transaction per trace', () => { + const serviceMapGenerator = serviceMap(BASIC_SERVICE_MAP_OPTS); + const transactions = serviceMapGenerator(TIMESTAMP); + const traces = transactions.map(getTraceDocsSubset); + for (const traceDocs of traces) { + const [transaction, ...spans] = traceDocs; + expect(transaction).toHaveProperty(['processor.event'], 'transaction'); + expect( + spans.every(({ 'processor.event': processorEvent }) => processorEvent === 'span') + ).toBe(true); + } + }); + }); + describe('Detailed definition', () => { + const DETAILED_SERVICE_MAP_OPTS: ServiceMapOpts = { + services: [ + { 'frontend-rum': 'rum-js' }, + { 'frontend-node': 'nodejs' }, + { advertService: 'java' }, + { checkoutService: 'go' }, + { cartService: 'dotnet' }, + { paymentService: 'nodejs' }, + { productCatalogService: 'go' }, + ], + definePaths([rum, node, adv, chk, cart, pay, prod]) { + return [ + [ + [rum, 'fetchAd'], + [node, 'GET /nodejs/adTag'], + [adv, 'APIRestController#getAd'], + ['elasticsearch', 'GET ad-*/_search'], + ], + [ + [rum, 'AddToCart'], + [node, 'POST /nodejs/addToCart'], + [cart, 'POST /dotnet/reserveProduct'], + ['redis', 'DECR inventory:i012345:stock'], + ], + { + path: [ + [rum, 'Checkout'], + [node, 'POST /nodejs/placeOrder'], + [chk, 'POST /go/placeOrder'], + [pay, 'POST /nodejs/processPayment'], + ], + transaction: (t) => t.defaults({ 'labels.name': 'transaction hook test' }), + }, + [ + [chk, 'POST /go/clearCart'], + [cart, 'PUT /dotnet/cart/c12345/reset'], + ['redis', 'INCR inventory:i012345:stock'], + ], + [ + [rum, 'ProductDashboard'], + [node, 'GET /nodejs/products'], + [prod, 'GET /go/product-catalog'], + ['elasticsearch', 'GET product-*/_search'], + ], + [ + [chk, 'PUT /go/update-inventory'], + [prod, 'PUT /go/product/i012345'], + ], + [pay], + ]; + }, + }; + + const SERVICE_AGENT_MAP: Record = { + 'frontend-rum': 'rum-js', + 'frontend-node': 'nodejs', + advertService: 'java', + checkoutService: 'go', + cartService: 'dotnet', + paymentService: 'nodejs', + productCatalogService: 'go', + }; + + it('should use the defined agent name for a given service', () => { + const serviceMapGenerator = serviceMap(DETAILED_SERVICE_MAP_OPTS); + const transactions = serviceMapGenerator(TIMESTAMP); + const traceDocs = transactions.flatMap(getTraceDocsSubset); + for (const doc of traceDocs) { + if (!(doc['service.name']! in SERVICE_AGENT_MAP)) { + throw new Error(`Unexpected service name '${doc['service.name']}' found`); + } + + expect(doc).toHaveProperty(['agent.name'], SERVICE_AGENT_MAP[doc['service.name']!]); + } + }); + + it('should use the defined transaction/span names for each trace document', () => { + const serviceMapGenerator = serviceMap(DETAILED_SERVICE_MAP_OPTS); + const transactions = serviceMapGenerator(TIMESTAMP); + const traceDocs = transactions.map((transaction) => { + return getTraceDocsSubset(transaction).map( + ({ 'span.name': spanName, 'transaction.name': transactionName }) => + transactionName || spanName + ); + }); + expect(traceDocs).toMatchInlineSnapshot(` + Array [ + Array [ + "fetchAd", + "fetchAd", + "GET /nodejs/adTag", + "APIRestController#getAd", + "GET ad-*/_search", + ], + Array [ + "AddToCart", + "AddToCart", + "POST /nodejs/addToCart", + "POST /dotnet/reserveProduct", + "DECR inventory:i012345:stock", + ], + Array [ + "Checkout", + "Checkout", + "POST /nodejs/placeOrder", + "POST /go/placeOrder", + "POST /nodejs/processPayment", + ], + Array [ + "POST /go/clearCart", + "POST /go/clearCart", + "PUT /dotnet/cart/c12345/reset", + "INCR inventory:i012345:stock", + ], + Array [ + "ProductDashboard", + "ProductDashboard", + "GET /nodejs/products", + "GET /go/product-catalog", + "GET product-*/_search", + ], + Array [ + "PUT /go/update-inventory", + "PUT /go/update-inventory", + "PUT /go/product/i012345", + ], + Array [ + "GET /api/paymentService/6", + "GET /api/paymentService/6", + ], + ] + `); + }); + + it('should apply the transaction hook function if defined', () => { + const serviceMapGenerator = serviceMap(DETAILED_SERVICE_MAP_OPTS); + const transactions = serviceMapGenerator(TIMESTAMP); + expect(transactions[2].fields['labels.name']).toBe('transaction hook test'); + }); + }); +}); + +function getTraceDocsSubset(transaction: BaseSpan): ApmFields[] { + const subsetFields = pick(transaction.fields, [ + 'processor.event', + 'service.name', + 'agent.name', + 'transaction.name', + 'span.name', + 'span.type', + 'span.subtype', + 'span.destination.service.resource', + ]); + + const children = transaction.getChildren(); + if (children) { + const childFields = children.flatMap((child) => getTraceDocsSubset(child)); + return [subsetFields, ...childFields]; + } + return [subsetFields]; +} + +function getTracePathLabel(transaction: BaseSpan) { + const traceDocs = getTraceDocsSubset(transaction); + const traceSpans = traceDocs.filter((doc) => doc['processor.event'] === 'span'); + const spanLabels = traceSpans.map((span) => + span['span.type'] === 'db' ? span['span.subtype'] : span['service.name'] + ); + return spanLabels.join(' → '); +} diff --git a/packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.ts b/packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.ts new file mode 100644 index 0000000000000..4c91352b11d02 --- /dev/null +++ b/packages/kbn-apm-synthtrace-client/src/lib/dsl/service_map.ts @@ -0,0 +1,156 @@ +/* + * Copyright 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 { AgentName } from '../../types/agent_names'; +import { apm } from '../apm'; +import { Instance } from '../apm/instance'; +import { elasticsearchSpan, redisSpan, sqliteSpan, Span } from '../apm/span'; +import { Transaction } from '../apm/transaction'; + +const ENVIRONMENT = 'Synthtrace: service_map'; + +function service(serviceName: string, agentName: AgentName, environment?: string) { + return apm + .service({ name: serviceName, environment: environment || ENVIRONMENT, agentName }) + .instance(serviceName); +} + +type DbSpan = 'elasticsearch' | 'redis' | 'sqlite'; +type ServiceMapNode = Instance | DbSpan; +type TransactionName = string; +type TraceItem = ServiceMapNode | [ServiceMapNode, TransactionName]; +type TracePath = TraceItem[]; + +function getTraceItem(traceItem: TraceItem) { + if (Array.isArray(traceItem)) { + const transactionName = traceItem[1]; + if (typeof traceItem[0] === 'string') { + const dbSpan = traceItem[0]; + return { dbSpan, transactionName, serviceInstance: undefined }; + } else { + const serviceInstance = traceItem[0]; + return { dbSpan: undefined, transactionName, serviceInstance }; + } + } else if (typeof traceItem === 'string') { + const dbSpan = traceItem; + return { dbSpan, transactionName: undefined, serviceInstance: undefined }; + } else { + const serviceInstance = traceItem; + return { dbSpan: undefined, transactionName: undefined, serviceInstance }; + } +} + +function getTransactionName( + transactionName: string | undefined, + serviceInstance: Instance, + index: number +) { + return transactionName || `GET /api/${serviceInstance.fields['service.name']}/${index}`; +} + +function getChildren( + childTraceItems: TracePath, + parentServiceInstance: Instance, + timestamp: number, + index: number +): Span[] { + if (childTraceItems.length === 0) { + return []; + } + const [first, ...rest] = childTraceItems; + const { dbSpan, serviceInstance, transactionName } = getTraceItem(first); + if (dbSpan) { + switch (dbSpan) { + case 'elasticsearch': + return [ + parentServiceInstance + .span(elasticsearchSpan(transactionName || 'GET ad-*/_search')) + .timestamp(timestamp) + .duration(1000), + ]; + case 'redis': + return [ + parentServiceInstance + .span(redisSpan(transactionName || 'INCR item:i012345:count')) + .timestamp(timestamp) + .duration(1000), + ]; + case 'sqlite': + return [ + parentServiceInstance + .span(sqliteSpan(transactionName || 'SELECT * FROM items')) + .timestamp(timestamp) + .duration(1000), + ]; + } + } + const childSpan = serviceInstance + .span({ + spanName: getTransactionName(transactionName, serviceInstance, index), + spanType: 'app', + }) + .timestamp(timestamp) + .duration(1000) + .children(...getChildren(rest, serviceInstance, timestamp, index)); + if (rest[0]) { + const next = getTraceItem(rest[0]); + if (next.serviceInstance) { + return [childSpan.destination(next.serviceInstance.fields['service.name']!)]; + } + } + return [childSpan]; +} + +interface TracePathOpts { + path: TracePath; + transaction?: (transaction: Transaction) => Transaction; +} +type PathDef = TracePath | TracePathOpts; +export interface ServiceMapOpts { + services: Array; + definePaths: (services: Instance[]) => PathDef[]; + environment?: string; +} + +export function serviceMap(options: ServiceMapOpts) { + const serviceInstances = options.services.map((s) => { + if (typeof s === 'string') { + return service(s, 'nodejs', options.environment); + } + return service(Object.keys(s)[0], Object.values(s)[0], options.environment); + }); + return (timestamp: number) => { + const tracePaths = options.definePaths(serviceInstances); + return tracePaths.map((traceDef, index) => { + const tracePath = 'path' in traceDef ? traceDef.path : traceDef; + const [first] = tracePath; + + const firstTraceItem = getTraceItem(first); + if (firstTraceItem.serviceInstance === undefined) { + throw new Error('First trace item must be a service instance'); + } + const transactionName = getTransactionName( + firstTraceItem.transactionName, + firstTraceItem.serviceInstance, + index + ); + + const transaction = firstTraceItem.serviceInstance + .transaction({ transactionName, transactionType: 'request' }) + .timestamp(timestamp) + .duration(1000) + .children(...getChildren(tracePath, firstTraceItem.serviceInstance, timestamp, index)); + + if ('transaction' in traceDef && traceDef.transaction) { + return traceDef.transaction(transaction); + } + + return transaction; + }); + }; +} diff --git a/packages/kbn-apm-synthtrace-client/src/types/agent_names.ts b/packages/kbn-apm-synthtrace-client/src/types/agent_names.ts new file mode 100644 index 0000000000000..d9e3a371e0e87 --- /dev/null +++ b/packages/kbn-apm-synthtrace-client/src/types/agent_names.ts @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +type ElasticAgentName = + | 'go' + | 'java' + | 'js-base' + | 'iOS/swift' + | 'rum-js' + | 'nodejs' + | 'python' + | 'dotnet' + | 'ruby' + | 'php' + | 'android/java'; + +type OpenTelemetryAgentName = + | 'otlp' + | 'opentelemetry/cpp' + | 'opentelemetry/dotnet' + | 'opentelemetry/erlang' + | 'opentelemetry/go' + | 'opentelemetry/java' + | 'opentelemetry/nodejs' + | 'opentelemetry/php' + | 'opentelemetry/python' + | 'opentelemetry/ruby' + | 'opentelemetry/swift' + | 'opentelemetry/webjs'; + +// Unable to reference AgentName from '@kbn/apm-plugin/typings/es_schemas/ui/fields/agent' due to circular reference +export type AgentName = ElasticAgentName | OpenTelemetryAgentName; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts b/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts index 41e499320fd50..f39d4bdd1e221 100644 --- a/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts +++ b/packages/kbn-apm-synthtrace/src/scenarios/service_map.ts @@ -6,116 +6,71 @@ * Side Public License, v 1. */ -import { apm, ApmFields, Instance } from '@kbn/apm-synthtrace-client'; -import { Transaction } from '@kbn/apm-synthtrace-client/src/lib/apm/transaction'; -import { AgentName } from '@kbn/apm-plugin/typings/es_schemas/ui/fields/agent'; +import { ApmFields, serviceMap } from '@kbn/apm-synthtrace-client'; import { Scenario } from '../cli/scenario'; import { RunOptions } from '../cli/utils/parse_run_cli_flags'; import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; -const ENVIRONMENT = getSynthtraceEnvironment(__filename); - -function generateTrace( - timestamp: number, - transactionName: string, - order: Instance[], - db?: 'elasticsearch' | 'redis' -) { - return order - .concat() - .reverse() - .reduce((prev, instance, index) => { - const invertedIndex = order.length - index - 1; - - const duration = 50; - const time = timestamp + invertedIndex * 10; - - const transaction: Transaction = instance - .transaction({ transactionName }) - .timestamp(time) - .duration(duration); - - if (prev) { - const next = order[invertedIndex + 1].fields['service.name']!; - transaction.children( - instance - .span({ spanName: `GET ${next}/api`, spanType: 'external', spanSubtype: 'http' }) - .destination(next) - .duration(duration) - .timestamp(time + 1) - .children(prev) - ); - } else if (db) { - transaction.children( - instance - .span({ spanName: db, spanType: 'db', spanSubtype: db }) - .destination(db) - .duration(duration) - .timestamp(time + 1) - ); - } - - return transaction; - }, undefined)!; -} - -function service(serviceName: string, agentName: AgentName) { - return apm - .service({ name: serviceName, environment: ENVIRONMENT, agentName }) - .instance(serviceName); -} +const environment = getSynthtraceEnvironment(__filename); const scenario: Scenario = async (runOptions: RunOptions) => { return { generate: ({ range }) => { - const frontendRum = service('frontend-rum', 'rum-js'); - const frontendNode = service('frontend-node', 'nodejs'); - const advertService = service('advertService', 'java'); - const checkoutService = service('checkoutService', 'go'); - const cartService = service('cartService', 'dotnet'); - const paymentService = service('paymentService', 'nodejs'); - const productCatalogService = service('productCatalogService', 'go'); return range .interval('1s') .rate(3) - .generator((timestamp) => { - return [ - generateTrace( - timestamp, - 'GET /api/adTag', - [frontendRum, frontendNode, advertService], - 'elasticsearch' - ), - generateTrace( - timestamp, - 'POST /api/addToCart', - [frontendRum, frontendNode, cartService], - 'redis' - ), - generateTrace(timestamp, 'POST /api/checkout', [ - frontendRum, - frontendNode, - checkoutService, - paymentService, - ]), - generateTrace( - timestamp, - 'DELETE /api/clearCart', - [checkoutService, cartService], - 'redis' - ), - generateTrace( - timestamp, - 'GET /api/products', - [frontendRum, frontendNode, productCatalogService], - 'elasticsearch' - ), - generateTrace(timestamp, 'PUT /api/updateInventory', [ - checkoutService, - productCatalogService, - ]), - ]; - }); + .generator( + serviceMap({ + services: [ + { 'frontend-rum': 'rum-js' }, + { 'frontend-node': 'nodejs' }, + { advertService: 'java' }, + { checkoutService: 'go' }, + { cartService: 'dotnet' }, + { paymentService: 'nodejs' }, + { productCatalogService: 'go' }, + ], + environment, + definePaths([rum, node, adv, chk, cart, pay, prod]) { + return [ + [ + [rum, 'fetchAd'], + [node, 'GET /nodejs/adTag'], + [adv, 'APIRestController#getAd'], + ['elasticsearch', 'GET ad-*/_search'], + ], + [ + [rum, 'AddToCart'], + [node, 'POST /nodejs/addToCart'], + [cart, 'POST /dotnet/reserveProduct'], + ['redis', 'DECR inventory:i012345:stock'], + ], + [ + [rum, 'Checkout'], + [node, 'POST /nodejs/placeOrder'], + [chk, 'POST /go/placeOrder'], + [pay, 'POST /nodejs/processPayment'], + ], + [ + [chk, 'POST /go/clearCart'], + [cart, 'PUT /dotnet/cart/c12345/reset'], + ['redis', 'INCR inventory:i012345:stock'], + ], + [ + [rum, 'ProductDashboard'], + [node, 'GET /nodejs/products'], + [prod, 'GET /go/product-catalog'], + ['elasticsearch', 'GET product-*/_search'], + ], + [ + [chk, 'PUT /go/update-inventory'], + [prod, 'PUT /go/product/i012345'], + ], + [pay], + ]; + }, + }) + ); }, }; }; diff --git a/packages/kbn-apm-synthtrace/tsconfig.json b/packages/kbn-apm-synthtrace/tsconfig.json index 3db0ec03f6f4d..22ff0442879ab 100644 --- a/packages/kbn-apm-synthtrace/tsconfig.json +++ b/packages/kbn-apm-synthtrace/tsconfig.json @@ -8,7 +8,6 @@ "kbn_references": [ "@kbn/datemath", "@kbn/apm-synthtrace-client", - "@kbn/apm-plugin" ], "exclude": [ "target/**/*", diff --git a/x-pack/test/apm_api_integration/tests/service_maps/service_maps_kuery_filter.spec.ts b/x-pack/test/apm_api_integration/tests/service_maps/service_maps_kuery_filter.spec.ts index e2dcafc0af815..7a454ad5c9687 100644 --- a/x-pack/test/apm_api_integration/tests/service_maps/service_maps_kuery_filter.spec.ts +++ b/x-pack/test/apm_api_integration/tests/service_maps/service_maps_kuery_filter.spec.ts @@ -5,14 +5,13 @@ * 2.0. */ import expect from '@kbn/expect'; -import { apm, timerange } from '@kbn/apm-synthtrace-client'; +import { timerange, serviceMap } from '@kbn/apm-synthtrace-client'; import { APIClientRequestParamsOf, APIReturnType, } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; import { RecursivePartial } from '@kbn/apm-plugin/typings/common'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { generateTrace } from '../traces/generate_trace'; export default function ApiTest({ getService }: FtrProviderContext) { const registry = getService('registry'); @@ -44,30 +43,30 @@ export default function ApiTest({ getService }: FtrProviderContext) { registry.when('Service map', { config: 'trial', archives: [] }, () => { describe('optional kuery param', () => { before(async () => { - const go = apm - .service({ name: 'synthbeans-go', environment: 'test', agentName: 'go' }) - .instance('synthbeans-go'); - const java = apm - .service({ name: 'synthbeans-java', environment: 'test', agentName: 'java' }) - .instance('synthbeans-java'); - const node = apm - .service({ name: 'synthbeans-node', environment: 'test', agentName: 'nodejs' }) - .instance('synthbeans-node'); - const events = timerange(start, end) .interval('15m') .rate(1) - .generator((timestamp) => { - return [ - generateTrace(timestamp, [go, java]), - generateTrace(timestamp, [java, go], 'redis'), - generateTrace(timestamp, [node], 'redis'), - generateTrace(timestamp, [node, java, go], 'elasticsearch').defaults({ - 'labels.name': 'node-java-go-es', - }), - generateTrace(timestamp, [go, node, java]), - ]; - }); + .generator( + serviceMap({ + services: [ + { 'synthbeans-go': 'go' }, + { 'synthbeans-java': 'java' }, + { 'synthbeans-node': 'nodejs' }, + ], + definePaths([go, java, node]) { + return [ + [go, java], + [java, go, 'redis'], + [node, 'redis'], + { + path: [node, java, go, 'elasticsearch'], + transaction: (t) => t.defaults({ 'labels.name': 'node-java-go-es' }), + }, + [go, node, java], + ]; + }, + }) + ); await synthtraceEsClient.index(events); }); From daaa7ea1ead8646cda58c01b1655b982ed31ea54 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 2 Mar 2023 07:49:56 -0700 Subject: [PATCH 121/131] Update dependency terser to ^5.16.5 (main) (#152573) 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.4` -> `^5.16.5`](https://renovatebot.com/diffs/npm/terser/5.16.5/5.16.5) | [![age](https://badges.renovateapi.com/packages/npm/terser/5.16.5/age-slim)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://badges.renovateapi.com/packages/npm/terser/5.16.5/adoption-slim)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://badges.renovateapi.com/packages/npm/terser/5.16.5/compatibility-slim/5.16.5)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://badges.renovateapi.com/packages/npm/terser/5.16.5/confidence-slim/5.16.5)](https://docs.renovatebot.com/merge-confidence/) | --- ### 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> --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index af678557e64ed..c81b11551cff8 100644 --- a/package.json +++ b/package.json @@ -1448,7 +1448,7 @@ "svgo": "^2.8.0", "tape": "^5.0.1", "tempy": "^0.3.0", - "terser": "^5.16.4", + "terser": "^5.16.5", "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 40dd3c35c1259..dd63058020b48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -27126,7 +27126,7 @@ 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.4, terser@^5.3.4, terser@^5.9.0: +terser@^5.14.1, terser@^5.16.5, terser@^5.3.4, terser@^5.9.0: version "5.16.5" resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.5.tgz#1c285ca0655f467f92af1bbab46ab72d1cb08e5a" integrity sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg== From 446f04d7b27b46e4da11e6b5d16696190532c570 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Thu, 2 Mar 2023 15:10:46 +0000 Subject: [PATCH 122/131] [ML] Fixing single to multi metric wizard redirect (#152547) Typo in redirect path introduced in [this PR](https://github.com/elastic/kibana/pull/149590) --- .../application/routing/routes/new_job/wizard.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx b/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx index 4300d73ae010e..a60fbae514e7f 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/new_job/wizard.tsx @@ -127,14 +127,13 @@ export const multiMetricRouteFactory = ( // redirect route to reset the job wizard when converting to multi metric job export const multiMetricRouteFactoryRedirect = (): MlRoute => ({ path: createPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_MULTI_METRIC), - render: (props) => ( - - ), + render: (props) => { + return ( + + ); + }, breadcrumbs: [], }); From 0c5fb37670139e70aeab29074c5296c503c36629 Mon Sep 17 00:00:00 2001 From: Maja Grubic Date: Thu, 2 Mar 2023 16:12:32 +0100 Subject: [PATCH 123/131] [Graph] Replace SavedObjectsFinder component (#152432) ## Summary This PR replaces the `SavedObjectsFinder` component from `saved_objects` plugin with the one in `saved_objects_finder` plugin. ### 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/))~ ~- [ ] 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))~ - [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> --- src/plugins/unified_search/kibana.jsonc | 3 ++- src/plugins/unified_search/public/types.ts | 2 ++ src/plugins/unified_search/tsconfig.json | 1 + x-pack/plugins/graph/kibana.jsonc | 4 +++- x-pack/plugins/graph/public/application.tsx | 2 ++ .../graph/public/apps/workspace_route.tsx | 4 +++- .../components/guidance_panel/guidance_panel.tsx | 4 ++-- .../graph/public/components/search_bar.test.tsx | 2 ++ .../graph/public/components/search_bar.tsx | 8 ++++++-- .../graph/public/components/source_picker.tsx | 16 +++++++++++----- x-pack/plugins/graph/public/plugin.ts | 3 +++ .../graph/public/services/source_modal.tsx | 6 +++++- x-pack/plugins/graph/tsconfig.json | 2 ++ 13 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/plugins/unified_search/kibana.jsonc b/src/plugins/unified_search/kibana.jsonc index 008b9d9fe03d2..5f146723b7c2e 100644 --- a/src/plugins/unified_search/kibana.jsonc +++ b/src/plugins/unified_search/kibana.jsonc @@ -17,7 +17,8 @@ "dataViews", "data", "uiActions", - "screenshotMode" + "screenshotMode", + "savedObjectsManagement" ], "optionalPlugins": [ "usageCollection" diff --git a/src/plugins/unified_search/public/types.ts b/src/plugins/unified_search/public/types.ts index 557c31865a417..66abc195b5b19 100755 --- a/src/plugins/unified_search/public/types.ts +++ b/src/plugins/unified_search/public/types.ts @@ -16,6 +16,7 @@ import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collectio import { Query, AggregateQuery } from '@kbn/es-query'; import { CoreStart, DocLinksStart } from '@kbn/core/public'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { AutocompleteSetup, AutocompleteStart } from './autocomplete'; import type { IndexPatternSelectProps, StatefulSearchBarProps } from '.'; import type { FiltersBuilderProps } from './filters_builder/filters_builder'; @@ -92,4 +93,5 @@ export interface IUnifiedSearchPluginServices extends Partial { dataViews: DataViewsPublicPluginStart; dataViewEditor: DataViewEditorStart; usageCollection?: UsageCollectionStart; + savedObjectsManagement: SavedObjectsManagementPluginStart; } diff --git a/src/plugins/unified_search/tsconfig.json b/src/plugins/unified_search/tsconfig.json index 0a4ab525d04b7..d11390cf0d18a 100644 --- a/src/plugins/unified_search/tsconfig.json +++ b/src/plugins/unified_search/tsconfig.json @@ -38,6 +38,7 @@ "@kbn/utility-types-jest", "@kbn/react-field", "@kbn/ui-theme", + "@kbn/saved-objects-management-plugin", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/graph/kibana.jsonc b/x-pack/plugins/graph/kibana.jsonc index c47a12d71cc92..5c85742b492a2 100644 --- a/x-pack/plugins/graph/kibana.jsonc +++ b/x-pack/plugins/graph/kibana.jsonc @@ -16,7 +16,9 @@ "navigation", "savedObjects", "unifiedSearch", - "inspector" + "inspector", + "savedObjectsManagement", + "savedObjectsFinder", ], "optionalPlugins": [ "home", diff --git a/x-pack/plugins/graph/public/application.tsx b/x-pack/plugins/graph/public/application.tsx index bbb14a96ac5eb..90cbc2b88b19f 100644 --- a/x-pack/plugins/graph/public/application.tsx +++ b/x-pack/plugins/graph/public/application.tsx @@ -35,6 +35,7 @@ import('./font_awesome'); import { SavedObjectsStart } from '@kbn/saved-objects-plugin/public'; import { SpacesApi } from '@kbn/spaces-plugin/public'; import { KibanaThemeProvider, toMountPoint } from '@kbn/kibana-react-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { GraphSavePolicy } from './types'; import { graphRouter } from './router'; import { checkLicense } from '../common/check_license'; @@ -72,6 +73,7 @@ export interface GraphDependencies { history: ScopedHistory; spaces?: SpacesApi; inspect: InspectorPublicPluginStart; + savedObjectsManagement: SavedObjectsManagementPluginStart; } export type GraphServices = Omit; diff --git a/x-pack/plugins/graph/public/apps/workspace_route.tsx b/x-pack/plugins/graph/public/apps/workspace_route.tsx index 75aafeb1a7868..8fcff177d054b 100644 --- a/x-pack/plugins/graph/public/apps/workspace_route.tsx +++ b/x-pack/plugins/graph/public/apps/workspace_route.tsx @@ -43,6 +43,7 @@ export const WorkspaceRoute = ({ spaces, indexPatterns: getIndexPatternProvider, inspect, + savedObjectsManagement, }, }: WorkspaceRouteProps) => { /** @@ -70,9 +71,10 @@ export const WorkspaceRoute = ({ storage, data, unifiedSearch, + savedObjectsManagement, ...coreStart, }), - [coreStart, data, storage, unifiedSearch] + [coreStart, data, storage, unifiedSearch, savedObjectsManagement] ); const { loading, requestAdapter, callNodeProxy, callSearchNodeProxy, handleSearchQueryError } = diff --git a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx index 81be2e191516a..6b6c06dbc02ba 100644 --- a/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx +++ b/x-pack/plugins/graph/public/components/guidance_panel/guidance_panel.tsx @@ -77,7 +77,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) { const kibana = useKibana(); const { services, overlays } = kibana; - const { http, uiSettings, application, data } = services; + const { http, uiSettings, application, data, savedObjectsManagement } = services; const [hasDataViews, setHasDataViews] = useState(true); useEffect(() => { @@ -90,7 +90,7 @@ function GuidancePanelComponent(props: GuidancePanelProps) { if (!overlays || !application) return null; const onOpenDatasourcePicker = () => { - openSourceModal({ overlays, http, uiSettings }, onIndexPatternSelected); + openSourceModal({ overlays, http, uiSettings, savedObjectsManagement }, onIndexPatternSelected); }; let content = ( diff --git a/x-pack/plugins/graph/public/components/search_bar.test.tsx b/x-pack/plugins/graph/public/components/search_bar.test.tsx index ca21e16c0fb36..e1ee8cb9d6331 100644 --- a/x-pack/plugins/graph/public/components/search_bar.test.tsx +++ b/x-pack/plugins/graph/public/components/search_bar.test.tsx @@ -29,6 +29,7 @@ import { GraphStore, setDatasource, submitSearchSaga } from '../state_management import { ReactWrapper } from 'enzyme'; import { createMockGraphStore } from '../state_management/mocks'; import { Provider } from 'react-redux'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; jest.mock('../services/source_modal', () => ({ openSourceModal: jest.fn() })); @@ -42,6 +43,7 @@ function getServiceMocks() { }, } as IUiSettingsClient, savedObjects: {} as SavedObjectsStart, + savedObjectsManagement: {} as SavedObjectsManagementPluginStart, notifications: {} as NotificationsStart, docLinks: { links: { diff --git a/x-pack/plugins/graph/public/components/search_bar.tsx b/x-pack/plugins/graph/public/components/search_bar.tsx index fcd5d576116d9..5bf23c1705dec 100644 --- a/x-pack/plugins/graph/public/components/search_bar.tsx +++ b/x-pack/plugins/graph/public/components/search_bar.tsx @@ -107,9 +107,9 @@ export function SearchBarComponent(props: SearchBarStateProps & SearchBarProps) notifications, http, docLinks, + savedObjectsManagement, } = services; if (!overlays) return null; - return (
    { @@ -131,7 +131,11 @@ export function SearchBarComponent(props: SearchBarStateProps & SearchBarProps) data-test-subj="graphDatasourceButton" onClick={() => { confirmWipeWorkspace( - () => openSourceModal({ overlays, http, uiSettings }, onIndexPatternSelected), + () => + openSourceModal( + { overlays, http, uiSettings, savedObjectsManagement }, + onIndexPatternSelected + ), i18n.translate('xpack.graph.clearWorkspace.confirmText', { defaultMessage: 'If you change data sources, your current fields and vertices will be reset.', diff --git a/x-pack/plugins/graph/public/components/source_picker.tsx b/x-pack/plugins/graph/public/components/source_picker.tsx index ceb165fd50840..ec227fdddc5bd 100644 --- a/x-pack/plugins/graph/public/components/source_picker.tsx +++ b/x-pack/plugins/graph/public/components/source_picker.tsx @@ -9,22 +9,28 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { CoreStart } from '@kbn/core/public'; -import { SavedObjectFinderUi } from '@kbn/saved-objects-plugin/public'; +import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { IndexPatternSavedObject } from '../types'; export interface SourcePickerProps { onIndexPatternSelected: (indexPattern: IndexPatternSavedObject) => void; http: CoreStart['http']; uiSettings: CoreStart['uiSettings']; + savedObjectsManagement: SavedObjectsManagementPluginStart; } const fixedPageSize = 8; -export function SourcePicker({ http, uiSettings, onIndexPatternSelected }: SourcePickerProps) { +export function SourcePicker({ + http, + uiSettings, + savedObjectsManagement, + onIndexPatternSelected, +}: SourcePickerProps) { return ( - { onIndexPatternSelected(indexPattern as IndexPatternSavedObject); }} diff --git a/x-pack/plugins/graph/public/plugin.ts b/x-pack/plugins/graph/public/plugin.ts index 96dac017eeabb..feca5656f73d6 100644 --- a/x-pack/plugins/graph/public/plugin.ts +++ b/x-pack/plugins/graph/public/plugin.ts @@ -28,6 +28,7 @@ import { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import type { HomePublicPluginSetup, HomePublicPluginStart } from '@kbn/home-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { SavedObjectsStart } from '@kbn/saved-objects-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { checkLicense } from '../common/check_license'; import { ConfigSchema } from '../config'; @@ -44,6 +45,7 @@ export interface GraphPluginStartDependencies { inspector: InspectorPublicPluginStart; home?: HomePublicPluginStart; spaces?: SpacesApi; + savedObjectsManagement: SavedObjectsManagementPluginStart; } export class GraphPlugin @@ -113,6 +115,7 @@ export class GraphPlugin uiSettings: core.uiSettings, spaces: pluginsStart.spaces, inspect: pluginsStart.inspector, + savedObjectsManagement: pluginsStart.savedObjectsManagement, }); }, }); diff --git a/x-pack/plugins/graph/public/services/source_modal.tsx b/x-pack/plugins/graph/public/services/source_modal.tsx index 258bb58d1e077..6da003833d1a9 100644 --- a/x-pack/plugins/graph/public/services/source_modal.tsx +++ b/x-pack/plugins/graph/public/services/source_modal.tsx @@ -8,6 +8,7 @@ import { CoreStart } from '@kbn/core/public'; import React from 'react'; import { KibanaReactOverlays } from '@kbn/kibana-react-plugin/public'; +import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { SourceModal } from '../components/source_modal'; import { IndexPatternSavedObject } from '../types'; @@ -16,17 +17,20 @@ export function openSourceModal( overlays, http, uiSettings, + savedObjectsManagement, }: { overlays: KibanaReactOverlays; http: CoreStart['http']; uiSettings: CoreStart['uiSettings']; + savedObjectsManagement: SavedObjectsManagementPluginStart; }, onSelected: (indexPattern: IndexPatternSavedObject) => void ) { const modalRef = overlays.openModal( { onSelected(indexPattern); modalRef.close(); diff --git a/x-pack/plugins/graph/tsconfig.json b/x-pack/plugins/graph/tsconfig.json index 0f9bc04b6975a..3979bb5b4d9a0 100644 --- a/x-pack/plugins/graph/tsconfig.json +++ b/x-pack/plugins/graph/tsconfig.json @@ -38,6 +38,8 @@ "@kbn/utility-types", "@kbn/react-field", "@kbn/shared-ux-router", + "@kbn/saved-objects-management-plugin", + "@kbn/saved-objects-finder-plugin", ], "exclude": [ "target/**/*", From 41f7e633a9b23108c95d51e559c586771f50fdbc Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Thu, 2 Mar 2023 08:14:59 -0700 Subject: [PATCH 124/131] [http] Adds route config option access flag to indicate if an API is public or internal (#152404) --- .../src/request.ts | 8 +++ .../src/router.mock.ts | 2 +- .../src/http_server.test.ts | 52 +++++++++++++++++++ .../src/http_server.ts | 1 + .../src/lifecycle_handlers.test.ts | 1 + .../src/lifecycle_handlers.ts | 1 + .../core-http-server/src/router/request.ts | 1 + .../http/core-http-server/src/router/route.ts | 12 +++++ .../core-version-http-server/src/example.ts | 2 +- .../src/version_http_toolkit.ts | 21 ++++++-- 10 files changed, 96 insertions(+), 5 deletions(-) diff --git a/packages/core/http/core-http-router-server-internal/src/request.ts b/packages/core/http/core-http-router-server-internal/src/request.ts index 7e8e927bd4671..26ac377c00bf3 100644 --- a/packages/core/http/core-http-router-server-internal/src/request.ts +++ b/packages/core/http/core-http-router-server-internal/src/request.ts @@ -201,6 +201,7 @@ export class CoreKibanaRequest< xsrfRequired: ((request.route?.settings as RouteOptions)?.app as KibanaRouteOptions)?.xsrfRequired ?? true, // some places in LP call KibanaRequest.from(request) manually. remove fallback to true before v8 + access: this.getAccess(request), tags: request.route?.settings?.tags || [], timeout: { payload: payloadTimeout, @@ -222,6 +223,13 @@ export class CoreKibanaRequest< options, }; } + /** infer route access from path if not declared */ + private getAccess(request: RawRequest): 'internal' | 'public' { + return ( + ((request.route?.settings as RouteOptions)?.app as KibanaRouteOptions)?.access ?? + (request.path.startsWith('/internal') ? 'internal' : 'public') + ); + } private getAuthRequired(request: RawRequest): boolean | 'optional' { if (isFakeRawRequest(request)) { diff --git a/packages/core/http/core-http-router-server-mocks/src/router.mock.ts b/packages/core/http/core-http-router-server-mocks/src/router.mock.ts index 1a3262fdf1f80..9b2d90e18640b 100644 --- a/packages/core/http/core-http-router-server-mocks/src/router.mock.ts +++ b/packages/core/http/core-http-router-server-mocks/src/router.mock.ts @@ -71,7 +71,7 @@ function createKibanaRequestMock

    ({ routeTags, routeAuthRequired, validation = {}, - kibanaRouteOptions = { xsrfRequired: true }, + kibanaRouteOptions = { xsrfRequired: true, access: 'public' }, kibanaRequestState = { requestId: '123', requestUuid: '123e4567-e89b-12d3-a456-426614174000', diff --git a/packages/core/http/core-http-server-internal/src/http_server.test.ts b/packages/core/http/core-http-server-internal/src/http_server.test.ts index 92fa63c502558..b6a120e06ab8d 100644 --- a/packages/core/http/core-http-server-internal/src/http_server.test.ts +++ b/packages/core/http/core-http-server-internal/src/http_server.test.ts @@ -817,6 +817,56 @@ test('allows attaching metadata to attach meta-data tag strings to a route', asy await supertest(innerServer.listener).get('/without-tags').expect(200, { tags: [] }); }); +test('allows declaring route access to flag a route as public or internal', async () => { + const access = 'internal'; + const { registerRouter, server: innerServer } = await server.setup(config); + + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/with-access', validate: false, options: { access } }, (context, req, res) => + res.ok({ body: { access: req.route.options.access } }) + ); + router.get({ path: '/without-access', validate: false }, (context, req, res) => + res.ok({ body: { access: req.route.options.access } }) + ); + registerRouter(router); + + await server.start(); + await supertest(innerServer.listener).get('/with-access').expect(200, { access }); + + await supertest(innerServer.listener).get('/without-access').expect(200, { access: 'public' }); +}); + +test('infers access flag from path if not defined', async () => { + const { registerRouter, server: innerServer } = await server.setup(config); + + const router = new Router('', logger, enhanceWithContext); + router.get({ path: '/internal/foo', validate: false }, (context, req, res) => + res.ok({ body: { access: req.route.options.access } }) + ); + router.get({ path: '/random/foo', validate: false }, (context, req, res) => + res.ok({ body: { access: req.route.options.access } }) + ); + router.get({ path: '/random/internal/foo', validate: false }, (context, req, res) => + res.ok({ body: { access: req.route.options.access } }) + ); + + router.get({ path: '/api/foo/internal/my-foo', validate: false }, (context, req, res) => + res.ok({ body: { access: req.route.options.access } }) + ); + registerRouter(router); + + await server.start(); + await supertest(innerServer.listener).get('/internal/foo').expect(200, { access: 'internal' }); + + await supertest(innerServer.listener).get('/random/foo').expect(200, { access: 'public' }); + await supertest(innerServer.listener) + .get('/random/internal/foo') + .expect(200, { access: 'public' }); + await supertest(innerServer.listener) + .get('/api/foo/internal/my-foo') + .expect(200, { access: 'public' }); +}); + test('exposes route details of incoming request to a route handler', async () => { const { registerRouter, server: innerServer } = await server.setup(config); @@ -833,6 +883,7 @@ test('exposes route details of incoming request to a route handler', async () => options: { authRequired: true, xsrfRequired: false, + access: 'public', tags: [], timeout: {}, }, @@ -1010,6 +1061,7 @@ test('exposes route details of incoming request to a route handler (POST + paylo options: { authRequired: true, xsrfRequired: true, + access: 'public', tags: [], timeout: { payload: 10000, diff --git a/packages/core/http/core-http-server-internal/src/http_server.ts b/packages/core/http/core-http-server-internal/src/http_server.ts index fb19795d77dce..1ef5be6c67a54 100644 --- a/packages/core/http/core-http-server-internal/src/http_server.ts +++ b/packages/core/http/core-http-server-internal/src/http_server.ts @@ -524,6 +524,7 @@ export class HttpServer { const kibanaRouteOptions: KibanaRouteOptions = { xsrfRequired: route.options.xsrfRequired ?? !isSafeMethod(route.method), + access: route.options.access ?? (route.path.startsWith('/internal') ? 'internal' : 'public'), }; this.server!.route({ diff --git a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts index 5e182005fd40c..d13bd001bbbb9 100644 --- a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts +++ b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts @@ -167,6 +167,7 @@ describe('xsrf post-auth handler', () => { path: '/some-path', kibanaRouteOptions: { xsrfRequired: false, + access: 'public', }, }); diff --git a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts index 3fe9c8ac727ff..af148413265e8 100644 --- a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts +++ b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts @@ -60,6 +60,7 @@ export const createVersionCheckPostAuthHandler = (kibanaVersion: string): OnPost }; }; +// TODO: implement header required for accessing internal routes. See https://github.com/elastic/kibana/issues/151940 export const createCustomHeadersPreResponseHandler = (config: HttpConfig): OnPreResponseHandler => { const { name: serverName, diff --git a/packages/core/http/core-http-server/src/router/request.ts b/packages/core/http/core-http-server/src/router/request.ts index ef33bec14f841..e0664cb1ea29a 100644 --- a/packages/core/http/core-http-server/src/router/request.ts +++ b/packages/core/http/core-http-server/src/router/request.ts @@ -19,6 +19,7 @@ import type { Headers } from './headers'; */ export interface KibanaRouteOptions extends RouteOptionsApp { xsrfRequired: boolean; + access: 'internal' | 'public'; } /** diff --git a/packages/core/http/core-http-server/src/router/route.ts b/packages/core/http/core-http-server/src/router/route.ts index 78d76bb4ba7b8..e2b11aec08e1a 100644 --- a/packages/core/http/core-http-server/src/router/route.ts +++ b/packages/core/http/core-http-server/src/router/route.ts @@ -120,6 +120,18 @@ export interface RouteConfigOptions { */ xsrfRequired?: Method extends 'get' ? never : boolean; + /** + * Defines intended request origin of the route: + * - public. The route is public, declared stable and intended for external access. + * In the future, may require an incomming request to contain a specified header. + * - internal. The route is internal and intended for internal access only. + * + * If not declared, infers access from route path: + * - access =`internal` for '/internal' route path prefix + * - access = `public` for everything else + */ + access?: 'public' | 'internal'; + /** * Additional metadata tag strings to attach to the route. */ diff --git a/packages/core/versioning/core-version-http-server/src/example.ts b/packages/core/versioning/core-version-http-server/src/example.ts index de529ccb07d9d..b63c75e86a562 100644 --- a/packages/core/versioning/core-version-http-server/src/example.ts +++ b/packages/core/versioning/core-version-http-server/src/example.ts @@ -22,7 +22,7 @@ const versionedRouter = vtk.createVersionedRouter({ router }); const versionedRoute = versionedRouter .post({ path: '/api/my-app/foo/{id?}', - options: { timeout: { payload: 60000 } }, + options: { timeout: { payload: 60000 }, access: 'public' }, }) .addVersion( { diff --git a/packages/core/versioning/core-version-http-server/src/version_http_toolkit.ts b/packages/core/versioning/core-version-http-server/src/version_http_toolkit.ts index 719e0075c0070..7d8dd7765e476 100644 --- a/packages/core/versioning/core-version-http-server/src/version_http_toolkit.ts +++ b/packages/core/versioning/core-version-http-server/src/version_http_toolkit.ts @@ -13,6 +13,7 @@ import type { RequestHandler, RouteValidatorFullConfig, RequestHandlerContextBase, + RouteConfigOptions, } from '@kbn/core-http-server'; type RqCtx = RequestHandlerContextBase; @@ -45,7 +46,7 @@ export interface CreateVersionedRouterArgs { * const versionedRoute = versionedRouter * .post({ * path: '/api/my-app/foo/{id?}', - * options: { timeout: { payload: 60000 } }, + * options: { timeout: { payload: 60000 }, access: 'public' }, * }) * .addVersion( * { @@ -99,14 +100,28 @@ export interface VersionHTTPToolkit { ): VersionedRouter; } +/** + * Converts an input property from optional to required. Needed for making RouteConfigOptions['access'] required. + */ +type WithRequiredProperty = Type & { + [Property in Key]-?: Type[Property]; +}; + +/** + * Versioned route access flag, required + * - '/api/foo' is 'public' + * - '/internal/my-foo' is 'internal' + * Required + */ +type VersionedRouteConfigOptions = WithRequiredProperty, 'access'>; /** * Configuration for a versioned route * @experimental */ export type VersionedRouteConfig = Omit< RouteConfig, - 'validate' ->; + 'validate' | 'options' +> & { options: VersionedRouteConfigOptions }; /** * Create an {@link VersionedRoute | versioned route}. From 8086b995858125560ef04ba957a280818ca10cd9 Mon Sep 17 00:00:00 2001 From: Dominique Clarke Date: Thu, 2 Mar 2023 10:32:03 -0500 Subject: [PATCH 125/131] [Synthetics] adjust overview status to account for various filters (#152527) ## Summary Resolves https://github.com/elastic/kibana/issues/152528 Resolves https://github.com/elastic/kibana/issues/152525 Resolves https://github.com/elastic/kibana/issues/152290 Summarize your PR. If it involves visual changes include a screenshot or gif. - Adjusts overview status query to take into account location filter for pending and disabled count - Adjusts overview status front end logic to take into account status filter for pending count [Synthetics-Overview-Synthetics---Kibana (6).webm](https://user-images.githubusercontent.com/11356435/222312223-a529e709-8171-4721-aeba-5dcbf23949a2.webm) ### Testing 1. Create two monitors, each with locations set to `North America - Central`, `US Central Staging` and and `US Central QA`. 2. Disable one of the monitors 3. Utilize the quick `up` `down` and `disabled` filters. Ensure the counts are correct. 4. Filter by locations, ensure the pending and disabled counts are correct --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../overview/overview/overview_status.tsx | 6 +- .../server/queries/query_monitor_status.ts | 7 +- .../overview_status/overview_status.test.ts | 250 +++++++++++++++++- .../routes/overview_status/overview_status.ts | 8 +- .../synthetics_monitor/get_all_monitors.ts | 18 +- 5 files changed, 272 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx index 2842581994d83..48ef68df3455f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx @@ -48,7 +48,7 @@ export function OverviewStatus() { up: status?.up || 0, down: 0, disabledCount: 0, - pending: status?.pending, + pending: 0, }); break; case 'down': { @@ -56,7 +56,7 @@ export function OverviewStatus() { up: 0, down: status?.down || 0, disabledCount: 0, - pending: status?.pending, + pending: 0, }); break; } @@ -65,7 +65,7 @@ export function OverviewStatus() { up: 0, down: 0, disabledCount: status?.disabledCount || 0, - pending: status?.pending, + pending: 0, }); break; } diff --git a/x-pack/plugins/synthetics/server/queries/query_monitor_status.ts b/x-pack/plugins/synthetics/server/queries/query_monitor_status.ts index 058d28d046c8a..a737e80e08069 100644 --- a/x-pack/plugins/synthetics/server/queries/query_monitor_status.ts +++ b/x-pack/plugins/synthetics/server/queries/query_monitor_status.ts @@ -53,7 +53,6 @@ export async function queryMonitorStatus( const pageCount = Math.ceil(monitorQueryIds.length / idSize); let up = 0; let down = 0; - let pending = 0; const upConfigs: Record = {}; const downConfigs: Record = {}; const monitorsWithoutData = new Map(Object.entries(cloneDeep(monitorLocationsMap))); @@ -135,8 +134,6 @@ export async function queryMonitorStatus( 'getCurrentStatusOverview' + i ); - pending += idsToQuery.length - (result.aggregations?.id.buckets.length ?? 0); - result.aggregations?.id.buckets.forEach(({ location, key: queryId }) => { const locationSummaries = location.buckets.map(({ status, key: locationName }) => { const ping = status.hits.hits[0]._source; @@ -188,8 +185,6 @@ export async function queryMonitorStatus( if (!monitorsWithoutData.get(monitorQueryId)?.length) { monitorsWithoutData.delete(monitorQueryId); } - } else { - pending += 1; } }); }); @@ -212,7 +207,7 @@ export async function queryMonitorStatus( return { up, down, - pending, + pending: Object.values(pendingConfigs).length, upConfigs, downConfigs, pendingConfigs, diff --git a/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.test.ts b/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.test.ts index 4679d555f6504..635b964c922ab 100644 --- a/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.test.ts +++ b/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.test.ts @@ -4,11 +4,21 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { SavedObjectsFindResult } from '@kbn/core-saved-objects-api-server'; +import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; import { getUptimeESMockClient } from '../../legacy_uptime/lib/requests/test_helpers'; import { periodToMs } from './overview_status'; import { queryMonitorStatus } from '../../queries/query_monitor_status'; +import { RouteContext } from '../../legacy_uptime/routes'; +import { getStatus } from './overview_status'; import times from 'lodash/times'; +import * as monitorsFns from '../../saved_objects/synthetics_monitor/get_all_monitors'; +import { EncryptedSyntheticsMonitor } from '../../../common/runtime_types'; + +jest.mock('../../saved_objects/synthetics_monitor/get_all_monitors', () => ({ + ...jest.requireActual('../../saved_objects/synthetics_monitor/get_all_monitors'), + getAllMonitors: jest.fn(), +})); jest.mock('../common', () => ({ getMonitors: jest.fn().mockReturnValue({ @@ -34,6 +44,7 @@ jest.mock('../common', () => ({ }, ], }), + getMonitorFilters: () => '', })); jest.mock('../../legacy_uptime/lib/requests/get_snapshot_counts', () => ({ @@ -61,7 +72,7 @@ describe('current status route', () => { }); }); - describe('getStats', () => { + describe('queryMonitorStatus', () => { it('parses expected agg fields', async () => { const { esClient, uptimeEsClient } = getUptimeESMockClient(); esClient.search.mockResponseOnce( @@ -514,7 +525,7 @@ describe('current status route', () => { } ) ).toEqual({ - pending: 2, + pending: 4, down: 1, enabledMonitorQueryIds: ['id1', 'id2', 'project-monitor-id', 'id4'], up: 2, @@ -575,6 +586,239 @@ describe('current status route', () => { }); }); }); + + describe('getStatus', () => { + it.each([ + [['US Central QA'], 1], + [['North America - US Central'], 1], + [['North America - US Central', 'US Central QA'], 2], + [undefined, 2], + ])('handles disabled count when using location filters', async (locations, disabledCount) => { + jest.spyOn(monitorsFns, 'getAllMonitors').mockResolvedValue([ + { + type: 'synthetics-monitor', + id: 'a9a94f2f-47ba-4fe2-afaa-e5cd29b281f1', + attributes: { + enabled: false, + schedule: { + number: '3', + unit: 'm', + }, + config_id: 'a9a94f2f-47ba-4fe2-afaa-e5cd29b281f1', + locations: [ + { + color: 'default', + isServiceManaged: true, + label: 'US Central QA', + id: 'us_central_qa', + }, + { + isServiceManaged: true, + label: 'North America - US Central', + id: 'us_central', + }, + ], + origin: 'project', + id: 'a-test2-default', + }, + references: [], + migrationVersion: { + 'synthetics-monitor': '8.6.0', + }, + coreMigrationVersion: '8.0.0', + updated_at: '2023-02-28T14:31:37.641Z', + created_at: '2023-02-28T14:31:37.641Z', + version: 'Wzg0MzkzLDVd', + namespaces: ['default'], + score: null, + sort: ['a', 3013], + } as unknown as SavedObjectsFindResult, + ]); + const { esClient, uptimeEsClient } = getUptimeESMockClient(); + esClient.search.mockResponseOnce( + getEsResponse([ + { + key: 'id1', + location: { + buckets: [ + { + key: 'Asia/Pacific - Japan', + status: { + hits: { + hits: [ + { + _source: { + '@timestamp': '2022-09-15T16:08:16.724Z', + monitor: { + status: 'up', + id: 'id1', + }, + summary: { + up: 1, + down: 0, + }, + config_id: 'id1', + observer: { + geo: { + name: 'Asia/Pacific - Japan', + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + { + key: 'id2', + location: { + buckets: [ + { + key: 'Asia/Pacific - Japan', + status: { + hits: { + hits: [ + { + _source: { + '@timestamp': '2022-09-15T16:09:16.724Z', + monitor: { + status: 'up', + id: 'id2', + }, + summary: { + up: 1, + down: 0, + }, + config_id: 'id2', + observer: { + geo: { + name: 'Asia/Pacific - Japan', + }, + }, + }, + }, + ], + }, + }, + }, + { + key: 'Europe - Germany', + status: { + hits: { + hits: [ + { + _source: { + '@timestamp': '2022-09-15T16:19:16.724Z', + monitor: { + status: 'down', + id: 'id2', + }, + summary: { + down: 1, + up: 0, + }, + config_id: 'id2', + observer: { + geo: { + name: 'Europe - Germany', + }, + }, + }, + }, + ], + }, + }, + }, + ], + }, + }, + ]) + ); + expect( + await getStatus( + { + uptimeEsClient, + savedObjectsClient: savedObjectsClientMock.create(), + } as unknown as RouteContext, + { + locations, + } + ) + ).toEqual( + expect.objectContaining({ + disabledCount, + }) + ); + }); + + it.each([ + [['US Central QA'], 1], + [['North America - US Central'], 1], + [['North America - US Central', 'US Central QA'], 2], + [undefined, 2], + ])('handles pending count when using location filters', async (locations, pending) => { + jest.spyOn(monitorsFns, 'getAllMonitors').mockResolvedValue([ + { + type: 'synthetics-monitor', + id: 'a9a94f2f-47ba-4fe2-afaa-e5cd29b281f1', + attributes: { + enabled: true, + schedule: { + number: '3', + unit: 'm', + }, + config_id: 'a9a94f2f-47ba-4fe2-afaa-e5cd29b281f1', + locations: [ + { + color: 'default', + isServiceManaged: true, + label: 'US Central QA', + id: 'us_central_qa', + }, + { + isServiceManaged: true, + label: 'North America - US Central', + id: 'us_central', + }, + ], + origin: 'project', + id: 'a-test2-default', + }, + references: [], + migrationVersion: { + 'synthetics-monitor': '8.6.0', + }, + coreMigrationVersion: '8.0.0', + updated_at: '2023-02-28T14:31:37.641Z', + created_at: '2023-02-28T14:31:37.641Z', + version: 'Wzg0MzkzLDVd', + namespaces: ['default'], + score: null, + sort: ['a', 3013], + } as unknown as SavedObjectsFindResult, + ]); + const { esClient, uptimeEsClient } = getUptimeESMockClient(); + esClient.search.mockResponseOnce(getEsResponse([])); + expect( + await getStatus( + { + uptimeEsClient, + savedObjectsClient: savedObjectsClientMock.create(), + } as unknown as RouteContext, + { + locations, + } + ) + ).toEqual( + expect.objectContaining({ + pending, + }) + ); + }); + }); }); function getEsResponse(buckets: any[]) { diff --git a/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts b/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts index 750727d85f7ce..11ae9ff793e21 100644 --- a/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts +++ b/x-pack/plugins/synthetics/server/routes/overview_status/overview_status.ts @@ -76,7 +76,13 @@ export async function getStatus(context: RouteContext, params: OverviewStatusQue disabledMonitorsCount, projectMonitorsCount, monitorQueryIdToConfigIdMap, - } = await processMonitors(allMonitors, server, savedObjectsClient, syntheticsMonitorClient); + } = await processMonitors( + allMonitors, + server, + savedObjectsClient, + syntheticsMonitorClient, + queryLocations + ); // Account for locations filter const queryLocationsArray = diff --git a/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts b/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts index d134705093937..e0f404ebef875 100644 --- a/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts +++ b/x-pack/plugins/synthetics/server/saved_objects/synthetics_monitor/get_all_monitors.ts @@ -11,6 +11,7 @@ import { SavedObjectsFindResult, } from '@kbn/core-saved-objects-api-server'; import pMap from 'p-map'; +import { intersection } from 'lodash'; import { periodToMs } from '../../routes/overview_status/overview_status'; import { UptimeServerSetup } from '../../legacy_uptime/lib/adapters'; import { getAllLocations } from '../../synthetics_service/get_all_locations'; @@ -64,7 +65,8 @@ export const processMonitors = async ( allMonitors: Array>, server: UptimeServerSetup, soClient: SavedObjectsClientContract, - syntheticsMonitorClient: SyntheticsMonitorClient + syntheticsMonitorClient: SyntheticsMonitorClient, + queryLocations?: string[] | string ) => { /** * Walk through all monitor saved objects, bucket IDs by disabled/enabled status. @@ -72,7 +74,6 @@ export const processMonitors = async ( * Track max period to make sure the snapshot query should reach back far enough to catch * latest ping for all enabled monitors. */ - const enabledMonitorQueryIds: string[] = []; let disabledCount = 0; let disabledMonitorsCount = 0; @@ -109,7 +110,13 @@ export const processMonitors = async ( monitorQueryIdToConfigIdMap[attrs[ConfigKey.MONITOR_QUERY_ID]] = attrs[ConfigKey.CONFIG_ID]; if (attrs[ConfigKey.ENABLED] === false) { - disabledCount += attrs[ConfigKey.LOCATIONS].length; + const monitorLocations = attrs[ConfigKey.LOCATIONS].map((location) => location.label); + const queriedLocations = Array.isArray(queryLocations) ? queryLocations : [queryLocations]; + const intersectingLocations = intersection( + monitorLocations, + queryLocations ? queriedLocations : monitorLocations + ); + disabledCount += intersectingLocations.length; disabledMonitorsCount += 1; } else { const missingLabels = new Set(); @@ -133,7 +140,10 @@ export const processMonitors = async ( getLocationLabel(locationId) ); - monitorLocationMap[attrs[ConfigKey.MONITOR_QUERY_ID]] = [...monLocs, ...locLabels]; + const monitorLocations = [...monLocs, ...locLabels]; + monitorLocationMap[attrs[ConfigKey.MONITOR_QUERY_ID]] = queryLocations + ? intersection(monitorLocations, queryLocations) + : monitorLocations; listOfLocationsSet = new Set([...listOfLocationsSet, ...monLocs, ...locLabels]); maxPeriod = Math.max(maxPeriod, periodToMs(attrs[ConfigKey.SCHEDULE])); From ba619273ebc67b79f44269588906d2f3bbfc9f5a Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Thu, 2 Mar 2023 10:32:18 -0500 Subject: [PATCH 126/131] chore(slo): change rule license (#152508) --- .../observability/server/lib/rules/slo_burn_rate/register.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts index 6a2351435e9aa..4f01d59f70174 100644 --- a/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts +++ b/x-pack/plugins/observability/server/lib/rules/slo_burn_rate/register.ts @@ -38,7 +38,7 @@ export function sloBurnRateRuleType(createLifecycleRuleExecutor: CreateLifecycle defaultActionGroupId: FIRED_ACTION.id, actionGroups: [FIRED_ACTION], producer: 'slo', - minimumLicenseRequired: 'basic' as LicenseType, + minimumLicenseRequired: 'platinum' as LicenseType, isExportable: true, executor: createLifecycleRuleExecutor(getRuleExecutor()), doesSetRecoveryContext: true, From c38c1ff5ae9ccecfdb3947ceb77fa1b078d43fd1 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Thu, 2 Mar 2023 19:41:19 +0400 Subject: [PATCH 127/131] [Enterprise Search] Allow custom pipelines to be deleted (#152556) ## Summary This allows users to revert their custom ingestion pipeline to the default pipeline settings, and prompts them to do so if their custom pipeline is still configured but has been deleted. https://user-images.githubusercontent.com/94373878/222418282-6b7367a3-a8c8-4c87-9482-c1aa47feb2f5.mov https://user-images.githubusercontent.com/94373878/222418308-3cd7f2a9-c1cd-4527-86d7-a4de0f2accfc.mov --- .../index/create_custom_pipeline_api_logic.ts | 5 +- ...evert_connector_pipeline_api_logic.test.ts | 20 + .../revert_connector_pipeline_api_logic.ts | 26 ++ .../customize_pipeline_item.tsx | 80 +++- .../ingest_pipelines_card.test.tsx | 26 -- .../ingest_pipelines_card.tsx | 12 +- .../search_index/pipelines/pipelines.tsx | 46 ++- .../pipelines/pipelines_logic.test.ts | 8 +- .../search_index/pipelines/pipelines_logic.ts | 59 ++- .../create_pipeline_definitions.test.ts | 10 +- .../pipelines/create_pipeline_definitions.ts | 346 +++++++++--------- .../server/lib/pipelines/delete_pipelines.ts | 34 ++ .../lib/pipelines/revert_custom_pipeline.ts | 29 ++ .../routes/enterprise_search/indices.ts | 22 ++ 14 files changed, 489 insertions(+), 234 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.ts create mode 100644 x-pack/plugins/enterprise_search/server/lib/pipelines/delete_pipelines.ts create mode 100644 x-pack/plugins/enterprise_search/server/lib/pipelines/revert_custom_pipeline.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts index 7d9a7ede6ad98..ba3b551b23602 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/index/create_custom_pipeline_api_logic.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; import { i18n } from '@kbn/i18n'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; @@ -14,9 +15,7 @@ export interface CreateCustomPipelineApiLogicArgs { indexName: string; } -export interface CreateCustomPipelineApiLogicResponse { - created: string[]; -} +export type CreateCustomPipelineApiLogicResponse = Record; export const createCustomPipeline = async ({ indexName, diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.test.ts new file mode 100644 index 0000000000000..2753fadb77aea --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.test.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 { mockHttpValues } from '../../../__mocks__/kea_logic'; + +import { revertConnectorPipeline } from './revert_connector_pipeline_api_logic'; + +describe('RevertConnectorPipelineApiLogic', () => { + it('should call delete pipeline endpoint', () => { + const { http } = mockHttpValues; + revertConnectorPipeline({ indexName: 'indexName' }); + expect(http.delete).toHaveBeenCalledWith( + '/internal/enterprise_search/indices/indexName/pipelines' + ); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.ts new file mode 100644 index 0000000000000..a97cafdcd1881 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/pipelines/revert_connector_pipeline_api_logic.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Actions, createApiLogic } from '../../../shared/api_logic/create_api_logic'; +import { HttpLogic } from '../../../shared/http'; + +export interface RevertConnectorPipelineArgs { + indexName: string; +} + +export const revertConnectorPipeline = async ({ indexName }: RevertConnectorPipelineArgs) => { + const route = `/internal/enterprise_search/indices/${indexName}/pipelines`; + + return await HttpLogic.values.http.delete(route); +}; + +export const RevertConnectorPipelineApilogic = createApiLogic( + ['revert_connector_pipeline_api'], + revertConnectorPipeline +); + +export type RevertConnectorPipelineActions = Actions; 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 96d213ced0f2d..e95fb524f29ab 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 @@ -9,20 +9,32 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { EuiButtonEmpty, EuiFlexGroup, EuiSpacer, EuiText } from '@elastic/eui'; +import { EuiButtonEmpty, EuiConfirmModal, EuiFlexGroup, EuiSpacer, EuiText } from '@elastic/eui'; + import { i18n } from '@kbn/i18n'; +import { Status } from '../../../../../../../common/types/api'; + +import { CANCEL_BUTTON_LABEL } from '../../../../../shared/constants'; + import { KibanaLogic } from '../../../../../shared/kibana'; import { LicensingLogic } from '../../../../../shared/licensing'; import { CreateCustomPipelineApiLogic } from '../../../../api/index/create_custom_pipeline_api_logic'; +import { RevertConnectorPipelineApilogic } from '../../../../api/pipelines/revert_connector_pipeline_api_logic'; import { IndexViewLogic } from '../../index_view_logic'; +import { PipelinesLogic } from '../pipelines_logic'; export const CustomizeIngestPipelineItem: React.FC = () => { const { indexName, ingestionMethod } = useValues(IndexViewLogic); const { isCloud } = useValues(KibanaLogic); const { hasPlatinumLicense } = useValues(LicensingLogic); const { makeRequest: createCustomPipeline } = useActions(CreateCustomPipelineApiLogic); + const { status: createStatus } = useValues(CreateCustomPipelineApiLogic); + const { isDeleteModalOpen, hasIndexIngestionPipeline } = useValues(PipelinesLogic); + const { closeDeleteModal, openDeleteModal } = useActions(PipelinesLogic); + const { makeRequest: revertPipeline } = useActions(RevertConnectorPipelineApilogic); + const { status: revertStatus } = useValues(RevertConnectorPipelineApilogic); const isGated = !isCloud && !hasPlatinumLicense; return ( @@ -49,17 +61,61 @@ export const CustomizeIngestPipelineItem: React.FC = () => { )} - createCustomPipeline({ indexName })} - > - {i18n.translate( - 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.copyButtonLabel', - { defaultMessage: 'Copy and customize' } - )} - + {isDeleteModalOpen && ( + revertPipeline({ indexName })} + cancelButtonText={CANCEL_BUTTON_LABEL} + confirmButtonText={i18n.translate( + 'xpack.enterpriseSearch.content.index.pipelines.deleteModal.confirmButton', + { + defaultMessage: 'Delete pipeline', + } + )} + buttonColor="danger" + > +

    + {i18n.translate( + 'xpack.enterpriseSearch.content.index.pipelines.deleteModal.description', + { + defaultMessage: + 'This will delete any custom pipelines associated with this index, including machine learning inference pipelines. The index will revert to using the default ingest pipeline.', + } + )} +

    + + )} + {hasIndexIngestionPipeline ? ( + openDeleteModal()} + > + {i18n.translate( + 'xpack.enterpriseSearch.content.index.pipelines.ingestFlyout.revertPipelineLabel', + { defaultMessage: 'Delete custom pipeline' } + )} + + ) : ( + createCustomPipeline({ indexName })} + > + {i18n.translate( + '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/ingest_pipelines_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.test.tsx index 0ca347da0712e..a6c68b47c7b5a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/ingest_pipelines/ingest_pipelines_card.test.tsx @@ -12,8 +12,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; - import { DEFAULT_PIPELINE_NAME } from '../../../../../../../common/constants'; import { CustomPipelineItem } from './custom_pipeline_item'; @@ -52,28 +50,4 @@ describe('IngestPipelinesCard', () => { expect(wrapper.find(CustomizeIngestPipelineItem)).toHaveLength(1); expect(wrapper.find(CustomPipelineItem)).toHaveLength(0); }); - it('does not render customize cta with index ingest pipeline', () => { - const pipelineName = crawlerIndex.name; - const pipelines: Record = { - [pipelineName]: {}, - [`${pipelineName}@custom`]: { - processors: [], - }, - }; - setMockValues({ - ...DEFAULT_VALUES, - data: pipelines, - hasIndexIngestionPipeline: true, - pipelineName, - pipelineState: { - ...DEFAULT_VALUES.pipelineState, - name: pipelineName, - }, - }); - - const wrapper = shallow(); - expect(wrapper.find(CustomizeIngestPipelineItem)).toHaveLength(0); - expect(wrapper.find(DefaultPipelineItem)).toHaveLength(1); - expect(wrapper.find(CustomPipelineItem)).toHaveLength(1); - }); }); 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 d57b4142d2905..64f195e217891 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 @@ -24,14 +24,8 @@ import { IngestPipelineFlyout } from './ingest_pipeline_flyout'; export const IngestPipelinesCard: React.FC = () => { const { indexName, ingestionMethod } = useValues(IndexViewLogic); - const { - canSetPipeline, - hasIndexIngestionPipeline, - index, - pipelineName, - pipelineState, - showPipelineSettings, - } = useValues(PipelinesLogic); + const { canSetPipeline, index, pipelineName, pipelineState, showPipelineSettings } = + useValues(PipelinesLogic); const { closePipelineSettings, openPipelineSettings, setPipelineState, savePipeline } = useActions(PipelinesLogic); const { makeRequest: fetchCustomPipeline } = useActions(FetchCustomPipelineApiLogic); @@ -45,7 +39,7 @@ export const IngestPipelinesCard: React.FC = () => { return ( <> - {!hasIndexIngestionPipeline && } + {showPipelineSettings && ( { - const { showAddMlInferencePipelineModal, hasIndexIngestionPipeline, index, pipelineName } = - useValues(PipelinesLogic); + const { + showMissingPipelineCallout, + showAddMlInferencePipelineModal, + hasIndexIngestionPipeline, + index, + pipelineName, + } = useValues(PipelinesLogic); const { closeAddMlInferencePipelineModal, openAddMlInferencePipelineModal } = useActions(PipelinesLogic); + const { indexName } = useValues(IndexNameLogic); + const { makeRequest: revertPipeline } = useActions(RevertConnectorPipelineApilogic); const apiIndex = isApiIndex(index); const pipelinesTabs: EuiTabbedContentTab[] = [ @@ -66,6 +78,36 @@ export const SearchIndexPipelines: React.FC = () => { return ( <> + {showMissingPipelineCallout && ( + +

    + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.missingPipeline.description', + { + defaultMessage: + 'The custom pipeline for this index has been deleted. This may affect connector data ingestion. Its configuration will need to be reverted to the default pipeline settings.', + } + )} +

    + revertPipeline({ indexName })}> + {i18n.translate( + 'xpack.enterpriseSearch.content.indices.pipelines.missingPipeline.buttonLabel', + { + defaultMessage: 'Revert pipeline to default', + } + )} + +
    + )} diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts index a16bd36ee54ba..69e01d45750fe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/pipelines/pipelines_logic.test.ts @@ -35,10 +35,12 @@ const DEFAULT_VALUES = { hasIndexIngestionPipeline: false, index: undefined, indexName: '', + isDeleteModalOpen: false, mlInferencePipelineProcessors: undefined, pipelineName: DEFAULT_PIPELINE_VALUES.name, pipelineState: DEFAULT_PIPELINE_VALUES, showAddMlInferencePipelineModal: false, + showMissingPipelineCallout: false, showPipelineSettings: false, }; @@ -145,16 +147,16 @@ describe('PipelinesLogic', () => { }); }); describe('createCustomPipelineSuccess', () => { - it('should call flashSuccessToast', () => { + it('should call flashSuccessToast and update pipelines', () => { PipelinesLogic.actions.setPipelineState = jest.fn(); PipelinesLogic.actions.savePipeline = jest.fn(); PipelinesLogic.actions.fetchCustomPipeline = jest.fn(); PipelinesLogic.actions.fetchIndexApiSuccess(connectorIndex); - PipelinesLogic.actions.createCustomPipelineSuccess({ created: ['a', 'b'] }); + PipelinesLogic.actions.createCustomPipelineSuccess({ [connectorIndex.name]: {} }); expect(flashSuccessToast).toHaveBeenCalledWith('Custom pipeline created'); expect(PipelinesLogic.actions.setPipelineState).toHaveBeenCalledWith({ ...PipelinesLogic.values.pipelineState, - name: 'a', + name: connectorIndex.name, }); expect(PipelinesLogic.actions.savePipeline).toHaveBeenCalled(); expect(PipelinesLogic.actions.fetchCustomPipeline).toHaveBeenCalled(); 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 dbe0239028ad5..bf71dc215243f 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 @@ -66,6 +66,10 @@ import { } from '../../../api/pipelines/detach_ml_inference_pipeline'; import { FetchMlInferencePipelineProcessorsApiLogic } from '../../../api/pipelines/fetch_ml_inference_pipeline_processors'; +import { + RevertConnectorPipelineActions, + RevertConnectorPipelineApilogic, +} from '../../../api/pipelines/revert_connector_pipeline_api_logic'; import { isApiIndex, isConnectorIndex, isCrawlerIndex } from '../../../utils/indices'; type PipelinesActions = Pick< @@ -77,6 +81,7 @@ type PipelinesActions = Pick< AttachMlInferencePipelineResponse >['apiSuccess']; closeAddMlInferencePipelineModal: () => void; + closeDeleteModal: () => void; closePipelineSettings: () => void; createCustomPipeline: Actions< CreateCustomPipelineApiLogicArgs, @@ -132,7 +137,9 @@ type PipelinesActions = Pick< fetchMlInferenceProcessors: typeof FetchMlInferencePipelineProcessorsApiLogic.actions.makeRequest; fetchMlInferenceProcessorsApiError: (error: HttpError) => HttpError; openAddMlInferencePipelineModal: () => void; + openDeleteModal: () => void; openPipelineSettings: () => void; + revertPipelineSuccess: RevertConnectorPipelineActions['apiSuccess']; savePipeline: () => void; setPipelineState(pipeline: IngestPipelineParams): { pipeline: IngestPipelineParams; @@ -148,18 +155,22 @@ interface PipelinesValues { hasIndexIngestionPipeline: boolean; index: CachedFetchIndexApiLogicValues['fetchIndexApiData']; indexName: string; + isDeleteModalOpen: boolean; mlInferencePipelineProcessors: InferencePipeline[]; pipelineName: string; pipelineState: IngestPipelineParams; showAddMlInferencePipelineModal: boolean; + showMissingPipelineCallout: boolean; showPipelineSettings: boolean; } export const PipelinesLogic = kea>({ actions: { closeAddMlInferencePipelineModal: true, + closeDeleteModal: true, closePipelineSettings: true, openAddMlInferencePipelineModal: true, + openDeleteModal: true, openPipelineSettings: true, savePipeline: true, setPipelineState: (pipeline: IngestPipelineParams) => ({ pipeline }), @@ -201,6 +212,8 @@ export const PipelinesLogic = kea { - actions.setPipelineState({ ...values.pipelineState, name: created[0] }); + createCustomPipelineSuccess: (created) => { + actions.fetchCustomPipelineSuccess(created); + actions.setPipelineState({ ...values.pipelineState, name: values.indexName }); actions.savePipeline(); actions.fetchCustomPipeline({ indexName: values.index.name }); }, @@ -313,6 +327,19 @@ export const PipelinesLogic = kea { + if (isConnectorIndex(values.index) || isCrawlerIndex(values.index)) { + if (values.index.connector) { + // had to split up these if checks rather than nest them or typescript wouldn't recognize connector as defined + actions.fetchIndexApiSuccess({ + ...values.index, + connector: { ...values.index.connector, pipeline: values.defaultPipelineValues }, + }); + actions.fetchCustomPipelineSuccess({}); + } + } + actions.fetchCustomPipeline({ indexName: values.indexName }); + }, savePipeline: () => { if (isConnectorIndex(values.index) || isCrawlerIndex(values.index)) { if (values.index.connector) { @@ -326,6 +353,14 @@ export const PipelinesLogic = kea ({ + isDeleteModalOpen: [ + false, + { + closeDeleteModal: () => false, + openDeleteModal: () => true, + revertPipelineSuccess: () => false, + }, + ], pipelineState: [ DEFAULT_PIPELINE_VALUES, { @@ -381,5 +416,25 @@ export const PipelinesLogic = kea customPipelineData && customPipelineData[indexName] ? indexName : pipelineState.name, ], + showMissingPipelineCallout: [ + () => [ + selectors.hasIndexIngestionPipeline, + selectors.pipelineName, + selectors.customPipelineData, + selectors.index, + ], + ( + hasCustomPipeline: boolean, + pipelineName: string, + customPipelineData: Record | undefined, + index: ElasticsearchIndexWithIngestion + ) => + Boolean( + hasCustomPipeline && + customPipelineData && + !customPipelineData[pipelineName] && + isConnectorIndex(index) + ), + ], }), }); diff --git a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts index 23232fda4199d..91859d66f6e55 100644 --- a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.test.ts @@ -8,8 +8,6 @@ import { merge } from 'lodash'; import { ElasticsearchClient } from '@kbn/core/server'; -import { getInferencePipelineNameFromIndexName } from '../../utils/ml_inference_pipeline_utils'; - import { createIndexPipelineDefinitions } from './create_pipeline_definitions'; import { formatMlPipelineBody } from './create_pipeline_definitions'; @@ -22,19 +20,13 @@ describe('createIndexPipelineDefinitions util function', () => { }, }; - const expectedResult = { - created: [indexName, `${indexName}@custom`, getInferencePipelineNameFromIndexName(indexName)], - }; - beforeEach(() => { jest.clearAllMocks(); }); it('should create the pipelines', async () => { mockClient.ingest.putPipeline.mockImplementation(() => Promise.resolve({ acknowledged: true })); - await expect( - createIndexPipelineDefinitions(indexName, mockClient as unknown as ElasticsearchClient) - ).resolves.toEqual(expectedResult); + await createIndexPipelineDefinitions(indexName, mockClient as unknown as ElasticsearchClient); expect(mockClient.ingest.putPipeline).toHaveBeenCalledTimes(3); }); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts index 8b511ab22c3e7..209d9d4787ea3 100644 --- a/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts +++ b/x-pack/plugins/enterprise_search/server/lib/pipelines/create_pipeline_definitions.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core/server'; import { generateMlInferencePipelineBody } from '../../../common/ml_inference_pipeline'; @@ -14,10 +15,6 @@ import { } from '../../../common/types/pipelines'; import { getInferencePipelineNameFromIndexName } from '../../utils/ml_inference_pipeline_utils'; -export interface CreatedPipelines { - created: string[]; -} - /** * Used to create index-specific Ingest Pipelines to be used in conjunction with Enterprise Search * ingestion mechanisms. Three pipelines are created: @@ -33,189 +30,202 @@ export interface CreatedPipelines { export const createIndexPipelineDefinitions = async ( indexName: string, esClient: ElasticsearchClient -): Promise => { +): Promise> => { // TODO: add back descriptions (see: https://github.com/elastic/elasticsearch-specification/issues/1827) - await esClient.ingest.putPipeline({ - description: `Enterprise Search Machine Learning Inference pipeline for the '${indexName}' index`, - id: getInferencePipelineNameFromIndexName(indexName), - processors: [], - version: 1, - }); - await esClient.ingest.putPipeline({ - description: `Enterprise Search customizable ingest pipeline for the '${indexName}' index`, - id: `${indexName}@custom`, - processors: [], - version: 1, - }); - await esClient.ingest.putPipeline({ - _meta: { - managed: true, - managed_by: 'Enterprise Search', - }, - description: `Enterprise Search ingest pipeline for the '${indexName}' index`, - id: `${indexName}`, - processors: [ - { - attachment: { - field: '_attachment', - if: 'ctx?._extract_binary_content == true', - ignore_missing: true, - indexed_chars_field: '_attachment_indexed_chars', - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - [ - "Processor 'attachment' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + let result: Record = {}; + try { + const mlPipeline = { + description: `Enterprise Search Machine Learning Inference pipeline for the '${indexName}' index`, + id: getInferencePipelineNameFromIndexName(indexName), + processors: [], + version: 1, + }; + await esClient.ingest.putPipeline(mlPipeline); + result = { ...result, [mlPipeline.id]: mlPipeline }; + const customPipeline = { + description: `Enterprise Search customizable ingest pipeline for the '${indexName}' index`, + id: `${indexName}@custom`, + processors: [], + version: 1, + }; + await esClient.ingest.putPipeline(customPipeline); + result = { ...result, [customPipeline.id]: customPipeline }; + const ingestPipeline = { + _meta: { + managed: true, + managed_by: 'Enterprise Search', + }, + description: `Enterprise Search ingest pipeline for the '${indexName}' index`, + id: `${indexName}`, + processors: [ + { + attachment: { + field: '_attachment', + if: 'ctx?._extract_binary_content == true', + ignore_missing: true, + indexed_chars_field: '_attachment_indexed_chars', + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + [ + "Processor 'attachment' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], ], - ], + }, }, - }, - ], - target_field: '_extracted_attachment', + ], + target_field: '_extracted_attachment', + }, }, - }, - { - set: { - field: 'body', - if: 'ctx?._extract_binary_content == true', - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - [ - "Processor 'set' with tag 'set_body' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + { + set: { + field: 'body', + if: 'ctx?._extract_binary_content == true', + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + [ + "Processor 'set' with tag 'set_body' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], ], - ], + }, }, - }, - ], - tag: 'set_body', - value: '{{{_extracted_attachment.content}}}', + ], + tag: 'set_body', + value: '{{{_extracted_attachment.content}}}', + }, }, - }, - { - pipeline: { - if: 'ctx?._run_ml_inference == true', - name: getInferencePipelineNameFromIndexName(indexName), - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - "Processor 'pipeline' with tag 'index_ml_inference_pipeline' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", - ], + { + pipeline: { + if: 'ctx?._run_ml_inference == true', + name: getInferencePipelineNameFromIndexName(indexName), + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + "Processor 'pipeline' with tag 'index_ml_inference_pipeline' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], + }, }, - }, - ], - tag: 'index_ml_inference_pipeline', + ], + tag: 'index_ml_inference_pipeline', + }, }, - }, - { - pipeline: { - name: `${indexName}@custom`, - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - "Processor 'pipeline' with tag 'index_custom_pipeline' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", - ], + { + pipeline: { + name: `${indexName}@custom`, + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + "Processor 'pipeline' with tag 'index_custom_pipeline' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], + }, }, - }, - ], - tag: 'index_custom_pipeline', + ], + tag: 'index_custom_pipeline', + }, }, - }, - { - gsub: { - field: 'body', - if: 'ctx?._extract_binary_content == true', - ignore_missing: true, - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - "Processor 'gsub' with tag 'remove_replacement_chars' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", - ], + { + gsub: { + field: 'body', + if: 'ctx?._extract_binary_content == true', + ignore_missing: true, + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + "Processor 'gsub' with tag 'remove_replacement_chars' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], + }, }, - }, - ], - pattern: '�', - replacement: '', - tag: 'remove_replacement_chars', + ], + pattern: '�', + replacement: '', + tag: 'remove_replacement_chars', + }, }, - }, - { - gsub: { - field: 'body', - if: 'ctx?._reduce_whitespace == true', - ignore_missing: true, - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - "Processor 'gsub' with tag 'remove_extra_whitespace' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", - ], + { + gsub: { + field: 'body', + if: 'ctx?._reduce_whitespace == true', + ignore_missing: true, + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + "Processor 'gsub' with tag 'remove_extra_whitespace' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], + }, }, - }, - ], - pattern: '\\s+', - replacement: ' ', - tag: 'remove_extra_whitespace', + ], + pattern: '\\s+', + replacement: ' ', + tag: 'remove_extra_whitespace', + }, }, - }, - { - trim: { - field: 'body', - if: 'ctx?._reduce_whitespace == true', - ignore_missing: true, - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - "Processor 'trim' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", - ], + { + trim: { + field: 'body', + if: 'ctx?._reduce_whitespace == true', + ignore_missing: true, + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + "Processor 'trim' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], + }, }, - }, - ], + ], + }, }, - }, - { - remove: { - field: [ - '_attachment', - '_attachment_indexed_chars', - '_extracted_attachment', - '_extract_binary_content', - '_reduce_whitespace', - '_run_ml_inference', - ], - ignore_missing: true, - on_failure: [ - { - append: { - field: '_ingestion_errors', - value: [ - "Processor 'remove' with tag 'remove_meta_fields' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", - ], + { + remove: { + field: [ + '_attachment', + '_attachment_indexed_chars', + '_extracted_attachment', + '_extract_binary_content', + '_reduce_whitespace', + '_run_ml_inference', + ], + ignore_missing: true, + on_failure: [ + { + append: { + field: '_ingestion_errors', + value: [ + "Processor 'remove' with tag 'remove_meta_fields' in pipeline '{{ _ingest.on_failure_pipeline }}' failed with message '{{ _ingest.on_failure_message }}'", + ], + }, }, - }, - ], - tag: 'remove_meta_fields', + ], + tag: 'remove_meta_fields', + }, }, - }, - ], - version: 1, - }); - return { - created: [indexName, `${indexName}@custom`, getInferencePipelineNameFromIndexName(indexName)], - }; + ], + version: 1, + }; + await esClient.ingest.putPipeline(ingestPipeline); + result = { ...result, [ingestPipeline.id]: ingestPipeline }; + return result; + } catch (error) { + // clean up pipelines if one failed to create + for (const id of Object.keys(result)) { + await esClient.ingest.deletePipeline({ id }); + } + throw error; + } }; /** diff --git a/x-pack/plugins/enterprise_search/server/lib/pipelines/delete_pipelines.ts b/x-pack/plugins/enterprise_search/server/lib/pipelines/delete_pipelines.ts new file mode 100644 index 0000000000000..3038f48004ea9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/pipelines/delete_pipelines.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IScopedClusterClient } from '@kbn/core/server'; + +import { getInferencePipelineNameFromIndexName } from '../../utils/ml_inference_pipeline_utils'; + +export const deleteIndexPipelines = async ( + client: IScopedClusterClient, + indexName: string +): Promise<{ deleted: string[] }> => { + const deleted: string[] = []; + const promises = [ + client.asCurrentUser.ingest + .deletePipeline({ id: indexName }) + .then(() => deleted.push(indexName)), + client.asCurrentUser.ingest + .deletePipeline({ + id: getInferencePipelineNameFromIndexName(indexName), + }) + .then(() => deleted.push(getInferencePipelineNameFromIndexName(indexName))), + client.asCurrentUser.ingest + .deletePipeline({ id: `${indexName}@custom` }) + .then(() => deleted.push(`${indexName}@custom`)), + ]; + await Promise.allSettled(promises); + return { + deleted, + }; +}; diff --git a/x-pack/plugins/enterprise_search/server/lib/pipelines/revert_custom_pipeline.ts b/x-pack/plugins/enterprise_search/server/lib/pipelines/revert_custom_pipeline.ts new file mode 100644 index 0000000000000..60a9e5cfcf97d --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/lib/pipelines/revert_custom_pipeline.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; 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 { fetchConnectorByIndexName } from '../connectors/fetch_connectors'; + +import { deleteIndexPipelines } from './delete_pipelines'; + +import { getDefaultPipeline } from './get_default_pipeline'; + +export const revertCustomPipeline = async (client: IScopedClusterClient, indexName: string) => { + const connector = await fetchConnectorByIndexName(client, indexName); + if (connector) { + const pipeline = await getDefaultPipeline(client); + await client.asCurrentUser.update({ + doc: { pipeline }, + id: connector?.id, + index: CONNECTORS_INDEX, + }); + } + return await deleteIndexPipelines(client, indexName); +}; diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts index 238a882142b7c..dc82b35c31f59 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/indices.ts @@ -44,6 +44,7 @@ import { createIndexPipelineDefinitions } from '../../lib/pipelines/create_pipel import { getCustomPipelines } from '../../lib/pipelines/get_custom_pipelines'; import { getPipeline } from '../../lib/pipelines/get_pipeline'; import { getMlInferencePipelines } from '../../lib/pipelines/ml_inference/get_ml_inference_pipelines'; +import { revertCustomPipeline } from '../../lib/pipelines/revert_custom_pipeline'; import { RouteDependencies } from '../../plugin'; import { createError } from '../../utils/create_error'; import { elasticsearchErrorHandler } from '../../utils/elasticsearch_error_handler'; @@ -299,6 +300,27 @@ export function registerIndexRoutes({ }) ); + router.delete( + { + path: '/internal/enterprise_search/indices/{indexName}/pipelines', + validate: { + params: schema.object({ + indexName: schema.string(), + }), + }, + }, + elasticsearchErrorHandler(log, async (context, request, response) => { + const indexName = decodeURIComponent(request.params.indexName); + const { client } = (await context.core).elasticsearch; + const body = await revertCustomPipeline(client, indexName); + + return response.ok({ + body, + headers: { 'content-type': 'application/json' }, + }); + }) + ); + router.get( { path: '/internal/enterprise_search/indices/{indexName}/pipelines', From 4be049381bf8793d74fbc75f64206215f4795b03 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Thu, 2 Mar 2023 16:45:16 +0100 Subject: [PATCH 128/131] [Ingest Pipelines] Add support for redact processor (#152353) --- .../__jest__/processors/processor.helpers.tsx | 5 +- .../__jest__/processors/redact.test.tsx | 141 ++++++++++++ .../processor_form/field_components/index.ts | 1 + .../field_components/input_list.scss | 20 ++ .../field_components/input_list.tsx | 166 ++++++++++++++ .../processor_form/processors/index.ts | 1 + .../processor_form/processors/redact.tsx | 207 ++++++++++++++++++ .../shared/map_processor_type_to_form.tsx | 19 ++ 8 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/redact.test.tsx create mode 100644 x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.scss create mode 100644 x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.tsx create mode 100644 x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/redact.tsx diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx index 9501598c53db2..970aaf83b5ae8 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/processor.helpers.tsx @@ -187,4 +187,7 @@ type TestSubject = | 'droppableList.addButton' | 'droppableList.input-0' | 'droppableList.input-1' - | 'droppableList.input-2'; + | 'droppableList.input-2' + | 'prefixField.input' + | 'suffixField.input' + | 'patternDefinitionsField'; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/redact.test.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/redact.test.tsx new file mode 100644 index 0000000000000..d34e4d1476bb8 --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/__jest__/processors/redact.test.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act } from 'react-dom/test-utils'; +import { setup, SetupResult, getProcessorValue, setupEnvironment } from './processor.helpers'; + +const REDACT_TYPE = 'redact'; + +describe('Processor: Redact', () => { + let onUpdate: jest.Mock; + let testBed: SetupResult; + let clickAddPattern: () => Promise; + const { httpSetup } = setupEnvironment(); + + beforeAll(() => { + jest.useFakeTimers({ legacyFakeTimers: true }); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + beforeEach(async () => { + onUpdate = jest.fn(); + + await act(async () => { + testBed = await setup(httpSetup, { + value: { + processors: [], + }, + onFlyoutOpen: jest.fn(), + onUpdate, + }); + }); + + const { find, component, actions } = testBed; + + clickAddPattern = async () => { + await act(async () => { + find('droppableList.addButton').simulate('click'); + }); + component.update(); + }; + + component.update(); + + // Open flyout to add new processor + actions.addProcessor(); + // Add type (the other fields are not visible until a type is selected) + await actions.addProcessorType(REDACT_TYPE); + }); + + test('prevents form submission if required fields are not provided', async () => { + const { + actions: { saveNewProcessor }, + form, + } = testBed; + + // Click submit button with only the type defined + await saveNewProcessor(); + + // Expect form error as "field" is a required parameter + expect(form.getErrorsMessages()).toEqual([ + 'A field value is required.', // "Field" input + 'A value is required.', // First input in "Patterns" list + ]); + }); + + test('saves with default parameter values', async () => { + const { + actions: { saveNewProcessor }, + form, + } = testBed; + + // Add "field" value + form.setInputValue('fieldNameField.input', 'test_redact_processor'); + + // Add pattern 1 + form.setInputValue('droppableList.input-0', 'pattern1'); + + // Add pattern 2 + await clickAddPattern(); + form.setInputValue('droppableList.input-1', 'pattern2'); + + // Save the field + await saveNewProcessor(); + + const processors = getProcessorValue(onUpdate, REDACT_TYPE); + + expect(processors[0][REDACT_TYPE]).toEqual({ + field: 'test_redact_processor', + patterns: ['pattern1', 'pattern2'], + }); + }); + + test('saves with optional parameter values', async () => { + const { + actions: { saveNewProcessor }, + component, + find, + form, + } = testBed; + + // Add "field" value + form.setInputValue('fieldNameField.input', 'test_redact_processor'); + + // Add one pattern to the list + form.setInputValue('droppableList.input-0', 'pattern1'); + + // Set suffix and prefix + form.setInputValue('prefixField.input', '$'); + form.setInputValue('suffixField.input', '$'); + + await act(async () => { + find('patternDefinitionsField').simulate('change', { + jsonContent: JSON.stringify({ GITHUB_NAME: '@%{USERNAME}' }), + }); + + // advance timers to allow the form to validate + jest.advanceTimersByTime(0); + }); + component.update(); + + // Save the field + await saveNewProcessor(); + + const processors = getProcessorValue(onUpdate, REDACT_TYPE); + + expect(processors[0][REDACT_TYPE]).toEqual({ + field: 'test_redact_processor', + patterns: ['pattern1'], + suffix: '$', + prefix: '$', + pattern_definitions: { GITHUB_NAME: '@%{USERNAME}' }, + }); + }); +}); diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/index.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/index.ts index bb63461d71209..e4b9817e89579 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/index.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/index.ts @@ -8,3 +8,4 @@ export { DragAndDropTextList } from './drag_and_drop_text_list'; export { XJsonEditor } from './xjson_editor'; export { TextEditor } from './text_editor'; +export { InputList } from './input_list'; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.scss b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.scss new file mode 100644 index 0000000000000..bec0c9981e308 --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.scss @@ -0,0 +1,20 @@ +.pipelineProcessorsEditor__form__inputList { + &__panel { + background-color: $euiColorLightestShade; + padding: $euiSizeM; + } + + &__removeButton { + margin-left: $euiSizeS; + } + + &__item { + background-color: $euiColorLightestShade; + padding-top: $euiSizeS; + padding-bottom: $euiSizeS; + } + + &__labelContainer { + margin-bottom: $euiSizeXS; + } +} diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.tsx new file mode 100644 index 0000000000000..602c5598551a5 --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/field_components/input_list.tsx @@ -0,0 +1,166 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 React, { useState } from 'react'; +import { v4 as uuidv4 } from 'uuid'; +import { + EuiButtonEmpty, + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiFieldText, + EuiFormRow, + EuiText, +} from '@elastic/eui'; + +import { + UseField, + ArrayItem, + ValidationFunc, + getFieldValidityAndErrorMessage, +} from '../../../../../../shared_imports'; + +import './input_list.scss'; + +interface Props { + label: string; + helpText: React.ReactNode; + error: string | null; + value: ArrayItem[]; + onAdd: () => void; + onRemove: (id: number) => void; + addLabel: string; + /** + * Validation to be applied to every text item + */ + textValidations?: Array>; + /** + * Serializer to be applied to every text item + */ + textSerializer?: (v: string) => O; + /** + * Deserializer to be applied to every text item + */ + textDeserializer?: (v: unknown) => string; +} + +const i18nTexts = { + removeItemButtonAriaLabel: i18n.translate( + 'xpack.ingestPipelines.pipelineEditor.inputList.removeItemLabel', + { defaultMessage: 'Remove item' } + ), +}; + +export function InputList({ + label, + helpText, + error, + value, + onAdd, + onRemove, + addLabel, + textValidations, + textDeserializer, + textSerializer, +}: Props): JSX.Element { + const [firstItemId] = useState(() => uuidv4()); + + return ( + + <> + + + + + + + + +

    {helpText}

    +
    +
    +
    + +
    + {value.map((item, idx) => ( + + + + path={item.path} + config={{ + validations: textValidations + ? textValidations.map((validator) => ({ validator })) + : undefined, + deserializer: textDeserializer, + serializer: textSerializer, + }} + readDefaultValueOnForm={!item.isNew} + > + {(field) => { + const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field); + return ( + + + + ); + }} + + + + {value.length > 1 ? ( + onRemove(item.id)} + size="s" + /> + ) : ( + + )} + + + ))} + + {addLabel} + +
    + +
    + ); +} diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/index.ts b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/index.ts index e3a0fae36e577..bf9ac7006e1c2 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/index.ts +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/index.ts @@ -31,6 +31,7 @@ export { Kv } from './kv'; export { Lowercase } from './lowercase'; export { NetworkDirection } from './network_direction'; export { Pipeline } from './pipeline'; +export { Redact } from './redact'; export { RegisteredDomain } from './registered_domain'; export { Remove } from './remove'; export { Rename } from './rename'; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/redact.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/redact.tsx new file mode 100644 index 0000000000000..4e8885e94eb7e --- /dev/null +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/processor_form/processors/redact.tsx @@ -0,0 +1,207 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, { FunctionComponent } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiCode, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; + +import { + FIELD_TYPES, + Field, + UseField, + UseArray, + fieldValidators, + ValidationFunc, +} from '../../../../../../shared_imports'; + +import { XJsonEditor, InputList } from '../field_components'; + +import { FieldNameField } from './common_fields/field_name_field'; +import { IgnoreMissingField } from './common_fields/ignore_missing_field'; +import { FieldsConfig, to, from, EDITOR_PX_HEIGHT } from './shared'; + +const { isJsonField, emptyField } = fieldValidators; + +const i18nTexts = { + addPatternLabel: i18n.translate( + 'xpack.ingestPipelines.pipelineEditor.redactForm.patternsAddPatternLabel', + { defaultMessage: 'Add pattern' } + ), +}; + +const valueRequiredMessage = i18n.translate( + 'xpack.ingestPipelines.pipelineEditor.redactForm.patternsValueRequiredError', + { defaultMessage: 'A value is required.' } +); + +const patternsValidation: ValidationFunc = ({ value }) => { + if (typeof value === 'string' && value.length === 0) { + return { + message: valueRequiredMessage, + }; + } +}; + +const patternValidations = [emptyField(valueRequiredMessage)]; + +const fieldsConfig: FieldsConfig = { + /* Required field configs */ + patterns: { + label: i18n.translate('xpack.ingestPipelines.pipelineEditor.redactForm.patternsFieldLabel', { + defaultMessage: 'Patterns', + }), + deserializer: String, + helpText: i18n.translate('xpack.ingestPipelines.pipelineEditor.redactForm.patternsHelpText', { + defaultMessage: 'A list of grok expressions to match and redact named captures with.', + }), + validations: [ + { + validator: patternsValidation as ValidationFunc, + }, + ], + }, + /* Optional field configs */ + pattern_definitions: { + type: FIELD_TYPES.TEXT, + deserializer: to.jsonString, + serializer: from.optionalJson, + label: i18n.translate( + 'xpack.ingestPipelines.pipelineEditor.redactForm.patternDefinitionsLabel', + { + defaultMessage: 'Pattern definitions (optional)', + } + ), + helpText: i18n.translate( + 'xpack.ingestPipelines.pipelineEditor.redactForm.patternDefinitionsHelpText', + { + defaultMessage: + 'A map of pattern-name and pattern tuples defining custom patterns to be used by the processor. Patterns matching existing names will override the pre-existing definition.', + } + ), + validations: [ + { + validator: isJsonField( + i18n.translate( + 'xpack.ingestPipelines.pipelineEditor.redactForm.patternsDefinitionsInvalidJSONError', + { defaultMessage: 'Invalid JSON' } + ), + { + allowEmptyString: true, + } + ), + }, + ], + }, + + prefix: { + type: FIELD_TYPES.TEXT, + label: i18n.translate('xpack.ingestPipelines.pipelineEditor.redactForm.prefixLabel', { + defaultMessage: 'Prefix (optional)', + }), + deserializer: String, + serializer: from.undefinedIfValue(''), + helpText: ( + {'<'} }} + /> + ), + }, + + suffix: { + type: FIELD_TYPES.TEXT, + label: i18n.translate('xpack.ingestPipelines.pipelineEditor.redactForm.suffixLabel', { + defaultMessage: 'Suffix (optional)', + }), + deserializer: String, + serializer: from.undefinedIfValue(''), + helpText: ( + {'>'} }} + /> + ), + }, +}; + +export const Redact: FunctionComponent = () => { + return ( + <> + + + + {({ items, addItem, removeItem, error }) => { + return ( + + ); + }} + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx index d47f90abbd36d..cd53afedcc341 100644 --- a/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx +++ b/x-pack/plugins/ingest_pipelines/public/application/components/pipeline_editor/components/shared/map_processor_type_to_form.tsx @@ -37,6 +37,7 @@ import { Lowercase, NetworkDirection, Pipeline, + Redact, RegisteredDomain, Remove, Rename, @@ -577,6 +578,24 @@ export const mapProcessorTypeToDescriptor: MapProcessorTypeToDescriptor = { }, }), }, + redact: { + FieldsComponent: Redact, + docLinkPath: '/redact-processor.html', + label: i18n.translate('xpack.ingestPipelines.processors.label.redact', { + defaultMessage: 'Redact', + }), + typeDescription: i18n.translate('xpack.ingestPipelines.processors.description.redact', { + defaultMessage: + 'The Redact processor uses the Grok rules engine to obscure text in the input document matching the given Grok patterns.', + }), + getDefaultDescription: ({ field }) => + i18n.translate('xpack.ingestPipelines.processors.defaultDescription.redact', { + defaultMessage: 'Redact values from "{field}" that match a grok pattern', + values: { + field, + }, + }), + }, registered_domain: { FieldsComponent: RegisteredDomain, docLinkPath: '/registered-domain-processor.html', From 0dacbe7570d3adbefa509588b4775d5e770538e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Thu, 2 Mar 2023 10:45:37 -0500 Subject: [PATCH 129/131] =?UTF-8?q?[Profiling]=20Blank=20page=20when=20an?= =?UTF-8?q?=20invalid=20query=20string=20is=20given=20and=20when=E2=80=A6?= =?UTF-8?q?=20(#152493)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes https://github.com/elastic/prodfiler/issues/3049 404: Screenshot 2023-03-01 at 1 24 14 PM Error boundary: Screenshot 2023-03-01 at 1 24 41 PM --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/profiling/public/app.tsx | 33 +++++---- .../public/routing/router_error_boundary.tsx | 71 +++++++++++++++++++ x-pack/plugins/profiling/tsconfig.json | 1 + 3 files changed, 90 insertions(+), 15 deletions(-) create mode 100644 x-pack/plugins/profiling/public/routing/router_error_boundary.tsx diff --git a/x-pack/plugins/profiling/public/app.tsx b/x-pack/plugins/profiling/public/app.tsx index bf3a35d060f05..bf2f53aed0b0b 100644 --- a/x-pack/plugins/profiling/public/app.tsx +++ b/x-pack/plugins/profiling/public/app.tsx @@ -22,6 +22,7 @@ import { profilingRouter } from './routing'; import { Services } from './services'; import { ProfilingPluginPublicSetupDeps, ProfilingPluginPublicStartDeps } from './types'; import { ProfilingHeaderActionMenu } from './components/profiling_header_action_menu'; +import { RouterErrorBoundary } from './routing/router_error_boundary'; interface Props { profilingFetchServices: Services; @@ -82,21 +83,23 @@ function App({ - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/x-pack/plugins/profiling/public/routing/router_error_boundary.tsx b/x-pack/plugins/profiling/public/routing/router_error_boundary.tsx new file mode 100644 index 0000000000000..355ee1bd42f79 --- /dev/null +++ b/x-pack/plugins/profiling/public/routing/router_error_boundary.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { NotFoundRouteException } from '@kbn/typed-react-router-config'; +import { EuiErrorBoundary } from '@elastic/eui'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import React from 'react'; +import { NotFoundPrompt } from '@kbn/shared-ux-prompt-not-found'; +import { useLocation } from 'react-router-dom'; +import { i18n } from '@kbn/i18n'; +import { ProfilingPluginPublicStartDeps } from '../types'; + +export function RouterErrorBoundary({ children }: { children?: React.ReactNode }) { + const location = useLocation(); + return {children}; +} + +class ErrorBoundary extends React.Component<{ children?: React.ReactNode }, { error?: Error }, {}> { + public state: { error?: Error } = { + error: undefined, + }; + + static getDerivedStateFromError(error: Error) { + return { error }; + } + + render() { + if (this.state.error) { + return ; + } + + return this.props.children; + } +} + +const pageHeader = { + pageTitle: i18n.translate('xpack.profiling.universalProfiling', { + defaultMessage: 'Universal Profiling', + }), +}; + +function ErrorWithTemplate({ error }: { error: Error }) { + const { services } = useKibana(); + const { observability } = services; + + const ObservabilityPageTemplate = observability.navigation.PageTemplate; + + if (error instanceof NotFoundRouteException) { + return ( + + + + ); + } + + return ( + + + + + + ); +} + +function DummyComponent({ error }: { error: Error }) { + throw error; + return
    ; +} diff --git a/x-pack/plugins/profiling/tsconfig.json b/x-pack/plugins/profiling/tsconfig.json index b1044792b3209..6364139982415 100644 --- a/x-pack/plugins/profiling/tsconfig.json +++ b/x-pack/plugins/profiling/tsconfig.json @@ -40,6 +40,7 @@ "@kbn/core-http-request-handler-context-server", "@kbn/spaces-plugin", "@kbn/cloud-plugin", + "@kbn/shared-ux-prompt-not-found", // add references to other TypeScript projects the plugin depends on // requiredPlugins from ./kibana.json From 0c60d8edb7cc32c8574d1665f9d81863582aa666 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Thu, 2 Mar 2023 07:46:19 -0800 Subject: [PATCH 130/131] [DOCS] Refresh index threshold rule screenshots (#152310) --- .../rule-types-index-threshold-conditions.png | Bin 89825 -> 107796 bytes ...e-types-index-threshold-example-action.png | Bin 0 -> 143457 bytes ...es-index-threshold-example-aggregation.png | Bin 117091 -> 109900 bytes ...e-types-index-threshold-example-alerts.png | Bin 0 -> 219322 bytes ...pes-index-threshold-example-comparison.png | Bin 118367 -> 0 bytes ...types-index-threshold-example-grouping.png | Bin 63925 -> 81441 bytes ...le-types-index-threshold-example-index.png | Bin 107133 -> 70676 bytes ...-types-index-threshold-example-preview.png | Bin 92003 -> 96207 bytes ...ypes-index-threshold-example-threshold.png | Bin 64291 -> 50117 bytes ...ypes-index-threshold-example-timefield.png | Bin 181645 -> 0 bytes ...e-types-index-threshold-example-window.png | Bin 99880 -> 0 bytes .../rule-types-index-threshold-preview.png | Bin 175367 -> 0 bytes .../rule-types-index-threshold-select.png | Bin 126954 -> 108572 bytes docs/user/alerting/rule-types.asciidoc | 2 +- .../rule-types/index-threshold.asciidoc | 98 ++++++------ .../common/expression_items/group_by_over.tsx | 1 + x-pack/test/functional/services/rules/api.ts | 2 +- .../response_ops_docs/stack_alerting/index.ts | 3 + .../stack_alerting/index_threshold_rule.ts | 141 ++++++++++++++++++ 19 files changed, 203 insertions(+), 44 deletions(-) create mode 100644 docs/user/alerting/images/rule-types-index-threshold-example-action.png create mode 100644 docs/user/alerting/images/rule-types-index-threshold-example-alerts.png delete mode 100644 docs/user/alerting/images/rule-types-index-threshold-example-comparison.png delete mode 100644 docs/user/alerting/images/rule-types-index-threshold-example-timefield.png delete mode 100644 docs/user/alerting/images/rule-types-index-threshold-example-window.png delete mode 100644 docs/user/alerting/images/rule-types-index-threshold-preview.png create mode 100644 x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts diff --git a/docs/user/alerting/images/rule-types-index-threshold-conditions.png b/docs/user/alerting/images/rule-types-index-threshold-conditions.png index 062b0a426b5d83d37ca19ead31f0113bf14dc602..9aac7bd26c3c0533aab713df7b7cb8d00d3c76ad 100644 GIT binary patch literal 107796 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%0DcL`D^F;x=2|6 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 !0X8RHU}6iVE*8F@M+|I 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

    aiOOB@zP808{PRK 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 literal 0 HcmV?d00001 diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-aggregation.png b/docs/user/alerting/images/rule-types-index-threshold-example-aggregation.png index a43c4bf1f0d37eb2486e7ebdc863bd634bcdf690..68b21a62d8a9be5a12dc77d2597e3d3a3d7b3bbe 100644 GIT binary patch literal 109900 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 diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-alerts.png b/docs/user/alerting/images/rule-types-index-threshold-example-alerts.png new file mode 100644 index 0000000000000000000000000000000000000000..f183a3744db925c10290f2094ae25e4213a1a589 GIT binary patch literal 219322 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 G{r(q-3$1zp literal 0 HcmV?d00001 diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-comparison.png b/docs/user/alerting/images/rule-types-index-threshold-example-comparison.png deleted file mode 100644 index 5e7c65e1247d88e2562800f76e609a7bb2632cf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 118367 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

    CKRO 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

    )#4jFKJD>ib?)$=2bJ175IG@_eU4Pe$(Yd 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 diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-grouping.png b/docs/user/alerting/images/rule-types-index-threshold-example-grouping.png index 9f4c2ccbec3c0e4e7669997277a5a8041a61954a..aaed0acfbf863fffff05c85897d9b4300fbe51bb 100644 GIT binary patch literal 81441 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

    s8g8CM{kemi72U0cdQg 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 z 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.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%0DT9?Q1Yh3BlioFv0^X2mK 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

    YzkUtukU_(!+#@JQrvJb-eVB`b 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 HcfeeL% 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Ì+Fj*Yr=5dIB>?-E4xVXYG2)G@O-~c>K0+tJd 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

    }M|jUR%Tt0fs18 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 z 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 Y33a)?zsOS8M}Yq`F}!I&xaJh~U!*cS@c;k- literal 64291 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ï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%0A6L*X~xC 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 diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-window.png b/docs/user/alerting/images/rule-types-index-threshold-example-window.png deleted file mode 100644 index 9b8e9a47ae91e6ac37c54cf38ae1fd202b747a8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99880 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�E@XY41yVucsTS>t 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 JSRro~`acF>$zuQj diff --git a/docs/user/alerting/images/rule-types-index-threshold-select.png b/docs/user/alerting/images/rule-types-index-threshold-select.png index aeb9de279b3a1a5933a8baab069dd6893eae79f6..3a00f5da6aa1a3107cf3b319e1f7695e5579356a 100644 GIT binary patch literal 108572 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 diff --git a/docs/user/alerting/rule-types.asciidoc b/docs/user/alerting/rule-types.asciidoc index 7aab91b27e030..e33dc4214dd8c 100644 --- a/docs/user/alerting/rule-types.asciidoc +++ b/docs/user/alerting/rule-types.asciidoc @@ -86,6 +86,6 @@ Alerts associated with security rules are visible only in the {security-app}; they are not visible in *{stack-manage-app} > {rules-ui}*. ============================================== -include::rule-types/index-threshold.asciidoc[] +include::rule-types/index-threshold.asciidoc[leveloffset=+1] include::rule-types/es-query.asciidoc[leveloffset=+1] include::rule-types/geo-rule-types.asciidoc[] diff --git a/docs/user/alerting/rule-types/index-threshold.asciidoc b/docs/user/alerting/rule-types/index-threshold.asciidoc index 870c53f69b9a1..531d56ef7e697 100644 --- a/docs/user/alerting/rule-types/index-threshold.asciidoc +++ b/docs/user/alerting/rule-types/index-threshold.asciidoc @@ -1,21 +1,16 @@ -[role="xpack"] [[rule-type-index-threshold]] -=== Index threshold +== Index threshold The index threshold rule type runs an {es} query. It aggregates field values from documents, compares them to threshold values, and schedules actions to run when the thresholds are met. [float] -==== Create the rule - -Fill in the name and optional tags, then select *Index Threshold*. - -[float] -==== Define the conditions - -Define properties to detect the condition. +=== Rule conditions [role="screenshot"] -image::user/alerting/images/rule-types-index-threshold-conditions.png[Five clauses define the condition to detect] +image::user/alerting/images/rule-types-index-threshold-conditions.png[Defining index threshold rule conditions in {kib}] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. + +When you create an index threshold rule, you must define the conditions for the rule to detect. For example: Index:: This clause requires an *index or data view* and a *time field* that will be used for the *time window*. When:: This clause specifies how the value to be compared to the threshold is calculated. The value is calculated by aggregating a numeric field a the *time window*. The aggregation options are: `count`, `average`, `sum`, `min`, and `max`. When using `count` the document count is used, and an aggregation field is not necessary. @@ -23,78 +18,97 @@ Over/Grouped Over:: This clause lets you configure whether the aggregation is ap Threshold:: This clause defines a threshold value and a comparison operator (one of `is above`, `is above or equals`, `is below`, `is below or equals`, or `is between`). The result of the aggregation is compared to this threshold. Time window:: This clause determines how far back to search for documents, using the *time field* set in the *index* clause. Generally this value should be to a value higher than the *check every* value, to avoid gaps in detection. -If data is available and all clauses have been defined, a preview chart will render the threshold value and display a line chart showing the value for the last 30 intervals. This can provide an indication of recent values and their proximity to the threshold, and help you tune the clauses. - -[role="screenshot"] -image::user/alerting/images/rule-types-index-threshold-preview.png[Five clauses define the condition to detect] +If data is available and all clauses have been defined, a preview chart will render the threshold value and display a line chart showing the value for the last 30 intervals. This can provide an indication of recent values and their proximity to the threshold, and help you tune the clauses. [float] -==== Add action variables +[[action-variables-index-threshold]] +=== Action variables -<> to run when the rule condition is met. The following variables are specific to the index threshold rule. You can also specify <>. +The following action variables are specific to the index threshold rule. You can also specify <>. -`context.title`:: A preconstructed title for the rule. Example: `rule kibana sites - high egress met threshold`. +`context.conditions`:: A description of the threshold condition. Example: `count greater than 4` +`context.date`:: The date, in ISO format, that the rule met the threshold condition. Example: `2020-01-01T00:00:00.000Z`. +`context.group`:: The name of the action group associated with the threshold condition. Example: `threshold met`. `context.message`:: A preconstructed message for the rule. Example: + `rule 'kibana sites - high egress' is active for group 'threshold met':` + `- Value: 42` + `- Conditions Met: count greater than 4 over 5m` + `- Timestamp: 2020-01-01T00:00:00.000Z` - -`context.group`:: The name of the action group associated with the threshold condition. Example: `threshold met`. -`context.date`:: The date, in ISO format, that the rule met the threshold condition. Example: `2020-01-01T00:00:00.000Z`. +`context.title`:: A preconstructed title for the rule. Example: `rule kibana sites - high egress met threshold`. `context.value`:: The value for the rule that met the threshold condition. -`context.conditions`:: A description of the threshold condition. Example: `count greater than 4` [float] -==== Example +=== Example -In this example, you will use the {kib} <> to set up and tune the conditions on an index threshold rule. For this example, you want to detect when any of the top four sites serve more than 420,000 bytes over a 24 hour period. +In this example, you will use the {kib} <> to set up and tune the conditions on an index threshold rule. For this example, you want to detect when any of the top four sites serve more than 420,000 bytes over a 24 hour period. . Open the main menu, then click *{stack-manage-app} > {rules-ui}*. -. Create a new rule that is checked every four hours and triggers actions when the rule status changes. +. Create a new rule. + +.. Provide a rule name and select the **Index threshold** rule type. + [role="screenshot"] image::user/alerting/images/rule-types-index-threshold-select.png[Choosing an index threshold rule type] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. -. Select the **Index threshold** rule type. - -. Click *Index*, and set *Indices to query* to *kibana_sample_data_logs*. +.. Select an index. Click *Index*, and set *Indices to query* to `kibana_sample_data_logs`. Set the *Time field* to `@timestamp`. + [role="screenshot"] image::user/alerting/images/rule-types-index-threshold-example-index.png[Choosing an index] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. -. Set the *Time field* to *@timestamp*. -+ -[role="screenshot"] -image::user/alerting/images/rule-types-index-threshold-example-timefield.png[Choosing a time field] - -. To detect the number of bytes served during the time window, click *When* and select `sum` as the aggregation, and bytes as the field to aggregate. +.. To detect the number of bytes served during the time window, click *When* and select `sum` as the aggregation, and `bytes` as the field to aggregate. + [role="screenshot"] image::user/alerting/images/rule-types-index-threshold-example-aggregation.png[Choosing the aggregation] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. -. To detect the four sites that have the most traffic, click *Over* and select `top`, enter `4`, and select `host.keyword` as the field. +.. To detect the four sites that have the most traffic, click *Over* and select `top`, enter `4`, and select `host.keyword` as the field. + [role="screenshot"] image::user/alerting/images/rule-types-index-threshold-example-grouping.png[Choosing the groups] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. -. To trigger the rule when any of the top four sites exceeds 420,000 bytes over a 24 hour period, select `is above` and enter `420000`. +.. Define the condition. To trigger the rule when any of the top four sites exceeds 420,000 bytes over a 24 hour period, select `is above` and enter `420000`. Then click *For the last*, enter `24`, and select `hours`. + [role="screenshot"] image::user/alerting/images/rule-types-index-threshold-example-threshold.png[Setting the threshold] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. -. Finally, click *For the last*, enter `24` and select `hours` to complete the rule configuration. +.. Schedule the rule to check every four hours. + +-- [role="screenshot"] -image::user/alerting/images/rule-types-index-threshold-example-window.png[Setting the time window] +image::user/alerting/images/rule-types-index-threshold-example-preview.png[Setting the check interval] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. + +The preview chart will render showing the 24 hour sum of bytes at 4 hours intervals (the _check interval_) for the past 120 hours (the last 30 intervals). +-- -. The preview chart will render showing the 24 hour sum of bytes at 4 hours intervals (the *check every* interval) for the past 120 hours (the last 30 intervals). +.. Change the time window and observe the effect it has on the chart. Compare a 24 window to a 12 hour window. Notice the variability in the sum of bytes, due to different traffic levels during the day compared to at night. This variability would result in noisy rules, so the 24 hour window is better. The preview chart can help you find the right values for your rule. + +.. Define the actions for your rule. + +-- +You can add one or more actions to your rule to generate notifications when its conditions are met and when they are no longer met. For each action, you must select a connector, set the action frequency, and compose the notification details. +For example, add an action that uses a server log connector to write an entry to the Kibana server log: + [role="screenshot"] -image::user/alerting/images/rule-types-index-threshold-example-preview.png[Setting the time window] +image::user/alerting/images/rule-types-index-threshold-example-action.png[Add an action to the rule] +// NOTE: This is an autogenerated screenshot. Do not edit it directly. + +NOTE: The index threshold rule does not support alert summaries; therefore they do not appear in the action frequency options. + +The unique action variables that you can use in the notification are listed in <>. For more information, refer to <> and <>. +-- -. Change the time window and observe the effect it has on the chart. Compare a 24 window to a 12 hour window. Notice the variability in the sum of bytes, due to different traffic levels during the day compared to at night. This variability would result in noisy rules, so the 24 hour window is better. The preview chart can help you find the right values for your rule. +.. Save the rule. + +. Find the rule and view its details in *{stack-manage-app} > {rules-ui}*. For example, you can see the status of the rule and its alerts: + [role="screenshot"] -image::user/alerting/images/rule-types-index-threshold-example-comparison.png[Comparing two time windows] \ No newline at end of file +image::user/alerting/images/rule-types-index-threshold-example-alerts.png[View the list of alerts for the rule] + +. Delete or disable this example rule when it's no longer useful. In the detailed rule view, select *Delete rule* from the actions menu. + diff --git a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx index e20fdd1c1a0b7..0819f7541d1cc 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/expression_items/group_by_over.tsx @@ -185,6 +185,7 @@ export const GroupByExpression = ({ 0} error={errors.termSize}> { @@ -23,10 +24,12 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) { }); after(async () => { + await rules.api.deleteAllRules(); await actions.api.deleteAllConnectors(); }); loadTestFile(require.resolve('./list_view')); loadTestFile(require.resolve('./connector_types')); + loadTestFile(require.resolve('./index_threshold_rule')); }); } diff --git a/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts b/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.ts new file mode 100644 index 0000000000000..ec27e67f0874e --- /dev/null +++ b/x-pack/test/screenshot_creation/apps/response_ops_docs/stack_alerting/index_threshold_rule.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; 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 default function ({ getService, getPageObjects }: FtrProviderContext) { + const comboBox = getService('comboBox'); + const commonScreenshots = getService('commonScreenshots'); + const find = getService('find'); + const rules = getService('rules'); + const testSubjects = getService('testSubjects'); + const pageObjects = getPageObjects(['common', 'header']); + const screenshotDirectories = ['response_ops_docs', 'stack_alerting']; + + describe('index threshold rule', function () { + it('create rule screenshot', async () => { + await pageObjects.common.navigateToApp('triggersActions'); + await pageObjects.header.waitUntilLoadingHasFinished(); + await rules.common.clickCreateAlertButton(); + await testSubjects.setValue('ruleNameInput', 'kibana sites - high egress'); + await testSubjects.click('tagsComboBox'); + await testSubjects.setValue('tagsComboBox', 'sample-data'); + await testSubjects.click('solutionsFilterButton'); + await testSubjects.click('solutionstackAlertsFilterOption'); + await testSubjects.setValue('solutionsFilterButton', 'solutionstackAlertsFilterOption'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-select', + screenshotDirectories, + 1400, + 1024 + ); + + await testSubjects.click('.index-threshold-SelectOption'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-conditions', + screenshotDirectories, + 1400, + 1024 + ); + + await testSubjects.scrollIntoView('selectIndexExpression'); + await testSubjects.click('selectIndexExpression'); + const indexComboBox = await find.byCssSelector('#indexSelectSearchBox'); + await indexComboBox.click(); + await indexComboBox.type('kibana_sample_data_logs '); + const filterSelectItem = await find.byCssSelector(`.euiFilterSelectItem`); + await filterSelectItem.click(); + await testSubjects.click('thresholdAlertTimeFieldSelect'); + await testSubjects.setValue('thresholdAlertTimeFieldSelect', '@timestamp'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-example-index', + screenshotDirectories, + 1400, + 1024 + ); + await testSubjects.click('closePopover'); + + await testSubjects.click('whenExpression'); + await testSubjects.click('whenExpressionSelect'); + await testSubjects.setValue('whenExpressionSelect', 'sum()'); + await testSubjects.click('ofExpressionPopover'); + const ofComboBox = await find.byCssSelector('#ofField'); + await ofComboBox.click(); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-example-aggregation', + screenshotDirectories, + 1400, + 1024 + ); + await ofComboBox.type('bytes'); + const ofOptionsString = await comboBox.getOptionsList('availablefieldsOptionsComboBox'); + const ofOptions = ofOptionsString.trim().split('\n'); + expect(ofOptions.length > 0).to.be(true); + await comboBox.set('availablefieldsOptionsComboBox', ofOptions[0]); + + await testSubjects.click('groupByExpression'); + await testSubjects.click('overExpressionSelect'); + await testSubjects.setValue('overExpressionSelect', 'top'); + await testSubjects.setValue('fieldsNumberSelect', '4'); + await testSubjects.setValue('fieldsExpressionSelect', 'host.keyword'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-example-grouping', + screenshotDirectories, + 1400, + 1024 + ); + // need this two out of popup clicks to close them + const nameInput1 = await testSubjects.find('ruleNameInput'); + await nameInput1.click(); + + await testSubjects.click('thresholdPopover'); + await testSubjects.setValue('alertThresholdInput', '420000'); + await testSubjects.click('forLastExpression'); + await testSubjects.setValue('timeWindowSizeNumber', '24'); + await testSubjects.setValue('timeWindowUnitSelect', 'hours'); + // need this two out of popup clicks to close them + const nameInput2 = await testSubjects.find('ruleNameInput'); + await nameInput2.click(); + await testSubjects.scrollIntoView('thresholdPopover'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-example-threshold', + screenshotDirectories, + 1400, + 1024 + ); + + await testSubjects.setValue('intervalInput', '4'); + await testSubjects.setValue('intervalInputUnit', 'hours'); + // need this two out of popup clicks to close them + const nameInput3 = await testSubjects.find('ruleNameInput'); + await nameInput3.click(); + await testSubjects.scrollIntoView('alertVisualizationChart'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-example-preview', + screenshotDirectories, + 1400, + 1024 + ); + + await testSubjects.click('.server-log-alerting-ActionTypeSelectOption'); + await testSubjects.scrollIntoView('addAlertActionButton'); + await commonScreenshots.takeScreenshot( + 'rule-types-index-threshold-example-action', + screenshotDirectories, + 1400, + 1024 + ); + /* + * const saveButton = await testSubjects.find('saveRuleButton'); + * await saveButton.click(); + */ + const flyOutCancelButton = await testSubjects.find('euiFlyoutCloseButton'); + await flyOutCancelButton.click(); + }); + }); +} From 95c9b33633e01a49ff8080de8a4a6e96f48a5021 Mon Sep 17 00:00:00 2001 From: Yngrid Coello Date: Thu, 2 Mar 2023 17:08:11 +0100 Subject: [PATCH 131/131] [APM] Awaiting yellow status of the cluster when creating an anomaly detection jobs (#152563) When creating an anomaly detection job we were calling function `waitForIndexStatus` but actually we weren't awaiting for the result so the instruction had no effect in the creation flow. --- .../lib/anomaly_detection/create_anomaly_detection_jobs.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts b/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts index 85c9550fd230d..636c7b2fde323 100644 --- a/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts +++ b/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts @@ -136,12 +136,12 @@ async function createAnomalyDetectionJob({ ], }); - waitForIndexStatus({ + await waitForIndexStatus({ client: esClient, index: '.ml-*', timeout: DEFAULT_TIMEOUT, status: 'yellow', - }); + })(); return anomalyDetectionJob; });

    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 diff --git a/docs/user/alerting/images/rule-types-index-threshold-example-index.png b/docs/user/alerting/images/rule-types-index-threshold-example-index.png index b2f1c78f7add82aa0c619597174fda3d46e751b7..29a9c9520d69e5fe4d93beb872fec09991a15fa1 100644 GIT binary patch literal 70676 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