-
- {node.name}
-
- {metrics.map((metric) => {
- const metricName = SnapshotMetricTypeRT.is(metric.name) ? metric.name : 'custom';
- const name = SNAPSHOT_METRIC_TRANSLATIONS[metricName] || metricName;
- // if custom metric, find field and label from waffleOptionsContext result
- // because useSnapshot does not return it
- const customMetric =
- name === 'custom' ? customMetrics.find((item) => item.id === metric.name) : null;
- const formatter = customMetric
- ? createFormatterForMetric(customMetric)
- : createInventoryMetricFormatter({ type: metricName });
- return (
-
-
- {customMetric ? getCustomMetricLabel(customMetric) : name}
-
-
- {(metric.value && formatter(metric.value)) || '-'}
-
-
- );
- })}
+ const dataNode = first(nodes);
+ const metrics = (dataNode && dataNode.metrics) || [];
+ return (
+
+
+ {node.name}
- );
-
- return (
-
-
- {children}
-
-
- );
- }
-);
+ {metrics.map((metric) => {
+ const metricName = SnapshotMetricTypeRT.is(metric.name) ? metric.name : 'custom';
+ const name = SNAPSHOT_METRIC_TRANSLATIONS[metricName] || metricName;
+ // if custom metric, find field and label from waffleOptionsContext result
+ // because useSnapshot does not return it
+ const customMetric =
+ name === 'custom' ? customMetrics.find((item) => item.id === metric.name) : null;
+ const formatter = customMetric
+ ? createFormatterForMetric(customMetric)
+ : createInventoryMetricFormatter({ type: metricName });
+ return (
+
+
+ {customMetric ? getCustomMetricLabel(customMetric) : name}
+
+
+ {(metric.value && formatter(metric.value)) || '-'}
+
+
+ );
+ })}
+
+ );
+});
diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx
index e972f9ca4f345f..031b826265e16f 100644
--- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx
+++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx
@@ -11,7 +11,7 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { first } from 'lodash';
-import { EuiPopover } from '@elastic/eui';
+import { EuiPopover, EuiToolTip } from '@elastic/eui';
import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common';
import {
InfraWaffleMapBounds,
@@ -64,13 +64,10 @@ export class Node extends React.PureComponent
{
const nodeBorder = this.state.isOverlayOpen ? { border: 'solid 4px #000' } : undefined;
const button = (
- }
>
{
-
+
);
return (
diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts
index 12fe53fb426c0e..9948976b01ea13 100644
--- a/x-pack/plugins/infra/public/plugin.ts
+++ b/x-pack/plugins/infra/public/plugin.ts
@@ -63,39 +63,37 @@ export class Plugin implements InfraClientPluginClass {
euiIconType: 'logoObservability',
order: 8100,
appRoute: '/app/logs',
- meta: {
- // !! Need to be kept in sync with the routes in x-pack/plugins/infra/public/pages/logs/page_content.tsx
- searchDeepLinks: [
- {
- id: 'stream',
- title: i18n.translate('xpack.infra.logs.index.streamTabTitle', {
- defaultMessage: 'Stream',
- }),
- path: '/stream',
- },
- {
- id: 'anomalies',
- title: i18n.translate('xpack.infra.logs.index.anomaliesTabTitle', {
- defaultMessage: 'Anomalies',
- }),
- path: '/anomalies',
- },
- {
- id: 'log-categories',
- title: i18n.translate('xpack.infra.logs.index.logCategoriesBetaBadgeTitle', {
- defaultMessage: 'Categories',
- }),
- path: '/log-categories',
- },
- {
- id: 'settings',
- title: i18n.translate('xpack.infra.logs.index.settingsTabTitle', {
- defaultMessage: 'Settings',
- }),
- path: '/settings',
- },
- ],
- },
+ // !! Need to be kept in sync with the routes in x-pack/plugins/infra/public/pages/logs/page_content.tsx
+ deepLinks: [
+ {
+ id: 'stream',
+ title: i18n.translate('xpack.infra.logs.index.streamTabTitle', {
+ defaultMessage: 'Stream',
+ }),
+ path: '/stream',
+ },
+ {
+ id: 'anomalies',
+ title: i18n.translate('xpack.infra.logs.index.anomaliesTabTitle', {
+ defaultMessage: 'Anomalies',
+ }),
+ path: '/anomalies',
+ },
+ {
+ id: 'log-categories',
+ title: i18n.translate('xpack.infra.logs.index.logCategoriesBetaBadgeTitle', {
+ defaultMessage: 'Categories',
+ }),
+ path: '/log-categories',
+ },
+ {
+ id: 'settings',
+ title: i18n.translate('xpack.infra.logs.index.settingsTabTitle', {
+ defaultMessage: 'Settings',
+ }),
+ path: '/settings',
+ },
+ ],
category: DEFAULT_APP_CATEGORIES.observability,
mount: async (params: AppMountParameters) => {
// mount callback should not use setup dependencies, get start dependencies instead
@@ -115,32 +113,30 @@ export class Plugin implements InfraClientPluginClass {
order: 8200,
appRoute: '/app/metrics',
category: DEFAULT_APP_CATEGORIES.observability,
- meta: {
- // !! Need to be kept in sync with the routes in x-pack/plugins/infra/public/pages/metrics/index.tsx
- searchDeepLinks: [
- {
- id: 'inventory',
- title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', {
- defaultMessage: 'Inventory',
- }),
- path: '/inventory',
- },
- {
- id: 'metrics-explorer',
- title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', {
- defaultMessage: 'Metrics Explorer',
- }),
- path: '/explorer',
- },
- {
- id: 'settings',
- title: i18n.translate('xpack.infra.homePage.settingsTabTitle', {
- defaultMessage: 'Settings',
- }),
- path: '/settings',
- },
- ],
- },
+ // !! Need to be kept in sync with the routes in x-pack/plugins/infra/public/pages/metrics/index.tsx
+ deepLinks: [
+ {
+ id: 'inventory',
+ title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', {
+ defaultMessage: 'Inventory',
+ }),
+ path: '/inventory',
+ },
+ {
+ id: 'metrics-explorer',
+ title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', {
+ defaultMessage: 'Metrics Explorer',
+ }),
+ path: '/explorer',
+ },
+ {
+ id: 'settings',
+ title: i18n.translate('xpack.infra.homePage.settingsTabTitle', {
+ defaultMessage: 'Settings',
+ }),
+ path: '/settings',
+ },
+ ],
mount: async (params: AppMountParameters) => {
// mount callback should not use setup dependencies, get start dependencies instead
const [coreStart, pluginsStart] = await core.getStartServices();
diff --git a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap
index 339fb5a7ab68f3..08b3393fafe482 100644
--- a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap
+++ b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap
@@ -33,6 +33,9 @@ Object {
"description": Array [
"",
],
+ "fillOpacity": Array [
+ 0.3,
+ ],
"fittingFunction": Array [
"Carry",
],
diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.tsx
index 006727b05b9056..e3b4565913ad87 100644
--- a/x-pack/plugins/lens/public/xy_visualization/expression.tsx
+++ b/x-pack/plugins/lens/public/xy_visualization/expression.tsx
@@ -196,6 +196,12 @@ export const xyChart: ExpressionFunctionDefinition<
defaultMessage: 'Define how curve type is rendered for a line chart',
}),
},
+ fillOpacity: {
+ types: ['number'],
+ help: i18n.translate('xpack.lens.xyChart.fillOpacity.help', {
+ defaultMessage: 'Define the area chart fill opacity',
+ }),
+ },
hideEndzones: {
types: ['boolean'],
default: false,
@@ -812,6 +818,7 @@ export function XYChart({
visible: !xAccessor,
radius: 5,
},
+ ...(args.fillOpacity && { area: { opacity: args.fillOpacity } }),
},
lineSeriesStyle: {
point: {
diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts
index dea6b1a7be0c57..269f10159892f4 100644
--- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts
+++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts
@@ -149,6 +149,7 @@ export const buildExpression = (
],
fittingFunction: [state.fittingFunction || 'None'],
curveType: [state.curveType || 'LINEAR'],
+ fillOpacity: [state.fillOpacity || 0.3],
yLeftExtent: [
{
type: 'expression',
diff --git a/x-pack/plugins/lens/public/xy_visualization/types.ts b/x-pack/plugins/lens/public/xy_visualization/types.ts
index ea28b492477c18..531b034b532425 100644
--- a/x-pack/plugins/lens/public/xy_visualization/types.ts
+++ b/x-pack/plugins/lens/public/xy_visualization/types.ts
@@ -464,6 +464,7 @@ export interface XYArgs {
tickLabelsVisibilitySettings?: AxesSettingsConfig & { type: 'lens_xy_tickLabelsConfig' };
gridlinesVisibilitySettings?: AxesSettingsConfig & { type: 'lens_xy_gridlinesConfig' };
curveType?: XYCurveType;
+ fillOpacity?: number;
hideEndzones?: boolean;
}
@@ -485,6 +486,7 @@ export interface XYState {
tickLabelsVisibilitySettings?: AxesSettingsConfig;
gridlinesVisibilitySettings?: AxesSettingsConfig;
curveType?: XYCurveType;
+ fillOpacity?: number;
hideEndzones?: boolean;
}
diff --git a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/fill_opacity_option.test.tsx b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/fill_opacity_option.test.tsx
new file mode 100644
index 00000000000000..3ba29e4f72c837
--- /dev/null
+++ b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/fill_opacity_option.test.tsx
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { mountWithIntl as mount, shallowWithIntl as shallow } from '@kbn/test/jest';
+import { EuiRange } from '@elastic/eui';
+import { FillOpacityOption } from './fill_opacity_option';
+
+describe('Line curve option', () => {
+ it('should show currently selected opacity value', () => {
+ const component = shallow();
+
+ expect(component.find(EuiRange).prop('value')).toEqual(0.3);
+ });
+
+ it('should show fill opacity option when enabled', () => {
+ const component = mount(
+
+ );
+
+ expect(component.exists('[data-test-subj="lnsFillOpacity"]')).toEqual(true);
+ });
+
+ it('should hide curve option when disabled', () => {
+ const component = mount(
+
+ );
+
+ expect(component.exists('[data-test-subj="lnsFillOpacity"]')).toEqual(false);
+ });
+});
diff --git a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/fill_opacity_option.tsx b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/fill_opacity_option.tsx
new file mode 100644
index 00000000000000..eb8d35c54a99b9
--- /dev/null
+++ b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/fill_opacity_option.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license 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 { EuiFormRow, EuiRange } from '@elastic/eui';
+import { useDebouncedValue } from '../../shared_components';
+
+export interface FillOpacityOptionProps {
+ /**
+ * Currently selected value
+ */
+ value: number;
+ /**
+ * Callback on display option change
+ */
+ onChange: (value: number) => void;
+ /**
+ * Flag for rendering or not the component
+ */
+ isFillOpacityEnabled?: boolean;
+}
+
+export const FillOpacityOption: React.FC = ({
+ onChange,
+ value,
+ isFillOpacityEnabled = true,
+}) => {
+ const { inputValue, handleInputChange } = useDebouncedValue({ value, onChange });
+ return isFillOpacityEnabled ? (
+ <>
+
+ {
+ handleInputChange(Number(e.currentTarget.value));
+ }}
+ />
+
+ >
+ ) : null;
+};
diff --git a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/missing_values_option.tsx b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/missing_values_option.tsx
index fb6ecec4d28013..a683d4fbf514c3 100644
--- a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/missing_values_option.tsx
+++ b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/missing_values_option.tsx
@@ -7,7 +7,14 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
-import { EuiButtonGroup, EuiFormRow, EuiIconTip, EuiSuperSelect, EuiText } from '@elastic/eui';
+import {
+ EuiButtonGroup,
+ EuiFormRow,
+ EuiIconTip,
+ EuiSuperSelect,
+ EuiText,
+ EuiSpacer,
+} from '@elastic/eui';
import { FittingFunction, fittingFunctionDefinitions } from '../fitting_functions';
import { ValueLabelConfig } from '../types';
@@ -133,6 +140,7 @@ export const MissingValuesOptions: React.FC = ({
/>
)}
+
>
);
};
diff --git a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.test.tsx b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.test.tsx
index e7ec395312bff4..b46ad1940491e6 100644
--- a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.test.tsx
+++ b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.test.tsx
@@ -14,6 +14,7 @@ import { State } from '../types';
import { VisualOptionsPopover } from './visual_options_popover';
import { ToolbarPopover } from '../../shared_components';
import { MissingValuesOptions } from './missing_values_option';
+import { FillOpacityOption } from './fill_opacity_option';
describe('Visual options popover', () => {
let frame: FramePublicAPI;
@@ -74,6 +75,22 @@ describe('Visual options popover', () => {
expect(component.find(MissingValuesOptions).prop('isFittingEnabled')).toEqual(false);
});
+ it('should not disable the fill opacity for percentage area charts', () => {
+ const state = testState();
+ const component = shallow(
+
+ );
+
+ expect(component.find(FillOpacityOption).prop('isFillOpacityEnabled')).toEqual(true);
+ });
+
it('should not disable the visual options for percentage area charts', () => {
const state = testState();
const component = shallow(
@@ -128,6 +145,40 @@ describe('Visual options popover', () => {
expect(component.find(MissingValuesOptions).prop('isFittingEnabled')).toEqual(false);
});
+ it('should hide the fill opacity option for bar series', () => {
+ const state = testState();
+ const component = shallow(
+
+ );
+
+ expect(component.find(FillOpacityOption).prop('isFillOpacityEnabled')).toEqual(false);
+ });
+
+ it('should hide the fill opacity option for line series', () => {
+ const state = testState();
+ const component = shallow(
+
+ );
+
+ expect(component.find(FillOpacityOption).prop('isFillOpacityEnabled')).toEqual(false);
+ });
+
it('should show the popover and display field enabled for bar and horizontal_bar series', () => {
const state = testState();
diff --git a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx
index b8b89f146bdc07..b07feb85892e53 100644
--- a/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx
+++ b/x-pack/plugins/lens/public/xy_visualization/visual_options_popover/visual_options_popover.tsx
@@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n';
import { ToolbarPopover } from '../../shared_components';
import { MissingValuesOptions } from './missing_values_option';
import { LineCurveOption } from './line_curve_option';
+import { FillOpacityOption } from './fill_opacity_option';
import { XYState } from '../types';
import { hasHistogramSeries } from '../state_helpers';
import { ValidLayer } from '../types';
@@ -61,6 +62,10 @@ export const VisualOptionsPopover: React.FC = ({
['bar', 'bar_horizontal'].includes(seriesType)
);
+ const hasAreaSeries = state?.layers.some(({ seriesType }) =>
+ ['area_stacked', 'area', 'area_percentage_stacked'].includes(seriesType)
+ );
+
const isHistogramSeries = Boolean(
hasHistogramSeries(state?.layers as ValidLayer[], datasourceLayers)
);
@@ -110,6 +115,17 @@ export const VisualOptionsPopover: React.FC = ({
setState({ ...state, fittingFunction: newVal });
}}
/>
+
+ {
+ setState({
+ ...state,
+ fillOpacity: newValue,
+ });
+ }}
+ />
);
diff --git a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts
index 4554c34b97c555..aff33778258fed 100644
--- a/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts
+++ b/x-pack/plugins/lens/public/xy_visualization/xy_suggestions.ts
@@ -524,6 +524,7 @@ function buildSuggestion({
valueLabels: currentState?.valueLabels || 'hide',
fittingFunction: currentState?.fittingFunction || 'None',
curveType: currentState?.curveType,
+ fillOpacity: currentState?.fillOpacity,
xTitle: currentState?.xTitle,
yTitle: currentState?.yTitle,
yRightTitle: currentState?.yRightTitle,
diff --git a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts
index 973f5822cae2b2..1566241e7351e0 100644
--- a/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts
+++ b/x-pack/plugins/lists/server/services/exception_lists/exception_list_client.mock.ts
@@ -32,9 +32,11 @@ export class ExceptionListClientMock extends ExceptionListClient {
public createEndpointList = jest.fn().mockResolvedValue(getExceptionListSchemaMock());
}
-export const getExceptionListClientMock = (): ExceptionListClient => {
+export const getExceptionListClientMock = (
+ savedObject?: ReturnType
+): ExceptionListClient => {
const mock = new ExceptionListClientMock({
- savedObjectsClient: savedObjectsClientMock.create(),
+ savedObjectsClient: savedObject ? savedObject : savedObjectsClientMock.create(),
user: 'elastic',
});
return mock;
diff --git a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx
index e0cfe978bf45cf..851fd583b4251f 100644
--- a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx
+++ b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx
@@ -30,7 +30,6 @@ import { registerLayerWizards } from '../../classes/layers/load_layer_wizards';
import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property';
import { GeoFieldWithIndex } from '../../components/geo_field_with_index';
import { MapRefreshConfig } from '../../../common/descriptor_types';
-import 'mapbox-gl/dist/mapbox-gl.css';
const RENDER_COMPLETE_EVENT = 'renderComplete';
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 ac3e72545033fb..355e49564620dd 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
@@ -7,9 +7,8 @@
import _ from 'lodash';
import React, { Component } from 'react';
-import { Map as MapboxMap, MapboxOptions, MapMouseEvent } from 'mapbox-gl';
-// @ts-expect-error
-import mapboxgl from 'mapbox-gl/dist/mapbox-gl-csp';
+import type { Map as MapboxMap, MapboxOptions, MapMouseEvent } from 'mapbox-gl';
+
// @ts-expect-error
import { spritesheet } from '@elastic/maki';
import sprites1 from '@elastic/maki/dist/sprite@1.png';
@@ -17,6 +16,9 @@ import sprites2 from '@elastic/maki/dist/sprite@2.png';
import { Adapters } from 'src/plugins/inspector/public';
import { Filter } from 'src/plugins/data/public';
import { ActionExecutionContext, Action } from 'src/plugins/ui_actions/public';
+
+import { mapboxgl } from '@kbn/mapbox-gl';
+
import { DrawFilterControl } from './draw_control';
import { ScaleControl } from './scale_control';
import { TooltipControl } from './tooltip_control';
@@ -45,13 +47,6 @@ import { GeoFieldWithIndex } from '../../components/geo_field_with_index';
import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property';
import { MapExtentState } from '../../actions';
import { TileStatusTracker } from './tile_status_tracker';
-// @ts-expect-error
-import mbRtlPlugin from '!!file-loader!@mapbox/mapbox-gl-rtl-text/mapbox-gl-rtl-text.min.js';
-// @ts-expect-error
-import mbWorkerUrl from '!!file-loader!mapbox-gl/dist/mapbox-gl-csp-worker';
-
-mapboxgl.workerUrl = mbWorkerUrl;
-mapboxgl.setRTLTextPlugin(mbRtlPlugin);
export interface Props {
isMapReady: boolean;
diff --git a/x-pack/plugins/ml/public/register_helper/register_search_links/register_search_links.ts b/x-pack/plugins/ml/public/register_helper/register_search_links/register_search_links.ts
index 6c219340da817d..dd3ca0bb8fa309 100644
--- a/x-pack/plugins/ml/public/register_helper/register_search_links/register_search_links.ts
+++ b/x-pack/plugins/ml/public/register_helper/register_search_links/register_search_links.ts
@@ -9,20 +9,18 @@ import { i18n } from '@kbn/i18n';
import { BehaviorSubject } from 'rxjs';
import { AppUpdater } from 'src/core/public';
-import { getSearchDeepLinks } from './search_deep_links';
+import { getDeepLinks } from './search_deep_links';
export function registerSearchLinks(
appUpdater: BehaviorSubject,
isFullLicense: boolean
) {
appUpdater.next(() => ({
- meta: {
- keywords: [
- i18n.translate('xpack.ml.keyword.ml', {
- defaultMessage: 'ML',
- }),
- ],
- searchDeepLinks: getSearchDeepLinks(isFullLicense),
- },
+ keywords: [
+ i18n.translate('xpack.ml.keyword.ml', {
+ defaultMessage: 'ML',
+ }),
+ ],
+ deepLinks: getDeepLinks(isFullLicense),
}));
}
diff --git a/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts b/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts
index d248df90889897..d682a93fa274c4 100644
--- a/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts
+++ b/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts
@@ -7,35 +7,35 @@
import { i18n } from '@kbn/i18n';
-import type { AppSearchDeepLink } from 'src/core/public';
+import type { AppDeepLink } from 'src/core/public';
import { ML_PAGES } from '../../../common/constants/ml_url_generator';
-const OVERVIEW_LINK_SEARCH_DEEP_LINK: AppSearchDeepLink = {
- id: 'mlOverviewSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.overview', {
+const OVERVIEW_LINK_DEEP_LINK: AppDeepLink = {
+ id: 'mlOverviewDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.overview', {
defaultMessage: 'Overview',
}),
path: `/${ML_PAGES.OVERVIEW}`,
};
-const ANOMALY_DETECTION_SEARCH_DEEP_LINK: AppSearchDeepLink = {
- id: 'mlAnomalyDetectionSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.anomalyDetection', {
+const ANOMALY_DETECTION_DEEP_LINK: AppDeepLink = {
+ id: 'mlAnomalyDetectionDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.anomalyDetection', {
defaultMessage: 'Anomaly Detection',
}),
path: `/${ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE}`,
};
-const DATA_FRAME_ANALYTICS_SEARCH_DEEP_LINK: AppSearchDeepLink = {
- id: 'mlDataFrameAnalyticsSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.dataFrameAnalytics', {
+const DATA_FRAME_ANALYTICS_DEEP_LINK: AppDeepLink = {
+ id: 'mlDataFrameAnalyticsDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.dataFrameAnalytics', {
defaultMessage: 'Data Frame Analytics',
}),
path: `/${ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE}`,
- searchDeepLinks: [
+ deepLinks: [
{
- id: 'mlTrainedModelsSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.trainedModels', {
+ id: 'mlTrainedModelsDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.trainedModels', {
defaultMessage: 'Trained Models',
}),
path: `/${ML_PAGES.DATA_FRAME_ANALYTICS_MODELS_MANAGE}`,
@@ -43,47 +43,47 @@ const DATA_FRAME_ANALYTICS_SEARCH_DEEP_LINK: AppSearchDeepLink = {
],
};
-const DATA_VISUALIZER_SEARCH_DEEP_LINK: AppSearchDeepLink = {
- id: 'mlDataVisualizerSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.dataVisualizer', {
+const DATA_VISUALIZER_DEEP_LINK: AppDeepLink = {
+ id: 'mlDataVisualizerDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.dataVisualizer', {
defaultMessage: 'Data Visualizer',
}),
path: `/${ML_PAGES.DATA_VISUALIZER}`,
};
-const FILE_UPLOAD_SEARCH_DEEP_LINK: AppSearchDeepLink = {
- id: 'mlFileUploadSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.fileUpload', {
+const FILE_UPLOAD_DEEP_LINK: AppDeepLink = {
+ id: 'mlFileUploadDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.fileUpload', {
defaultMessage: 'File Upload',
}),
path: `/${ML_PAGES.DATA_VISUALIZER_FILE}`,
};
-const INDEX_DATA_VISUALIZER_SEARCH_DEEP_LINK: AppSearchDeepLink = {
- id: 'mlIndexDataVisualizerSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.indexDataVisualizer', {
+const INDEX_DATA_VISUALIZER_DEEP_LINK: AppDeepLink = {
+ id: 'mlIndexDataVisualizerDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.indexDataVisualizer', {
defaultMessage: 'Index Data Visualizer',
}),
path: `/${ML_PAGES.DATA_VISUALIZER_INDEX_SELECT}`,
};
-const SETTINGS_SEARCH_DEEP_LINK: AppSearchDeepLink = {
- id: 'mlSettingsSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.settings', {
+const SETTINGS_DEEP_LINK: AppDeepLink = {
+ id: 'mlSettingsDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.settings', {
defaultMessage: 'Settings',
}),
path: `/${ML_PAGES.SETTINGS}`,
- searchDeepLinks: [
+ deepLinks: [
{
- id: 'mlCalendarSettingsSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.calendarSettings', {
+ id: 'mlCalendarSettingsDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.calendarSettings', {
defaultMessage: 'Calendars',
}),
path: `/${ML_PAGES.CALENDARS_MANAGE}`,
},
{
- id: 'mlFilterListsSettingsSearchDeepLink',
- title: i18n.translate('xpack.ml.searchDeepLink.filterListsSettings', {
+ id: 'mlFilterListsSettingsDeepLink',
+ title: i18n.translate('xpack.ml.deepLink.filterListsSettings', {
defaultMessage: 'Filter Lists',
}),
path: `/${ML_PAGES.SETTINGS}`, // Link to settings page as read only users cannot view filter lists.
@@ -91,19 +91,19 @@ const SETTINGS_SEARCH_DEEP_LINK: AppSearchDeepLink = {
],
};
-export function getSearchDeepLinks(isFullLicense: boolean) {
- const deepLinks: AppSearchDeepLink[] = [
- DATA_VISUALIZER_SEARCH_DEEP_LINK,
- FILE_UPLOAD_SEARCH_DEEP_LINK,
- INDEX_DATA_VISUALIZER_SEARCH_DEEP_LINK,
+export function getDeepLinks(isFullLicense: boolean) {
+ const deepLinks: AppDeepLink[] = [
+ DATA_VISUALIZER_DEEP_LINK,
+ FILE_UPLOAD_DEEP_LINK,
+ INDEX_DATA_VISUALIZER_DEEP_LINK,
];
if (isFullLicense === true) {
deepLinks.push(
- OVERVIEW_LINK_SEARCH_DEEP_LINK,
- ANOMALY_DETECTION_SEARCH_DEEP_LINK,
- DATA_FRAME_ANALYTICS_SEARCH_DEEP_LINK,
- SETTINGS_SEARCH_DEEP_LINK
+ OVERVIEW_LINK_DEEP_LINK,
+ ANOMALY_DETECTION_DEEP_LINK,
+ DATA_FRAME_ANALYTICS_DEEP_LINK,
+ SETTINGS_DEEP_LINK
);
}
diff --git a/x-pack/plugins/reporting/server/lib/store/report_ilm_policy.ts b/x-pack/plugins/reporting/server/lib/store/report_ilm_policy.ts
new file mode 100644
index 00000000000000..f4cd69a0331d7d
--- /dev/null
+++ b/x-pack/plugins/reporting/server/lib/store/report_ilm_policy.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 { PutLifecycleRequest } from '@elastic/elasticsearch/api/types';
+
+export const reportingIlmPolicy: PutLifecycleRequest['body'] = {
+ policy: {
+ phases: {
+ hot: {
+ actions: {},
+ },
+ },
+ },
+};
diff --git a/x-pack/plugins/reporting/server/lib/store/store.test.ts b/x-pack/plugins/reporting/server/lib/store/store.test.ts
index 7f96433fcc6ceb..fa35240dfc8fbd 100644
--- a/x-pack/plugins/reporting/server/lib/store/store.test.ts
+++ b/x-pack/plugins/reporting/server/lib/store/store.test.ts
@@ -7,6 +7,7 @@
import type { DeeplyMockedKeys } from '@kbn/utility-types/jest';
import { ElasticsearchClient } from 'src/core/server';
+import { elasticsearchServiceMock } from 'src/core/server/mocks';
import { ReportingCore } from '../../';
import {
createMockConfigSchema,
@@ -16,6 +17,8 @@ import {
import { Report, ReportDocument } from './report';
import { ReportingStore } from './store';
+const { createApiResponse } = elasticsearchServiceMock;
+
describe('ReportingStore', () => {
const mockLogger = createMockLevelLogger();
let mockCore: ReportingCore;
@@ -403,4 +406,40 @@ describe('ReportingStore', () => {
]
`);
});
+
+ describe('start', () => {
+ it('creates an ILM policy for managing reporting indices if there is not already one', async () => {
+ mockEsClient.ilm.getLifecycle.mockRejectedValueOnce(createApiResponse({ statusCode: 404 }));
+ mockEsClient.ilm.putLifecycle.mockResolvedValueOnce(createApiResponse());
+
+ const store = new ReportingStore(mockCore, mockLogger);
+ await store.start();
+
+ expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ policy: 'kibana-reporting' });
+ expect(mockEsClient.ilm.putLifecycle.mock.calls[0][0]).toMatchInlineSnapshot(`
+ Object {
+ "body": Object {
+ "policy": Object {
+ "phases": Object {
+ "hot": Object {
+ "actions": Object {},
+ },
+ },
+ },
+ },
+ "policy": "kibana-reporting",
+ }
+ `);
+ });
+
+ it('does not create an ILM policy for managing reporting indices if one already exists', async () => {
+ mockEsClient.ilm.getLifecycle.mockResolvedValueOnce(createApiResponse());
+
+ const store = new ReportingStore(mockCore, mockLogger);
+ await store.start();
+
+ expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ policy: 'kibana-reporting' });
+ expect(mockEsClient.ilm.putLifecycle).not.toHaveBeenCalled();
+ });
+ });
});
diff --git a/x-pack/plugins/reporting/server/lib/store/store.ts b/x-pack/plugins/reporting/server/lib/store/store.ts
index fc7bd9c23d7693..9fb203fd5627ab 100644
--- a/x-pack/plugins/reporting/server/lib/store/store.ts
+++ b/x-pack/plugins/reporting/server/lib/store/store.ts
@@ -14,6 +14,7 @@ import { ReportTaskParams } from '../tasks';
import { indexTimestamp } from './index_timestamp';
import { mapping } from './mapping';
import { Report, ReportDocument, ReportSource } from './report';
+import { reportingIlmPolicy } from './report_ilm_policy';
/*
* When searching for long-pending reports, we get a subset of fields
@@ -71,19 +72,22 @@ export class ReportingStore {
return exists;
}
- const indexSettings = {
- number_of_shards: 1,
- auto_expand_replicas: '0-1',
- };
- const body = {
- settings: indexSettings,
- mappings: {
- properties: mapping,
- },
- };
-
try {
- await client.indices.create({ index: indexName, body });
+ await client.indices.create({
+ index: indexName,
+ body: {
+ settings: {
+ number_of_shards: 1,
+ auto_expand_replicas: '0-1',
+ lifecycle: {
+ name: this.ilmPolicyName,
+ },
+ },
+ mappings: {
+ properties: mapping,
+ },
+ },
+ });
return true;
} catch (error) {
@@ -130,6 +134,44 @@ export class ReportingStore {
return client.indices.refresh({ index });
}
+ private readonly ilmPolicyName = 'kibana-reporting';
+
+ private async doesIlmPolicyExist(): Promise {
+ const client = await this.getClient();
+ try {
+ await client.ilm.getLifecycle({ policy: this.ilmPolicyName });
+ return true;
+ } catch (e) {
+ if (e.statusCode === 404) {
+ return false;
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Function to be called during plugin start phase. This ensures the environment is correctly
+ * configured for storage of reports.
+ */
+ public async start() {
+ const client = await this.getClient();
+ try {
+ if (await this.doesIlmPolicyExist()) {
+ this.logger.debug(`Found ILM policy ${this.ilmPolicyName}; skipping creation.`);
+ return;
+ }
+ this.logger.info(`Creating ILM policy for managing reporting indices: ${this.ilmPolicyName}`);
+ await client.ilm.putLifecycle({
+ policy: this.ilmPolicyName,
+ body: reportingIlmPolicy,
+ });
+ } catch (e) {
+ this.logger.error('Error in start phase');
+ this.logger.error(e.body.error);
+ throw e;
+ }
+ }
+
public async addReport(report: Report): Promise {
let index = report._index;
if (!index) {
diff --git a/x-pack/plugins/reporting/server/plugin.ts b/x-pack/plugins/reporting/server/plugin.ts
index fc52e10dd0cf94..efe1d9450bef31 100644
--- a/x-pack/plugins/reporting/server/plugin.ts
+++ b/x-pack/plugins/reporting/server/plugin.ts
@@ -107,6 +107,9 @@ export class ReportingPlugin
logger: this.logger,
});
+ // Note: this must be called after ReportingCore.pluginStart
+ await store.start();
+
this.logger.debug('Start complete');
})().catch((e) => {
this.logger.error(`Error in Reporting start, reporting may not function properly`);
diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts
index 8d1cc4ca2c1f07..6195dd61a79841 100644
--- a/x-pack/plugins/security_solution/common/experimental_features.ts
+++ b/x-pack/plugins/security_solution/common/experimental_features.ts
@@ -14,7 +14,6 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues;
const allowedExperimentalValues = Object.freeze({
trustedAppsByPolicyEnabled: false,
metricsEntitiesEnabled: false,
- eventFilteringEnabled: false,
hostIsolationEnabled: false,
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
index 5af5a8adf95b7f..aeee7077ec9c04 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
@@ -23,7 +23,7 @@ import { unmappedRule } from '../../objects/rule';
import { DETECTIONS_URL } from '../../urls/navigation';
describe('Alert details with unmapped fields', () => {
- before(() => {
+ beforeEach(() => {
cleanKibana();
esArchiverLoad('unmapped_fields');
loginAndWaitForPageWithoutDateRange(DETECTIONS_URL);
diff --git a/x-pack/plugins/security_solution/public/app/search/index.test.ts b/x-pack/plugins/security_solution/public/app/search/index.test.ts
index d6c36e89558d02..328395f9b85c9e 100644
--- a/x-pack/plugins/security_solution/public/app/search/index.test.ts
+++ b/x-pack/plugins/security_solution/public/app/search/index.test.ts
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import { getSearchDeepLinksAndKeywords } from '.';
+import { getDeepLinksAndKeywords } from '.';
import { SecurityPageName } from '../../../common/constants';
describe('public search functions', () => {
@@ -13,10 +13,9 @@ describe('public search functions', () => {
const platinumLicense = 'platinum';
for (const pageName of Object.values(SecurityPageName)) {
expect.assertions(Object.values(SecurityPageName).length * 2);
- const basicLinkCount =
- getSearchDeepLinksAndKeywords(pageName, basicLicense).searchDeepLinks?.length || 0;
- const platinumLinks = getSearchDeepLinksAndKeywords(pageName, platinumLicense);
- expect(platinumLinks.searchDeepLinks?.length).toBeGreaterThanOrEqual(basicLinkCount);
+ const basicLinkCount = getDeepLinksAndKeywords(pageName, basicLicense).deepLinks?.length || 0;
+ const platinumLinks = getDeepLinksAndKeywords(pageName, platinumLicense);
+ expect(platinumLinks.deepLinks?.length).toBeGreaterThanOrEqual(basicLinkCount);
expect(platinumLinks.keywords?.length).not.toBe(null);
}
});
diff --git a/x-pack/plugins/security_solution/public/app/search/index.ts b/x-pack/plugins/security_solution/public/app/search/index.ts
index 110356269e8917..93d931fc4d1370 100644
--- a/x-pack/plugins/security_solution/public/app/search/index.ts
+++ b/x-pack/plugins/security_solution/public/app/search/index.ts
@@ -11,7 +11,7 @@ import { Subject } from 'rxjs';
import { AppUpdater } from 'src/core/public';
import { LicenseType } from '../../../../licensing/common/types';
import { SecuritySubPluginNames, SecurityDeepLinks } from '../types';
-import { AppMeta } from '../../../../../../src/core/public';
+import { App } from '../../../../../../src/core/public';
const securityDeepLinks: SecurityDeepLinks = {
detections: {
@@ -198,10 +198,10 @@ const subpluginKeywords: { [key in SecuritySubPluginNames]: string[] } = {
* @param subPluginName SubPluginName of the app to retrieve meta information for.
* @param licenseType optional string for license level, if not provided basic is assumed.
*/
-export function getSearchDeepLinksAndKeywords(
+export function getDeepLinksAndKeywords(
subPluginName: SecuritySubPluginNames,
licenseType?: LicenseType
-): AppMeta {
+): Pick {
const baseRoutes = [...securityDeepLinks[subPluginName].base];
if (
licenseType === 'gold' ||
@@ -214,29 +214,27 @@ export function getSearchDeepLinksAndKeywords(
if (premiumRoutes !== undefined) {
return {
keywords: subpluginKeywords[subPluginName],
- searchDeepLinks: [...baseRoutes, ...premiumRoutes],
+ deepLinks: [...baseRoutes, ...premiumRoutes],
};
}
}
return {
keywords: subpluginKeywords[subPluginName],
- searchDeepLinks: baseRoutes,
+ deepLinks: baseRoutes,
};
}
/**
* A function that updates a subplugin's meta property as appropriate when license level changes.
- * @param subPluginName SubPluginName of the app to register searchDeepLinks for
+ * @param subPluginName SubPluginName of the app to register deepLinks for
* @param appUpdater an instance of appUpdater$ observable to update search links when needed.
* @param licenseType A string representing the current license level.
*/
-export function registerSearchLinks(
+export function registerDeepLinks(
subPluginName: SecuritySubPluginNames,
appUpdater?: Subject,
licenseType?: LicenseType
) {
if (appUpdater !== undefined) {
- appUpdater.next(() => ({
- meta: getSearchDeepLinksAndKeywords(subPluginName, licenseType),
- }));
+ appUpdater.next(() => ({ ...getDeepLinksAndKeywords(subPluginName, licenseType) }));
}
}
diff --git a/x-pack/plugins/security_solution/public/app/types.ts b/x-pack/plugins/security_solution/public/app/types.ts
index a617c6f14b9c48..77d5b99e1c3a3b 100644
--- a/x-pack/plugins/security_solution/public/app/types.ts
+++ b/x-pack/plugins/security_solution/public/app/types.ts
@@ -17,7 +17,7 @@ import {
CombinedState,
} from 'redux';
-import { AppMountParameters, AppSearchDeepLink } from '../../../../../src/core/public';
+import { AppMountParameters, AppDeepLink } from '../../../../../src/core/public';
import { StartServices } from '../types';
/**
@@ -58,8 +58,8 @@ export type SecuritySubPluginKeyStore =
export type SecuritySubPluginNames = keyof typeof SecurityPageName;
interface SecurityDeepLink {
- base: AppSearchDeepLink[];
- premium?: AppSearchDeepLink[];
+ base: AppDeepLink[];
+ premium?: AppDeepLink[];
}
export type SecurityDeepLinks = { [key in SecuritySubPluginNames]: SecurityDeepLink };
diff --git a/x-pack/plugins/security_solution/public/common/mock/global_state.ts b/x-pack/plugins/security_solution/public/common/mock/global_state.ts
index b1b3147f4f4941..af278b09e719c4 100644
--- a/x-pack/plugins/security_solution/public/common/mock/global_state.ts
+++ b/x-pack/plugins/security_solution/public/common/mock/global_state.ts
@@ -40,7 +40,6 @@ export const mockGlobalState: State = {
{ id: 'error-id-2', title: 'title-2', message: ['error-message-2'] },
],
enableExperimental: {
- eventFilteringEnabled: false,
trustedAppsByPolicyEnabled: false,
metricsEntitiesEnabled: false,
hostIsolationEnabled: false,
diff --git a/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx b/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx
index 02fbb4f4b02962..72a6de2a2de8d1 100644
--- a/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx
+++ b/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx
@@ -25,7 +25,6 @@ import {
getEventFiltersListPath,
getTrustedAppsListPath,
} from '../common/routing';
-import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features';
/** Ensure that all flyouts z-index in Administation area show the flyout header */
const EuiPanelStyled = styled(EuiPanel)`
@@ -44,7 +43,6 @@ interface AdministrationListPageProps {
export const AdministrationListPage: FC = memo(
({ beta, title, subtitle, actions, children, headerBackComponent, ...otherProps }) => {
- const isEventFilteringEnabled = useIsExperimentalFeatureEnabled('eventFilteringEnabled');
const badgeOptions = !beta ? undefined : { beta: true, text: BETA_BADGE_LABEL };
return (
@@ -77,18 +75,14 @@ export const AdministrationListPage: FC
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx
index cec3e34d9c98fd..c594aaa5c7e19d 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx
@@ -64,7 +64,6 @@ describe('When event filters delete modal is shown', () => {
};
waitForAction = mockedContext.middlewareSpy.waitForAction;
- mockedContext.setExperimentalFlag({ eventFilteringEnabled: true });
});
it('should display name of event filter in body message', async () => {
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.test.tsx
index 2fbabad746cad7..465f92dfda767f 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.test.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.test.tsx
@@ -41,7 +41,6 @@ describe('When on the Event Filters List Page', () => {
waitForAction = mockedContext.middlewareSpy.waitForAction;
act(() => {
- mockedContext.setExperimentalFlag({ eventFilteringEnabled: true });
history.push('/event_filters');
});
});
diff --git a/x-pack/plugins/security_solution/public/management/pages/index.tsx b/x-pack/plugins/security_solution/public/management/pages/index.tsx
index 4be75117daedad..8273f1a6e55c20 100644
--- a/x-pack/plugins/security_solution/public/management/pages/index.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/index.tsx
@@ -25,7 +25,6 @@ import { SecurityPageName } from '../../../common/constants';
import { SpyRoute } from '../../common/utils/route/spy_routes';
import { useIngestEnabledCheck } from '../../common/hooks/endpoint/ingest_enabled';
import { EventFiltersContainer } from './event_filters';
-import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features';
const NoPermissions = memo(() => {
return (
@@ -58,7 +57,6 @@ NoPermissions.displayName = 'NoPermissions';
export const ManagementContainer = memo(() => {
const history = useHistory();
- const isEventFilteringEnabled = useIsExperimentalFeatureEnabled('eventFilteringEnabled');
const { allEnabled: isIngestEnabled } = useIngestEnabledCheck();
if (!isIngestEnabled) {
@@ -70,10 +68,7 @@ export const ManagementContainer = memo(() => {
-
- {isEventFilteringEnabled && (
-
- )}
+
{
const [coreStart, startPlugins] = await core.getStartServices();
const { timelines: subPlugin } = await this.subPlugins();
@@ -300,7 +300,7 @@ export class Plugin implements IPlugin {
const [coreStart, startPlugins] = await core.getStartServices();
const { management: managementSubPlugin } = await this.subPlugins();
@@ -366,19 +366,19 @@ export class Plugin implements IPlugin {
if (currentLicense.type !== undefined) {
- registerSearchLinks(SecurityPageName.network, this.networkUpdater$, currentLicense.type);
- registerSearchLinks(
+ registerDeepLinks(SecurityPageName.network, this.networkUpdater$, currentLicense.type);
+ registerDeepLinks(
SecurityPageName.detections,
this.detectionsUpdater$,
currentLicense.type
);
- registerSearchLinks(SecurityPageName.hosts, this.hostsUpdater$, currentLicense.type);
- registerSearchLinks(SecurityPageName.case, this.caseUpdater$, currentLicense.type);
+ registerDeepLinks(SecurityPageName.hosts, this.hostsUpdater$, currentLicense.type);
+ registerDeepLinks(SecurityPageName.case, this.caseUpdater$, currentLicense.type);
}
});
}
diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx
index 0824dea0803ba9..2053b9a0da942d 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/actions/index.tsx
@@ -21,7 +21,6 @@ import { EventsTdContent } from '../../styles';
import * as i18n from '../translations';
import { DEFAULT_ICON_BUTTON_WIDTH } from '../../helpers';
import { useShallowEqualSelector } from '../../../../../common/hooks/use_selector';
-import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features';
import { AddToCaseAction } from '../../../../../cases/components/timeline_actions/add_to_case_action';
import { TimelineId, TimelineTabs } from '../../../../../../common/types/timeline';
import { timelineSelectors } from '../../../../store/timeline';
@@ -89,8 +88,6 @@ const ActionsComponent: React.FC = ({
const emptyNotes: string[] = [];
const getTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []);
- const isEventFilteringEnabled = useIsExperimentalFeatureEnabled('eventFilteringEnabled');
-
const handleSelectEvent = useCallback(
(event: React.ChangeEvent) =>
onRowSelected({
@@ -116,8 +113,8 @@ const ActionsComponent: React.FC = ({
const eventType = getEventType(ecsData);
const isEventContextMenuEnabled = useMemo(
- () => isEventFilteringEnabled && !!ecsData.event?.kind && ecsData.event?.kind[0] === 'event',
- [ecsData.event?.kind, isEventFilteringEnabled]
+ () => !!ecsData.event?.kind && ecsData.event?.kind[0] === 'event',
+ [ecsData.event?.kind]
);
return (
diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts
index 85857301d5f399..cda42bdf3f585e 100644
--- a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/mocks.ts
@@ -92,6 +92,36 @@ export const createPackagePolicyWithInitialManifestMock = (): PackagePolicy => {
artifact_manifest: {
value: {
artifacts: {
+ 'endpoint-eventfilterlist-linux-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-linux-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-macos-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-windows-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256: 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256: 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
'endpoint-exceptionlist-macos-v1': {
compression_algorithm: 'zlib',
encryption_algorithm: 'none',
diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts
index f471ace617a6dc..e0bbfc351a20f1 100644
--- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts
@@ -69,13 +69,16 @@ export interface ManifestManagerMockOptions {
export const buildManifestManagerMockOptions = (
opts: Partial
-): ManifestManagerMockOptions => ({
- cache: new LRU({ max: 10, maxAge: 1000 * 60 * 60 }),
- exceptionListClient: listMock.getExceptionListClient(),
- packagePolicyService: createPackagePolicyServiceMock(),
- savedObjectsClient: savedObjectsClientMock.create(),
- ...opts,
-});
+): ManifestManagerMockOptions => {
+ const savedObjectMock = savedObjectsClientMock.create();
+ return {
+ cache: new LRU({ max: 10, maxAge: 1000 * 60 * 60 }),
+ exceptionListClient: listMock.getExceptionListClient(savedObjectMock),
+ packagePolicyService: createPackagePolicyServiceMock(),
+ savedObjectsClient: savedObjectMock,
+ ...opts,
+ };
+};
export const buildManifestManagerContextMock = (
opts: Partial
diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts
index e1de39482428d7..7719dbf30c72bf 100644
--- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts
@@ -65,6 +65,9 @@ describe('ManifestManager', () => {
const ARTIFACT_NAME_TRUSTED_APPS_MACOS = 'endpoint-trustlist-macos-v1';
const ARTIFACT_NAME_TRUSTED_APPS_WINDOWS = 'endpoint-trustlist-windows-v1';
const ARTIFACT_NAME_TRUSTED_APPS_LINUX = 'endpoint-trustlist-linux-v1';
+ const ARTIFACT_NAME_EVENT_FILTERS_MACOS = 'endpoint-eventfilterlist-macos-v1';
+ const ARTIFACT_NAME_EVENT_FILTERS_WINDOWS = 'endpoint-eventfilterlist-windows-v1';
+ const ARTIFACT_NAME_EVENT_FILTERS_LINUX = 'endpoint-eventfilterlist-linux-v1';
let ARTIFACTS: InternalArtifactCompleteSchema[] = [];
let ARTIFACTS_BY_ID: { [K: string]: InternalArtifactCompleteSchema } = {};
@@ -219,6 +222,9 @@ describe('ManifestManager', () => {
ARTIFACT_NAME_TRUSTED_APPS_MACOS,
ARTIFACT_NAME_TRUSTED_APPS_WINDOWS,
ARTIFACT_NAME_TRUSTED_APPS_LINUX,
+ ARTIFACT_NAME_EVENT_FILTERS_MACOS,
+ ARTIFACT_NAME_EVENT_FILTERS_WINDOWS,
+ ARTIFACT_NAME_EVENT_FILTERS_LINUX,
];
const getArtifactIds = (artifacts: InternalArtifactSchema[]) => [
@@ -249,6 +255,11 @@ describe('ManifestManager', () => {
context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({});
context.packagePolicyService.listIds = mockPolicyListIdsResponse([TEST_POLICY_ID_1]);
+ context.savedObjectsClient.create = jest
+ .fn()
+ .mockImplementation((type: string, object: InternalManifestSchema) => ({
+ attributes: object,
+ }));
const manifest = await manifestManager.buildNewManifest();
expect(manifest?.getSchemaVersion()).toStrictEqual('v1');
@@ -257,7 +268,7 @@ describe('ManifestManager', () => {
const artifacts = manifest.getAllArtifacts();
- expect(artifacts.length).toBe(6);
+ expect(artifacts.length).toBe(9);
expect(getArtifactIds(artifacts)).toStrictEqual(SUPPORTED_ARTIFACT_NAMES);
expect(artifacts.every(isCompressed)).toBe(true);
@@ -280,6 +291,11 @@ describe('ManifestManager', () => {
[ENDPOINT_LIST_ID]: { macos: [exceptionListItem] },
[ENDPOINT_TRUSTED_APPS_LIST_ID]: { linux: [trustedAppListItem] },
});
+ context.savedObjectsClient.create = jest
+ .fn()
+ .mockImplementation((type: string, object: InternalManifestSchema) => ({
+ attributes: object,
+ }));
context.packagePolicyService.listIds = mockPolicyListIdsResponse([TEST_POLICY_ID_1]);
const manifest = await manifestManager.buildNewManifest();
@@ -290,7 +306,7 @@ describe('ManifestManager', () => {
const artifacts = manifest.getAllArtifacts();
- expect(artifacts.length).toBe(6);
+ expect(artifacts.length).toBe(9);
expect(getArtifactIds(artifacts)).toStrictEqual(SUPPORTED_ARTIFACT_NAMES);
expect(artifacts.every(isCompressed)).toBe(true);
@@ -304,6 +320,9 @@ describe('ManifestManager', () => {
expect(await uncompressArtifact(artifacts[5])).toStrictEqual({
entries: translateToEndpointExceptions([trustedAppListItem], 'v1'),
});
+ expect(await uncompressArtifact(artifacts[6])).toStrictEqual({ entries: [] });
+ expect(await uncompressArtifact(artifacts[7])).toStrictEqual({ entries: [] });
+ expect(await uncompressArtifact(artifacts[8])).toStrictEqual({ entries: [] });
for (const artifact of artifacts) {
expect(manifest.isDefaultArtifact(artifact)).toBe(true);
@@ -323,7 +342,11 @@ describe('ManifestManager', () => {
[ENDPOINT_LIST_ID]: { macos: [exceptionListItem] },
});
context.packagePolicyService.listIds = mockPolicyListIdsResponse([TEST_POLICY_ID_1]);
-
+ context.savedObjectsClient.create = jest
+ .fn()
+ .mockImplementation((type: string, object: InternalManifestSchema) => ({
+ attributes: object,
+ }));
const oldManifest = await manifestManager.buildNewManifest();
context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({
@@ -339,7 +362,7 @@ describe('ManifestManager', () => {
const artifacts = manifest.getAllArtifacts();
- expect(artifacts.length).toBe(6);
+ expect(artifacts.length).toBe(9);
expect(getArtifactIds(artifacts)).toStrictEqual(SUPPORTED_ARTIFACT_NAMES);
expect(artifacts.every(isCompressed)).toBe(true);
@@ -351,6 +374,9 @@ describe('ManifestManager', () => {
expect(await uncompressArtifact(artifacts[5])).toStrictEqual({
entries: translateToEndpointExceptions([trustedAppListItem], 'v1'),
});
+ expect(await uncompressArtifact(artifacts[6])).toStrictEqual({ entries: [] });
+ expect(await uncompressArtifact(artifacts[7])).toStrictEqual({ entries: [] });
+ expect(await uncompressArtifact(artifacts[8])).toStrictEqual({ entries: [] });
for (const artifact of artifacts) {
expect(manifest.isDefaultArtifact(artifact)).toBe(true);
@@ -384,6 +410,12 @@ describe('ManifestManager', () => {
TEST_POLICY_ID_2,
]);
+ context.savedObjectsClient.create = jest
+ .fn()
+ .mockImplementation((type: string, object: InternalManifestSchema) => ({
+ attributes: object,
+ }));
+
const manifest = await manifestManager.buildNewManifest();
expect(manifest?.getSchemaVersion()).toStrictEqual('v1');
@@ -392,7 +424,7 @@ describe('ManifestManager', () => {
const artifacts = manifest.getAllArtifacts();
- expect(artifacts.length).toBe(7);
+ expect(artifacts.length).toBe(10);
expect(getArtifactIds(artifacts)).toStrictEqual(SUPPORTED_ARTIFACT_NAMES);
expect(artifacts.every(isCompressed)).toBe(true);
@@ -412,6 +444,9 @@ describe('ManifestManager', () => {
'v1'
),
});
+ expect(await uncompressArtifact(artifacts[7])).toStrictEqual({ entries: [] });
+ expect(await uncompressArtifact(artifacts[8])).toStrictEqual({ entries: [] });
+ expect(await uncompressArtifact(artifacts[9])).toStrictEqual({ entries: [] });
for (const artifact of artifacts.slice(0, 5)) {
expect(manifest.isDefaultArtifact(artifact)).toBe(true);
diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts
index fe4aba165d2bda..6c25b6152938f7 100644
--- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts
@@ -361,10 +361,7 @@ export class ManifestManager {
const results = await Promise.all([
this.buildExceptionListArtifacts(),
this.buildTrustedAppsArtifacts(),
- // If Endpoint Event Filtering feature is ON, then add in the exceptions for them
- ...(this.experimentalFeatures.eventFilteringEnabled
- ? [this.buildEventFiltersArtifacts()]
- : []),
+ this.buildEventFiltersArtifacts(),
]);
const manifest = new Manifest({
diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.test.tsx b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.test.tsx
index 4474b9f288570e..e43db6b86f8b90 100644
--- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.test.tsx
+++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/index.test.tsx
@@ -32,7 +32,6 @@ const mockDeps = {
experimentalFeatures: {
trustedAppsByPolicyEnabled: false,
metricsEntitiesEnabled: false,
- eventFilteringEnabled: false,
hostIsolationEnabled: false,
},
service: {} as EndpointAppContextService,
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index 134f58236cfee3..af6cdd1d672a17 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -15978,16 +15978,16 @@
"xpack.ml.ruleEditor.selectRuleAction.orText": "OR ",
"xpack.ml.ruleEditor.typicalAppliesTypeText": "通常",
"xpack.ml.sampleDataLinkLabel": "ML ジョブ",
- "xpack.ml.searchDeepLink.anomalyDetection": "異常検知",
- "xpack.ml.searchDeepLink.calendarSettings": "カレンダー",
- "xpack.ml.searchDeepLink.dataFrameAnalytics": "データフレーム分析",
- "xpack.ml.searchDeepLink.dataVisualizer": "データビジュアライザー",
- "xpack.ml.searchDeepLink.fileUpload": "ファイルアップロード",
- "xpack.ml.searchDeepLink.filterListsSettings": "フィルターリスト",
- "xpack.ml.searchDeepLink.indexDataVisualizer": "インデックスデータビジュアライザー",
- "xpack.ml.searchDeepLink.overview": "概要",
- "xpack.ml.searchDeepLink.settings": "設定",
- "xpack.ml.searchDeepLink.trainedModels": "学習済みモデル",
+ "xpack.ml.deepLink.anomalyDetection": "異常検知",
+ "xpack.ml.deepLink.calendarSettings": "カレンダー",
+ "xpack.ml.deepLink.dataFrameAnalytics": "データフレーム分析",
+ "xpack.ml.deepLink.dataVisualizer": "データビジュアライザー",
+ "xpack.ml.deepLink.fileUpload": "ファイルアップロード",
+ "xpack.ml.deepLink.filterListsSettings": "フィルターリスト",
+ "xpack.ml.deepLink.indexDataVisualizer": "インデックスデータビジュアライザー",
+ "xpack.ml.deepLink.overview": "概要",
+ "xpack.ml.deepLink.settings": "設定",
+ "xpack.ml.deepLink.trainedModels": "学習済みモデル",
"xpack.ml.settings.anomalyDetection.anomalyDetectionTitle": "異常検知",
"xpack.ml.settings.anomalyDetection.calendarsText": "システム停止日や祝日など、異常値を生成したくないイベントについては、カレンダーに予定されているイベントのリストを登録できます。",
"xpack.ml.settings.anomalyDetection.calendarsTitle": "カレンダー",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 67677f86ddbf78..c8376b72daef17 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -16203,16 +16203,16 @@
"xpack.ml.ruleEditor.selectRuleAction.orText": "或 ",
"xpack.ml.ruleEditor.typicalAppliesTypeText": "典型",
"xpack.ml.sampleDataLinkLabel": "ML 作业",
- "xpack.ml.searchDeepLink.anomalyDetection": "异常检测",
- "xpack.ml.searchDeepLink.calendarSettings": "日历",
- "xpack.ml.searchDeepLink.dataFrameAnalytics": "数据帧分析",
- "xpack.ml.searchDeepLink.dataVisualizer": "数据可视化工具",
- "xpack.ml.searchDeepLink.fileUpload": "文件上传",
- "xpack.ml.searchDeepLink.filterListsSettings": "筛选列表",
- "xpack.ml.searchDeepLink.indexDataVisualizer": "索引数据可视化工具",
- "xpack.ml.searchDeepLink.overview": "概览",
- "xpack.ml.searchDeepLink.settings": "设置",
- "xpack.ml.searchDeepLink.trainedModels": "已训练模型",
+ "xpack.ml.deepLink.anomalyDetection": "异常检测",
+ "xpack.ml.deepLink.calendarSettings": "日历",
+ "xpack.ml.deepLink.dataFrameAnalytics": "数据帧分析",
+ "xpack.ml.deepLink.dataVisualizer": "数据可视化工具",
+ "xpack.ml.deepLink.fileUpload": "文件上传",
+ "xpack.ml.deepLink.filterListsSettings": "筛选列表",
+ "xpack.ml.deepLink.indexDataVisualizer": "索引数据可视化工具",
+ "xpack.ml.deepLink.overview": "概览",
+ "xpack.ml.deepLink.settings": "设置",
+ "xpack.ml.deepLink.trainedModels": "已训练模型",
"xpack.ml.settings.anomalyDetection.anomalyDetectionTitle": "异常检测",
"xpack.ml.settings.anomalyDetection.calendarsSummaryCount": "您有 {calendarsCountBadge} 个{calendarsCount, plural, other {日历}}",
"xpack.ml.settings.anomalyDetection.calendarsText": "日志包含不应生成异常的已计划事件列表,例如已计划系统中断或公共假期。",
diff --git a/x-pack/plugins/uptime/public/apps/plugin.ts b/x-pack/plugins/uptime/public/apps/plugin.ts
index 0832274f0785a1..80a131676951e4 100644
--- a/x-pack/plugins/uptime/public/apps/plugin.ts
+++ b/x-pack/plugins/uptime/public/apps/plugin.ts
@@ -104,28 +104,26 @@ export class UptimePlugin
order: 8400,
title: PLUGIN.TITLE,
category: DEFAULT_APP_CATEGORIES.observability,
- meta: {
- keywords: [
- 'Synthetics',
- 'pings',
- 'checks',
- 'availability',
- 'response duration',
- 'response time',
- 'outside in',
- 'reachability',
- 'reachable',
- 'digital',
- 'performance',
- 'web performance',
- 'web perf',
- ],
- searchDeepLinks: [
- { id: 'Down monitors', title: 'Down monitors', path: '/?statusFilter=down' },
- { id: 'Certificates', title: 'TLS Certificates', path: '/certificates' },
- { id: 'Settings', title: 'Settings', path: '/settings' },
- ],
- },
+ keywords: [
+ 'Synthetics',
+ 'pings',
+ 'checks',
+ 'availability',
+ 'response duration',
+ 'response time',
+ 'outside in',
+ 'reachability',
+ 'reachable',
+ 'digital',
+ 'performance',
+ 'web performance',
+ 'web perf',
+ ],
+ deepLinks: [
+ { id: 'Down monitors', title: 'Down monitors', path: '/?statusFilter=down' },
+ { id: 'Certificates', title: 'TLS Certificates', path: '/certificates' },
+ { id: 'Settings', title: 'Settings', path: '/settings' },
+ ],
mount: async (params: AppMountParameters) => {
const [coreStart, corePlugins] = await core.getStartServices();
diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts
index 1cc7c87f3a1a84..7578abbad33e75 100644
--- a/x-pack/test/functional/apps/infra/home_page.ts
+++ b/x-pack/test/functional/apps/infra/home_page.ts
@@ -38,9 +38,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
after(async () => await esArchiver.unload('infra/metrics_and_logs'));
- it('renders the waffle map for dates with data', async () => {
+ it('renders the waffle map and tooltips for dates with data', async () => {
await pageObjects.infraHome.goToTime(DATE_WITH_DATA);
await pageObjects.infraHome.getWaffleMap();
+ await pageObjects.infraHome.getWaffleMapTooltips();
});
it('renders an empty data prompt for dates with no data', async () => {
diff --git a/x-pack/test/functional/apps/lens/index.ts b/x-pack/test/functional/apps/lens/index.ts
index ab7cee13ffebda..d0466b8814fec1 100644
--- a/x-pack/test/functional/apps/lens/index.ts
+++ b/x-pack/test/functional/apps/lens/index.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { FtrProviderContext } from '../../ftr_provider_context.d';
+import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService, loadTestFile }: FtrProviderContext) {
const browser = getService('browser');
diff --git a/x-pack/test/functional/ftr_provider_context.d.ts b/x-pack/test/functional/ftr_provider_context.ts
similarity index 74%
rename from x-pack/test/functional/ftr_provider_context.d.ts
rename to x-pack/test/functional/ftr_provider_context.ts
index 24f5087ef7fe2f..e757164fa1de92 100644
--- a/x-pack/test/functional/ftr_provider_context.d.ts
+++ b/x-pack/test/functional/ftr_provider_context.ts
@@ -5,9 +5,10 @@
* 2.0.
*/
-import { GenericFtrProviderContext } from '@kbn/test';
+import { GenericFtrProviderContext, GenericFtrService } from '@kbn/test';
import { pageObjects } from './page_objects';
import { services } from './services';
export type FtrProviderContext = GenericFtrProviderContext;
+export class FtrService extends GenericFtrService {}
diff --git a/x-pack/test/functional/page_objects/infra_home_page.ts b/x-pack/test/functional/page_objects/infra_home_page.ts
index 04dfbe5da00024..2f4575d45cc20f 100644
--- a/x-pack/test/functional/page_objects/infra_home_page.ts
+++ b/x-pack/test/functional/page_objects/infra_home_page.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import expect from '@kbn/expect/expect.js';
import testSubjSelector from '@kbn/test-subj-selector';
import { FtrProviderContext } from '../ftr_provider_context';
@@ -34,6 +35,34 @@ export function InfraHomePageProvider({ getService }: FtrProviderContext) {
return await testSubjects.find('waffleMap');
},
+ async getWaffleMapTooltips() {
+ const node = await testSubjects.findAll('nodeContainer');
+ await node[0].moveMouseTo();
+ const tooltip = await testSubjects.find('conditionalTooltipContent-demo-stack-redis-01');
+ const metrics = await tooltip.findAllByTestSubject('conditionalTooltipContent-metric');
+ const values = await tooltip.findAllByTestSubject('conditionalTooltipContent-value');
+ expect(await metrics[0].getVisibleText()).to.be('CPU usage');
+ expect(await values[0].getVisibleText()).to.be('1%');
+ expect(await metrics[1].getVisibleText()).to.be('Memory usage');
+ expect(await values[1].getVisibleText()).to.be('15.9%');
+ expect(await metrics[2].getVisibleText()).to.be('Outbound traffic');
+ expect(await values[2].getVisibleText()).to.be('71.9kbit/s');
+ expect(await metrics[3].getVisibleText()).to.be('Inbound traffic');
+ expect(await values[3].getVisibleText()).to.be('25.6kbit/s');
+ await node[1].moveMouseTo();
+ const tooltip2 = await testSubjects.find('conditionalTooltipContent-demo-stack-nginx-01');
+ const metrics2 = await tooltip2.findAllByTestSubject('conditionalTooltipContent-metric');
+ const values2 = await tooltip2.findAllByTestSubject('conditionalTooltipContent-value');
+ expect(await metrics2[0].getVisibleText()).to.be('CPU usage');
+ expect(await values2[0].getVisibleText()).to.be('1.1%');
+ expect(await metrics2[1].getVisibleText()).to.be('Memory usage');
+ expect(await values2[1].getVisibleText()).to.be('18%');
+ expect(await metrics2[2].getVisibleText()).to.be('Outbound traffic');
+ expect(await values2[2].getVisibleText()).to.be('256.3kbit/s');
+ expect(await metrics2[3].getVisibleText()).to.be('Inbound traffic');
+ expect(await values2[3].getVisibleText()).to.be('255.1kbit/s');
+ },
+
async openInvenotrySwitcher() {
await testSubjects.click('openInventorySwitcher');
return await testSubjects.find('goToHost');
diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
index d8bc9f6444f646..44348d1ad0d9c4 100644
--- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
+++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_details.ts
@@ -248,6 +248,42 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
relative_url:
'/api/fleet/artifacts/endpoint-trustlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
},
+ 'endpoint-eventfilterlist-linux-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-linux-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-macos-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-windows-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
},
// The manifest version could have changed when the Policy was updated because the
// policy details page ensures that a save action applies the udpated policy on top
@@ -416,6 +452,42 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
relative_url:
'/api/fleet/artifacts/endpoint-trustlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
},
+ 'endpoint-eventfilterlist-linux-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-linux-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-macos-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-windows-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
},
// The manifest version could have changed when the Policy was updated because the
// policy details page ensures that a save action applies the udpated policy on top
@@ -582,6 +654,42 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
relative_url:
'/api/fleet/artifacts/endpoint-trustlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
},
+ 'endpoint-eventfilterlist-linux-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-linux-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-macos-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-macos-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
+ 'endpoint-eventfilterlist-windows-v1': {
+ compression_algorithm: 'zlib',
+ decoded_sha256:
+ 'd801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ decoded_size: 14,
+ encoded_sha256:
+ 'f8e6afa1d5662f5b37f83337af774b5785b5b7f1daee08b7b00c2d6813874cda',
+ encoded_size: 22,
+ encryption_algorithm: 'none',
+ relative_url:
+ '/api/fleet/artifacts/endpoint-eventfilterlist-windows-v1/d801aa1fb7ddcc330a5e3173372ea6af4a3d08ec58074478e85aa5603e926658',
+ },
},
// The manifest version could have changed when the Policy was updated because the
// policy details page ensures that a save action applies the udpated policy on top
diff --git a/yarn.lock b/yarn.lock
index f1f421e2a766f5..9967cedea9fde1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2678,6 +2678,10 @@
version "0.0.0"
uid ""
+"@kbn/mapbox-gl@link:bazel-bin/packages/kbn-mapbox-gl/npm_module":
+ version "0.0.0"
+ uid ""
+
"@kbn/monaco@link:packages/kbn-monaco":
version "0.0.0"
uid ""