From 1f891cc67aabd6078a39f880e9799cb8a7c51ad2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?=
Date: Mon, 10 Jan 2022 16:53:08 +0100
Subject: [PATCH 01/19] Bump backport to 6.1.5 (#122505)
* Bump backport to 6.1.5
* Remove default values
---
.github/workflows/backport.yml | 2 --
package.json | 2 +-
yarn.lock | 8 ++++----
3 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
index 5ba208a45766e..d126ea6ec9b38 100644
--- a/.github/workflows/backport.yml
+++ b/.github/workflows/backport.yml
@@ -39,5 +39,3 @@ jobs:
github_token: ${{secrets.KIBANAMACHINE_TOKEN}}
commit_user: kibanamachine
commit_email: 42973632+kibanamachine@users.noreply.github.com
- auto_merge: 'true'
- auto_merge_method: 'squash'
diff --git a/package.json b/package.json
index 0118e28918310..9f89b9845ae52 100644
--- a/package.json
+++ b/package.json
@@ -712,7 +712,7 @@
"babel-plugin-require-context-hook": "^1.0.0",
"babel-plugin-styled-components": "^2.0.2",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
- "backport": "^6.1.3",
+ "backport": "6.1.5",
"callsites": "^3.1.0",
"chai": "3.5.0",
"chance": "1.0.18",
diff --git a/yarn.lock b/yarn.lock
index e3adc81008ffc..f35058f15cd8a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8656,10 +8656,10 @@ bach@^1.0.0:
async-settle "^1.0.0"
now-and-later "^2.0.0"
-backport@^6.1.3:
- version "6.1.3"
- resolved "https://registry.yarnpkg.com/backport/-/backport-6.1.3.tgz#48a0a8b8eadf422c475f816199390ef06fad16e0"
- integrity sha512-LMSXgUOFI9G/Eu4hZDaC7uQwmpedGSxihxVpVcQYwxfdKgMAsYLRwf2R0uQZaWWzTepbpyN9SXvTR5FnacVSFA==
+backport@6.1.5:
+ version "6.1.5"
+ resolved "https://registry.yarnpkg.com/backport/-/backport-6.1.5.tgz#2e8da121cd7ac89a51003f33fdd7febaa0a34202"
+ integrity sha512-fEn50S9P8mU3odGYZXNaj4LMTpio+zB2Vwq92wlu6u/fOQmkGvSxklp78NoAwSi8UBC3+vPa7G5zFp1uFLD6jg==
dependencies:
"@octokit/rest" "^18.12.0"
axios "^0.24.0"
From 2f028580b534977fea32d687e8aa5e9cf09e562c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?David=20S=C3=A1nchez?=
Date: Mon, 10 Jan 2022 17:08:17 +0100
Subject: [PATCH 02/19] Adds description field on event filters and displays it
in artifact entry card belong to comments. It also adds a unit test (#122511)
---
.../artifact_entry_card.tsx | 2 +-
.../view/components/form/index.test.tsx | 16 +++++++
.../view/components/form/index.tsx | 48 ++++++++++++++++++-
.../view/components/form/translations.ts | 13 +++++
.../view/event_filters_list_page.tsx | 1 -
5 files changed, 76 insertions(+), 4 deletions(-)
diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx
index 87d40cba26a2b..19e7ca9c9b397 100644
--- a/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx
+++ b/x-pack/plugins/security_solution/public/management/components/artifact_entry_card/artifact_entry_card.tsx
@@ -91,7 +91,7 @@ export const ArtifactEntryCard = memo(
{!hideComments ? (
<>
-
+ {hideDescription && }
>
) : null}
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx
index 424f7b3bc2791..6ff820a6b7e62 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx
@@ -162,6 +162,22 @@ describe('Event filter form', () => {
expect(getState().form.hasNameError).toBeTruthy();
});
+ it('should change description', async () => {
+ component = await renderWithData();
+
+ const nameInput = component.getByTestId('eventFilters-form-description-input');
+
+ act(() => {
+ fireEvent.change(nameInput, {
+ target: {
+ value: 'Exception description',
+ },
+ });
+ });
+
+ expect(getState().form.entry?.description).toBe('Exception description');
+ });
+
it('should change comments', async () => {
component = await renderWithData();
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.tsx
index 045ca779a0eff..8921488f64c79 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.tsx
@@ -19,6 +19,7 @@ import {
EuiSuperSelectOption,
EuiText,
EuiHorizontalRule,
+ EuiTextArea,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
@@ -36,7 +37,15 @@ import { getExceptionBuilderComponentLazy } from '../../../../../../../../lists/
import type { OnChangeProps } from '../../../../../../../../lists/public';
import { useEventFiltersSelector } from '../../hooks';
import { getFormEntryStateMutable, getHasNameError, getNewComment } from '../../../store/selector';
-import { NAME_LABEL, NAME_ERROR, NAME_PLACEHOLDER, OS_LABEL, RULE_NAME } from './translations';
+import {
+ NAME_LABEL,
+ NAME_ERROR,
+ DESCRIPTION_LABEL,
+ DESCRIPTION_PLACEHOLDER,
+ NAME_PLACEHOLDER,
+ OS_LABEL,
+ RULE_NAME,
+} from './translations';
import { OS_TITLES } from '../../../../../common/translations';
import { ENDPOINT_EVENT_FILTERS_LIST_ID, EVENT_FILTER_LIST_TYPE } from '../../../constants';
import { ABOUT_EVENT_FILTERS } from '../../translations';
@@ -134,6 +143,7 @@ export const EventFiltersForm: React.FC = memo(
entry: {
...arg.exceptionItems[0],
name: exception?.name ?? '',
+ description: exception?.description ?? '',
comments: exception?.comments ?? [],
os_types: exception?.os_types ?? [OperatingSystem.WINDOWS],
tags: exception?.tags ?? [],
@@ -165,6 +175,21 @@ export const EventFiltersForm: React.FC = memo(
[dispatch, exception]
);
+ const handleOnDescriptionChange = useCallback(
+ (e: React.ChangeEvent) => {
+ if (!exception) return;
+ setHasFormChanged(true);
+ const description = e.target.value.toString().trim();
+ dispatch({
+ type: 'eventFiltersChangeForm',
+ payload: {
+ entry: { ...exception, description },
+ },
+ });
+ },
+ [dispatch, exception]
+ );
+
const handleOnChangeComment = useCallback(
(value: string) => {
if (!exception) return;
@@ -229,6 +254,24 @@ export const EventFiltersForm: React.FC = memo(
[hasNameError, exception?.name, handleOnChangeName, hasBeenInputNameVisited]
);
+ const descriptionInputMemo = useMemo(
+ () => (
+
+
+
+ ),
+ [exception?.description, handleOnDescriptionChange]
+ );
+
const osInputMemo = useMemo(
() => (
@@ -285,9 +328,10 @@ export const EventFiltersForm: React.FC = memo(
{nameInputMemo}
+ {descriptionInputMemo}
>
),
- [nameInputMemo]
+ [nameInputMemo, descriptionInputMemo]
);
const criteriaSection = useMemo(
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/translations.ts b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/translations.ts
index bfb828699118e..20bdde0364e2c 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/translations.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/translations.ts
@@ -17,6 +17,19 @@ export const NAME_PLACEHOLDER = i18n.translate(
export const NAME_LABEL = i18n.translate('xpack.securitySolution.eventFilter.form.name.label', {
defaultMessage: 'Name your event filter',
});
+export const DESCRIPTION_LABEL = i18n.translate(
+ 'xpack.securitySolution.eventFilter.form.description.placeholder',
+ {
+ defaultMessage: 'Description',
+ }
+);
+
+export const DESCRIPTION_PLACEHOLDER = i18n.translate(
+ 'xpack.securitySolution.eventFilter.form.description.label',
+ {
+ defaultMessage: 'Describe your event filter',
+ }
+);
export const NAME_ERROR = i18n.translate('xpack.securitySolution.eventFilter.form.name.error', {
defaultMessage: "The name can't be empty",
diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx
index fcbf3d9489b96..2cc4bc7b8bd71 100644
--- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx
@@ -193,7 +193,6 @@ export const EventFiltersListPage = memo(() => {
cachedCardProps[eventFilter.id] = {
item: eventFilter as AnyArtifact,
policies: artifactCardPolicies,
- hideDescription: true,
'data-test-subj': 'eventFilterCard',
actions: [
{
From b15805593ba5c4056d6e7bf0ca45c5c75018b9de Mon Sep 17 00:00:00 2001
From: Joe Portner <5295965+jportner@users.noreply.github.com>
Date: Mon, 10 Jan 2022 11:19:13 -0500
Subject: [PATCH 03/19] Add tooltip for usernames on API Key management page
(#122488)
---
.../api_keys_grid/api_keys_grid_page.tsx | 24 ++++++++++++-------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx
index c3d4fdc41390d..dabcce11d319f 100644
--- a/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx
+++ b/x-pack/plugins/security/public/management/api_keys/api_keys_grid/api_keys_grid_page.tsx
@@ -22,6 +22,7 @@ import {
EuiText,
EuiToolTip,
} from '@elastic/eui';
+import { css } from '@emotion/react';
import type { History } from 'history';
import moment from 'moment-timezone';
import React, { Component } from 'react';
@@ -388,14 +389,21 @@ export class APIKeysGridPage extends Component {
return {
value: username,
view: (
-
-
-
-
-
- {username}
-
-
+
+
+
+
+
+
+ {username}
+
+
+
),
};
}),
From f5aa068ef2e071148b886bc8fb2b3dd4fe97a5cf Mon Sep 17 00:00:00 2001
From: Dmitry Tomashevich <39378793+Dmitriynj@users.noreply.github.com>
Date: Mon, 10 Jan 2022 19:55:28 +0300
Subject: [PATCH 04/19] [Discover] Add kibana services provider for embeddable
(#121621)
* [Discover] add kibana services provider for embeddable
* [Discover] add functional test
* [Discover] fix functional test
* [Discover] fix data grid test
* [Discover] go to discover main page before each test
* [Discover] remove redundant navigation to discover
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../public/embeddable/saved_search_grid.tsx | 37 ++++++++-----
.../apps/discover/_data_grid_doc_table.ts | 54 ++++++++++++++++++-
test/functional/services/data_grid.ts | 2 +-
3 files changed, 77 insertions(+), 16 deletions(-)
diff --git a/src/plugins/discover/public/embeddable/saved_search_grid.tsx b/src/plugins/discover/public/embeddable/saved_search_grid.tsx
index aa15ccb79da8b..f0423eac4f963 100644
--- a/src/plugins/discover/public/embeddable/saved_search_grid.tsx
+++ b/src/plugins/discover/public/embeddable/saved_search_grid.tsx
@@ -12,6 +12,7 @@ import { DiscoverGrid, DiscoverGridProps } from '../components/discover_grid/dis
import { getServices } from '../kibana_services';
import { TotalDocuments } from '../application/main/components/total_documents/total_documents';
import { ElasticSearchHit } from '../types';
+import { KibanaContextProvider } from '../../../kibana_react/public';
export interface DiscoverGridEmbeddableProps extends DiscoverGridProps {
totalHitCount: number;
@@ -22,25 +23,33 @@ export const DataGridMemoized = React.memo((props: DiscoverGridProps) => (
));
export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
+ const services = getServices();
const [expandedDoc, setExpandedDoc] = useState(undefined);
return (
-
- {props.totalHitCount !== 0 && (
-
-
+
+
+ {props.totalHitCount !== 0 && (
+
+
+
+ )}
+
+
- )}
-
-
-
-
+
+
);
}
diff --git a/test/functional/apps/discover/_data_grid_doc_table.ts b/test/functional/apps/discover/_data_grid_doc_table.ts
index f4019ba1eb31c..0721c45c1f9fa 100644
--- a/test/functional/apps/discover/_data_grid_doc_table.ts
+++ b/test/functional/apps/discover/_data_grid_doc_table.ts
@@ -17,7 +17,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const monacoEditor = getService('monacoEditor');
- const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker']);
+ const dashboardAddPanel = getService('dashboardAddPanel');
+ const PageObjects = getPageObjects(['common', 'discover', 'header', 'timePicker', 'dashboard']);
const defaultSettings = {
defaultIndex: 'logstash-*',
'doc_table:legacy': false,
@@ -32,6 +33,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
await kibanaServer.uiSettings.replace(defaultSettings);
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
+ });
+
+ beforeEach(async () => {
await PageObjects.common.navigateToApp('discover');
});
@@ -101,6 +105,54 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
);
});
+ it('should show popover with expanded cell content by click on expand button on embeddable', async () => {
+ log.debug('open popover with expanded cell content to get json from the editor');
+ await PageObjects.timePicker.setDefaultAbsoluteRange();
+ await PageObjects.discover.waitUntilSearchingHasFinished();
+ await PageObjects.discover.saveSearch('expand-cell-search');
+
+ await PageObjects.common.navigateToApp('dashboard');
+ await PageObjects.dashboard.gotoDashboardLandingPage();
+ await PageObjects.dashboard.clickNewDashboard();
+ await PageObjects.header.waitUntilLoadingHasFinished();
+ await dashboardAddPanel.addSavedSearch('expand-cell-search');
+
+ await retry.waitForWithTimeout('timestamp matches expected doc', 5000, async () => {
+ const cell = await dataGrid.getCellElement(0, 2);
+ const text = await cell.getVisibleText();
+ log.debug(`row document timestamp: ${text}`);
+ return text === 'Sep 22, 2015 @ 23:50:13.253';
+ });
+ const docCell = await dataGrid.getCellElement(0, 3);
+ await docCell.click();
+ const expandCellContentButton = await docCell.findByClassName(
+ 'euiDataGridRowCell__expandButtonIcon'
+ );
+ await expandCellContentButton.click();
+
+ let expandDocId = '';
+
+ await retry.waitForWithTimeout('expandDocId to be valid', 5000, async () => {
+ const text = await monacoEditor.getCodeEditorValue();
+ return (expandDocId = JSON.parse(text)._id) === 'AU_x3_g4GFA8no6QjkYX';
+ });
+ log.debug(`expanded document id: ${expandDocId}`);
+
+ await dataGrid.clickRowToggle();
+ await find.clickByCssSelectorWhenNotDisabled('#kbn_doc_viewer_tab_1');
+
+ await retry.waitForWithTimeout(
+ 'document id in flyout matching the expanded document id',
+ 5000,
+ async () => {
+ const text = await monacoEditor.getCodeEditorValue();
+ const flyoutJson = JSON.parse(text);
+ log.debug(`flyout document id: ${flyoutJson._id}`);
+ return flyoutJson._id === expandDocId;
+ }
+ );
+ });
+
describe('expand a document row', function () {
const rowToInspect = 1;
diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts
index d49ef5fa0990a..ca031116ec417 100644
--- a/test/functional/services/data_grid.ts
+++ b/test/functional/services/data_grid.ts
@@ -155,7 +155,7 @@ export class DataGridService extends FtrService {
options: SelectOptions = { isAnchorRow: false, rowIndex: 0 }
): Promise {
const row = await this.getRow(options);
- const toggle = await row[0];
+ const toggle = await row[0].findByTestSubject('~docTableExpandToggleColumn');
await toggle.click();
}
From a9b82b0740187c825afd703975589dd1d4360faf Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Mon, 10 Jan 2022 10:05:24 -0700
Subject: [PATCH 05/19] [maps] fix map application crashes when leaving map
while drawing filter (#122353)
* [maps] fix map application crashes when leaving map while drawing filter
* clean-up
* more clean up
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../mb_map/draw_control/draw_circle.ts | 21 +++++++++++--
.../mb_map/draw_control/draw_control.tsx | 31 +++++--------------
2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_circle.ts b/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_circle.ts
index 998329a78bfbb..c555b67eebac2 100644
--- a/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_circle.ts
+++ b/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_circle.ts
@@ -15,7 +15,24 @@ import { Feature, GeoJSON, Position } from 'geojson';
const DRAW_CIRCLE_RADIUS = 'draw-circle-radius';
-export const DRAW_CIRCLE_RADIUS_MB_FILTER = ['==', 'meta', DRAW_CIRCLE_RADIUS];
+export const DRAW_CIRCLE_RADIUS_LABEL_STYLE = {
+ id: 'gl-draw-radius-label',
+ type: 'symbol',
+ filter: ['==', 'meta', DRAW_CIRCLE_RADIUS],
+ layout: {
+ 'text-anchor': 'right',
+ 'text-field': '{radiusLabel}',
+ 'text-size': 16,
+ 'text-offset': [-1, 0],
+ 'text-ignore-placement': true,
+ 'text-allow-overlap': true,
+ },
+ paint: {
+ 'text-color': '#fbb03b',
+ 'text-halo-color': 'rgba(0, 0, 0, 1)',
+ 'text-halo-width': 2,
+ },
+};
export interface DrawCircleProperties {
center: Position;
@@ -148,7 +165,7 @@ export const DrawCircle = {
radiusLabel = `${Math.round(state.circle.properties.radiusKm)} km`;
}
- // display radius label, requires custom 'symbol' style with DRAW_CIRCLE_RADIUS_MB_FILTER filter
+ // display radius label, requires custom style: DRAW_CIRCLE_RADIUS_LABEL_STYLE
display({
type: 'Feature',
properties: {
diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_control.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_control.tsx
index ce4fcd8f12560..11b8c80e9fdec 100644
--- a/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_control.tsx
+++ b/x-pack/plugins/maps/public/connected_components/mb_map/draw_control/draw_control.tsx
@@ -10,16 +10,16 @@ import React, { Component } from 'react';
// @ts-expect-error
import MapboxDraw from '@mapbox/mapbox-gl-draw';
// @ts-expect-error
+import mapboxDrawStyles from '@mapbox/mapbox-gl-draw/src/lib/theme';
+// @ts-expect-error
import DrawRectangle from 'mapbox-gl-draw-rectangle-mode';
import type { Map as MbMap } from '@kbn/mapbox-gl';
import { Feature } from 'geojson';
import { MapMouseEvent } from '@kbn/mapbox-gl';
import { DRAW_SHAPE } from '../../../../common/constants';
-import { DrawCircle, DRAW_CIRCLE_RADIUS_MB_FILTER } from './draw_circle';
+import { DrawCircle, DRAW_CIRCLE_RADIUS_LABEL_STYLE } from './draw_circle';
import { DrawTooltip } from './draw_tooltip';
-const GL_DRAW_RADIUS_LABEL_LAYER_ID = 'gl-draw-radius-label';
-
const mbModeEquivalencies = new Map([
['simple_select', DRAW_SHAPE.SIMPLE_SELECT],
['draw_rectangle', DRAW_SHAPE.BOUNDS],
@@ -50,6 +50,7 @@ export class DrawControl extends Component {
private _mbDrawControl = new MapboxDraw({
displayControlsDefault: false,
modes: mbDrawModes,
+ styles: [...mapboxDrawStyles, DRAW_CIRCLE_RADIUS_LABEL_STYLE],
});
componentDidUpdate() {
@@ -97,7 +98,9 @@ export class DrawControl extends Component {
};
_removeDrawControl() {
- if (!this._mbDrawControlAdded) {
+ // Do not remove draw control after mbMap.remove is called, causes execeptions and mbMap.remove cleans up all map resources.
+ const isMapRemoved = !this.props.mbMap.loaded();
+ if (!this._mbDrawControlAdded || isMapRemoved) {
return;
}
@@ -107,7 +110,6 @@ export class DrawControl extends Component {
if (this.props.onClick) {
this.props.mbMap.off('click', this._onClick);
}
- this.props.mbMap.removeLayer(GL_DRAW_RADIUS_LABEL_LAYER_ID);
this.props.mbMap.removeControl(this._mbDrawControl);
this._mbDrawControlAdded = false;
}
@@ -119,25 +121,6 @@ export class DrawControl extends Component {
if (!this._mbDrawControlAdded) {
this.props.mbMap.addControl(this._mbDrawControl);
- this.props.mbMap.addLayer({
- id: GL_DRAW_RADIUS_LABEL_LAYER_ID,
- type: 'symbol',
- source: 'mapbox-gl-draw-hot',
- filter: DRAW_CIRCLE_RADIUS_MB_FILTER,
- layout: {
- 'text-anchor': 'right',
- 'text-field': '{radiusLabel}',
- 'text-size': 16,
- 'text-offset': [-1, 0],
- 'text-ignore-placement': true,
- 'text-allow-overlap': true,
- },
- paint: {
- 'text-color': '#fbb03b',
- 'text-halo-color': 'rgba(0, 0, 0, 1)',
- 'text-halo-width': 2,
- },
- });
this._mbDrawControlAdded = true;
this.props.mbMap.getCanvas().style.cursor = 'crosshair';
this.props.mbMap.on('draw.modechange', this._onModeChange);
From 1ca5b89038c36ee06ef627f5311a876869cd8ca0 Mon Sep 17 00:00:00 2001
From: sphilipse <94373878+sphilipse@users.noreply.github.com>
Date: Mon, 10 Jan 2022 19:43:58 +0100
Subject: [PATCH 06/19] [Workplace Search] Make Inline Editable Table slightly
more accessible (#122193)
* [Workplace Search] Make Inline Editable Table slightly more accessible
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../tables/inline_editable_table/constants.ts | 8 ---
.../inline_editable_table.test.tsx | 34 +++++++--
.../inline_editable_table.tsx | 24 +++----
.../inline_editable_table_logic.test.ts | 71 +++++++++++++++----
.../inline_editable_table_logic.ts | 22 ++----
5 files changed, 105 insertions(+), 54 deletions(-)
delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/constants.ts
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/constants.ts b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/constants.ts
deleted file mode 100644
index 43a5a5b1df9e6..0000000000000
--- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/constants.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-export const EMPTY_ITEM = { id: null };
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 c8d3079b033c0..9725abcd6eba7 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
@@ -88,14 +88,38 @@ describe('InlineEditableTable', () => {
const reorderableTable = wrapper.find(ReorderableTable);
expect(reorderableTable.exists()).toBe(true);
expect(reorderableTable.prop('items')).toEqual(items);
- expect(wrapper.find('[data-test-subj="actionButton"]').children().text()).toEqual('New row');
+ expect(
+ wrapper.find('[data-test-subj="inlineEditableTableActionButton"]').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);
+ });
+
+ it('does not render a title if none is provided', () => {
+ const wrapper = shallow(
+ Some Description}
+ />
+ );
+ expect(wrapper.find('[data-test-subj="inlineEditableTableTitle"]').exists()).toBe(false);
});
it('renders a description if one is provided', () => {
const wrapper = shallow(
Some Description} />
);
- expect(wrapper.find('[data-test-subj="description"]').exists()).toBe(true);
+ expect(wrapper.find('[data-test-subj="inlineEditableTableDescription"]').exists()).toBe(true);
+ });
+
+ it('renders no description if none is provided', () => {
+ const wrapper = shallow();
+ expect(wrapper.find('[data-test-subj="inlineEditableTableDescription"]').exists()).toBe(false);
});
it('can specify items in the table that are uneditable', () => {
@@ -117,9 +141,9 @@ describe('InlineEditableTable', () => {
const wrapper = shallow(
);
- expect(wrapper.find('[data-test-subj="actionButton"]').children().text()).toEqual(
- 'Add a new row custom text'
- );
+ expect(
+ wrapper.find('[data-test-subj="inlineEditableTableActionButton"]').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 3c670264dff22..3ccd5f15e29e9 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
@@ -18,7 +18,6 @@ import { ReorderableTable } from '../reorderable_table';
import { ItemWithAnID } from '../types';
-import { EMPTY_ITEM } from './constants';
import { getUpdatedColumns } from './get_updated_columns';
import { InlineEditableTableLogic } from './inline_editable_table_logic';
import { FormErrors, InlineEditableTableColumn } from './types';
@@ -103,16 +102,16 @@ export const InlineEditableTableContents = - ({
const isEditingItem = (item: Item) => item.id === editingItemId;
const isActivelyEditing = (item: Item) => isEditing && isEditingItem(item);
+ const emptyItem = { id: null } as Item;
const displayedItems = isEditingUnsavedItem
? uneditableItems
- ? [EMPTY_ITEM, ...items]
- : [...items, EMPTY_ITEM]
+ ? [emptyItem, ...items]
+ : [...items, emptyItem]
: items;
const updatedColumns = getUpdatedColumns({
columns,
- // TODO We shouldn't need this cast here
- displayedItems: displayedItems as Item[],
+ displayedItems,
isActivelyEditing,
canRemoveLastItem,
isLoading,
@@ -124,14 +123,16 @@ export const InlineEditableTableContents =
- ({
<>
-
-
{title}
-
+ {!!title && (
+
+ {title}
+
+ )}
{!!description && (
<>
({
disabled={isEditing}
onClick={editNewItem}
color="success"
- data-test-subj="actionButton"
+ data-test-subj="inlineEditableTableActionButton"
>
{addButtonText ||
i18n.translate('xpack.enterpriseSearch.inlineEditableTable.newRowButtonLabel', {
@@ -160,8 +161,7 @@ export const InlineEditableTableContents = - ({
({
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.test.ts
index 5a8a724076223..4b0f6b83ba5d0 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.test.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.test.ts
@@ -27,14 +27,14 @@ describe('InlineEditableTableLogic', () => {
const { mount } = new LogicMounter(InlineEditableTableLogic);
const DEFAULT_VALUES = {
- editingItemId: null,
editingItemValue: null,
fieldErrors: {},
- isEditing: false,
rowErrors: [],
};
const SELECTORS = {
+ editingItemId: null,
+ isEditing: false,
doesEditingItemValueContainEmptyProperty: false,
isEditingUnsavedItem: false,
};
@@ -102,8 +102,6 @@ describe('InlineEditableTableLogic', () => {
describe('editNewItem', () => {
it('updates state to reflect a new item being edited', () => {
const logic = mountLogic({
- isEditing: false,
- editingItemId: 1,
editingItemValue: {
id: 1,
foo: 'some foo',
@@ -113,8 +111,6 @@ describe('InlineEditableTableLogic', () => {
logic.actions.editNewItem();
expect(logicValuesWithoutSelectors(logic)).toEqual({
...DEFAULT_VALUES,
- isEditing: true,
- editingItemId: null,
editingItemValue: {
// Note that new values do not yet have an id
foo: '',
@@ -127,8 +123,6 @@ describe('InlineEditableTableLogic', () => {
describe('editExistingItem', () => {
it('updates state to reflect the item that was passed being edited', () => {
const logic = mountLogic({
- isEditing: false,
- editingItemId: 1,
editingItemValue: {
id: 1,
foo: '',
@@ -142,8 +136,6 @@ describe('InlineEditableTableLogic', () => {
});
expect(logicValuesWithoutSelectors(logic)).toEqual({
...DEFAULT_VALUES,
- isEditing: true,
- editingItemId: 2,
editingItemValue: {
id: 2,
foo: 'existing foo',
@@ -208,11 +200,66 @@ describe('InlineEditableTableLogic', () => {
});
describe('selectors', () => {
+ describe('isEditing', () => {
+ it('is true when the user is currently editing an item', () => {
+ const logic = mountLogic({
+ editingItemValue: {
+ id: null,
+ foo: '',
+ },
+ });
+
+ expect(logic.values.isEditing).toBe(true);
+ });
+
+ it('is false when the user is NOT currently editing an item', () => {
+ const logic = mountLogic({
+ editingItemValue: null,
+ });
+
+ expect(logic.values.isEditing).toBe(false);
+ });
+ });
+
+ describe('editingItemId', () => {
+ it('equals the id of the currently edited item', () => {
+ const logic = mountLogic({
+ editingItemValue: {
+ id: 1,
+ foo: '',
+ },
+ });
+
+ expect(logic.values.editingItemId).toBe(1);
+ });
+
+ it('equals null if the currently edited item is a new unsaved item', () => {
+ const logic = mountLogic({
+ editingItemValue: {
+ id: null,
+ foo: '',
+ },
+ });
+
+ expect(logic.values.editingItemId).toBe(null);
+ });
+
+ it('is null when the user is NOT currently editing an item', () => {
+ const logic = mountLogic({
+ editingItemValue: null,
+ });
+
+ expect(logic.values.editingItemId).toBe(null);
+ });
+ });
+
describe('isEditingUnsavedItem', () => {
it('is true when the user is currently editing an unsaved item', () => {
const logic = mountLogic({
- isEditing: true,
- editingItemId: null,
+ editingItemValue: {
+ id: null,
+ foo: '',
+ },
});
expect(logic.values.isEditingUnsavedItem).toBe(true);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts
index 04b5ceb998851..d62d894d18ef5 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table_logic.ts
@@ -35,7 +35,6 @@ const getUnsavedItemId = () => null;
const doesIdMatchUnsavedId = (idToCheck: number) => idToCheck === getUnsavedItemId();
interface InlineEditableTableValues
- {
- // TODO This could likely be a selector
isEditing: boolean;
// TODO we should editingItemValue have editingItemValue and editingItemId should be a selector
editingItemId: Item['id'] | null; // editingItem is null when the user is editing a new but not saved item
@@ -81,22 +80,6 @@ export const InlineEditableTableLogic = kea ({ rowErrors }),
}),
reducers: ({ props: { columns } }) => ({
- isEditing: [
- false,
- {
- doneEditing: () => false,
- editNewItem: () => true,
- editExistingItem: () => true,
- },
- ],
- editingItemId: [
- null,
- {
- doneEditing: () => null,
- editNewItem: () => getUnsavedItemId(),
- editExistingItem: (_, { item }) => item.id,
- },
- ],
editingItemValue: [
null,
{
@@ -124,6 +107,11 @@ export const InlineEditableTableLogic = kea ({
+ editingItemId: [
+ () => [selectors.editingItemValue],
+ (editingItemValue) => editingItemValue?.id ?? null,
+ ],
+ isEditing: [() => [selectors.editingItemValue], (editingItemValue) => !!editingItemValue],
isEditingUnsavedItem: [
() => [selectors.isEditing, selectors.editingItemId],
(isEditing, editingItemId) => {
From 1ddb64758fee9684f3f712219f8a890a78ad670b Mon Sep 17 00:00:00 2001
From: Madison Caldwell
Date: Mon, 10 Jan 2022 13:57:51 -0500
Subject: [PATCH 07/19] [Security Solution] Disable legacy rules on upgrade to
8.x (#121442)
* Disable legacy rule and notify user to upgrade
* Ensure rules are disabled on upgrade
* Fix dupe detection on upgrade
* Revert "Fix dupe detection on upgrade"
This reverts commit 021ec0fac4accc4dda7a742b3ea8cfdc3e193eb3.
* Add legacy notification
* Add tests for 8.0 security_solution rule migration
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../server/saved_objects/migrations.test.ts | 32 +
.../server/saved_objects/migrations.ts | 5 +-
.../signals/signal_rule_alert_type.test.ts | 599 ------------------
.../signals/signal_rule_alert_type.ts | 596 -----------------
.../security_solution/server/plugin.ts | 17 -
.../spaces_only/tests/alerting/migrations.ts | 13 +
.../functional/es_archives/alerts/data.json | 1 +
7 files changed, 49 insertions(+), 1214 deletions(-)
delete mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts
delete mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts
diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts
index 08312d0be0419..5e2d8efedbcb3 100644
--- a/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts
+++ b/x-pack/plugins/alerting/server/saved_objects/migrations.test.ts
@@ -11,6 +11,7 @@ import { RawRule } from '../types';
import { SavedObjectUnsanitizedDoc } from 'kibana/server';
import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks';
import { migrationMocks } from 'src/core/server/mocks';
+import { RuleType, ruleTypeMappings } from '@kbn/securitysolution-rules';
const migrationContext = migrationMocks.createContext();
const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup();
@@ -2056,6 +2057,37 @@ describe('successful migrations', () => {
);
});
+ test('doesnt change AAD rule params if not a siem.signals rule', () => {
+ const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0'];
+ const alert = getMockData(
+ { params: { outputIndex: 'output-index', type: 'query' }, alertTypeId: 'not.siem.signals' },
+ true
+ );
+ expect(migration800(alert, migrationContext).attributes.alertTypeId).toEqual(
+ 'not.siem.signals'
+ );
+ expect(migration800(alert, migrationContext).attributes.enabled).toEqual(true);
+ expect(migration800(alert, migrationContext).attributes.params.outputIndex).toEqual(
+ 'output-index'
+ );
+ });
+
+ test.each(Object.keys(ruleTypeMappings) as RuleType[])(
+ 'Changes AAD rule params accordingly if rule is a siem.signals %p rule',
+ (ruleType) => {
+ const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0'];
+ const alert = getMockData(
+ { params: { outputIndex: 'output-index', type: ruleType }, alertTypeId: 'siem.signals' },
+ true
+ );
+ expect(migration800(alert, migrationContext).attributes.alertTypeId).toEqual(
+ ruleTypeMappings[ruleType]
+ );
+ expect(migration800(alert, migrationContext).attributes.enabled).toEqual(false);
+ expect(migration800(alert, migrationContext).attributes.params.outputIndex).toEqual('');
+ }
+ );
+
describe('Metrics Inventory Threshold rule', () => {
test('Migrates incorrect action group spelling', () => {
const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0'];
diff --git a/x-pack/plugins/alerting/server/saved_objects/migrations.ts b/x-pack/plugins/alerting/server/saved_objects/migrations.ts
index 6736fd3573adb..e664095e8c846 100644
--- a/x-pack/plugins/alerting/server/saved_objects/migrations.ts
+++ b/x-pack/plugins/alerting/server/saved_objects/migrations.ts
@@ -131,7 +131,7 @@ export function getMigrations(
(doc: SavedObjectUnsanitizedDoc): doc is SavedObjectUnsanitizedDoc => true,
pipeMigrations(
addThreatIndicatorPathToThreatMatchRules,
- addRACRuleTypes,
+ addSecuritySolutionAADRuleTypes,
fixInventoryThresholdGroupId
)
);
@@ -652,7 +652,7 @@ function setLegacyId(doc: SavedObjectUnsanitizedDoc): SavedObjectUnsani
};
}
-function addRACRuleTypes(
+function addSecuritySolutionAADRuleTypes(
doc: SavedObjectUnsanitizedDoc
): SavedObjectUnsanitizedDoc {
const ruleType = doc.attributes.params.type;
@@ -662,6 +662,7 @@ function addRACRuleTypes(
attributes: {
...doc.attributes,
alertTypeId: ruleTypeMappings[ruleType],
+ enabled: false,
params: {
...doc.attributes.params,
outputIndex: '',
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts
deleted file mode 100644
index 10a7f38fbf389..0000000000000
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import moment from 'moment';
-import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
-import { loggingSystemMock } from 'src/core/server/mocks';
-import { getAlertMock } from '../routes/__mocks__/request_responses';
-import { signalRulesAlertType } from './signal_rule_alert_type';
-import { alertsMock, AlertServicesMock } from '../../../../../alerting/server/mocks';
-import {
- getListsClient,
- getExceptions,
- checkPrivileges,
- createSearchAfterReturnType,
-} from './utils';
-import { parseScheduleDates } from '@kbn/securitysolution-io-ts-utils';
-import { RuleExecutorOptions, SearchAfterAndBulkCreateReturnType } from './types';
-import { RuleAlertType } from '../rules/types';
-import { listMock } from '../../../../../lists/server/mocks';
-import { getListClientMock } from '../../../../../lists/server/services/lists/list_client.mock';
-import { getExceptionListClientMock } from '../../../../../lists/server/services/exception_lists/exception_list_client.mock';
-import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock';
-import type { TransportResult } from '@elastic/elasticsearch';
-// eslint-disable-next-line @kbn/eslint/no-restricted-paths
-import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
-import { queryExecutor } from './executors/query';
-import { mlExecutor } from './executors/ml';
-import { getMlRuleParams, getQueryRuleParams } from '../schemas/rule_schemas.mock';
-import { errors } from '@elastic/elasticsearch';
-import { allowedExperimentalValues } from '../../../../common/experimental_features';
-import { scheduleNotificationActions } from '../notifications/schedule_notification_actions';
-import { ruleExecutionLogClientMock } from '../rule_execution_log/__mocks__/rule_execution_log_client';
-import { RuleExecutionStatus } from '../../../../common/detection_engine/schemas/common/schemas';
-import { scheduleThrottledNotificationActions } from '../notifications/schedule_throttle_notification_actions';
-import { eventLogServiceMock } from '../../../../../event_log/server/mocks';
-import { createMockConfig } from '../routes/__mocks__';
-
-jest.mock('./utils', () => {
- const original = jest.requireActual('./utils');
- return {
- ...original,
- getListsClient: jest.fn(),
- getExceptions: jest.fn(),
- sortExceptionItems: jest.fn(),
- checkPrivileges: jest.fn(),
- };
-});
-jest.mock('../notifications/schedule_notification_actions');
-jest.mock('./executors/query');
-jest.mock('./executors/ml');
-jest.mock('@kbn/securitysolution-io-ts-utils', () => {
- const original = jest.requireActual('@kbn/securitysolution-io-ts-utils');
- return {
- ...original,
- parseScheduleDates: jest.fn(),
- };
-});
-jest.mock('../notifications/schedule_throttle_notification_actions');
-const mockRuleExecutionLogClient = ruleExecutionLogClientMock.create();
-
-jest.mock('../rule_execution_log/rule_execution_log_client', () => ({
- RuleExecutionLogClient: jest.fn().mockImplementation(() => mockRuleExecutionLogClient),
-}));
-
-const getPayload = (
- ruleAlert: RuleAlertType,
- services: AlertServicesMock
-): RuleExecutorOptions => ({
- alertId: ruleAlert.id,
- services,
- name: ruleAlert.name,
- tags: ruleAlert.tags,
- params: {
- ...ruleAlert.params,
- },
- state: {},
- spaceId: '',
- startedAt: new Date('2019-12-13T16:50:33.400Z'),
- previousStartedAt: new Date('2019-12-13T16:40:33.400Z'),
- createdBy: 'elastic',
- updatedBy: 'elastic',
- rule: {
- name: ruleAlert.name,
- tags: ruleAlert.tags,
- consumer: 'foo',
- producer: 'foo',
- ruleTypeId: 'ruleType',
- ruleTypeName: 'Name of rule',
- enabled: true,
- schedule: {
- interval: '5m',
- },
- actions: ruleAlert.actions,
- createdBy: 'elastic',
- updatedBy: 'elastic',
- createdAt: new Date('2019-12-13T16:50:33.400Z'),
- updatedAt: new Date('2019-12-13T16:50:33.400Z'),
- throttle: null,
- notifyWhen: null,
- },
-});
-
-// Deprecated
-describe.skip('signal_rule_alert_type', () => {
- const version = '8.0.0';
- const jobsSummaryMock = jest.fn();
- const mlMock = {
- mlClient: {
- callAsInternalUser: jest.fn(),
- close: jest.fn(),
- asScoped: jest.fn(),
- },
- jobServiceProvider: jest.fn().mockReturnValue({
- jobsSummary: jobsSummaryMock,
- }),
- anomalyDetectorsProvider: jest.fn(),
- mlSystemProvider: jest.fn(),
- modulesProvider: jest.fn(),
- resultsServiceProvider: jest.fn(),
- alertingServiceProvider: jest.fn(),
- };
- let payload: jest.Mocked;
- let alert: ReturnType;
- let logger: ReturnType;
- let alertServices: AlertServicesMock;
- let eventLogService: ReturnType;
-
- beforeEach(() => {
- alertServices = alertsMock.createAlertServices();
- logger = loggingSystemMock.createLogger();
- eventLogService = eventLogServiceMock.create();
- (getListsClient as jest.Mock).mockReturnValue({
- listClient: getListClientMock(),
- exceptionsClient: getExceptionListClientMock(),
- });
- (getExceptions as jest.Mock).mockReturnValue([getExceptionListItemSchemaMock()]);
- (checkPrivileges as jest.Mock).mockImplementation(async (_, indices) => {
- return {
- index: indices.reduce(
- (acc: { index: { [x: string]: { read: boolean } } }, index: string) => {
- return {
- [index]: {
- read: true,
- },
- ...acc,
- };
- },
- {}
- ),
- };
- });
- const executorReturnValue = createSearchAfterReturnType({
- createdSignalsCount: 10,
- });
- (queryExecutor as jest.Mock).mockClear();
- (queryExecutor as jest.Mock).mockResolvedValue(executorReturnValue);
- (mlExecutor as jest.Mock).mockClear();
- (mlExecutor as jest.Mock).mockResolvedValue(executorReturnValue);
- (parseScheduleDates as jest.Mock).mockReturnValue(moment(100));
- const value: Partial> = {
- statusCode: 200,
- body: {
- indices: ['index1', 'index2', 'index3', 'index4'],
- fields: {
- '@timestamp': {
- // @ts-expect-error not full interface
- date: {
- indices: ['index1', 'index2', 'index3', 'index4'],
- searchable: true,
- aggregatable: false,
- },
- },
- },
- },
- };
- alertServices.scopedClusterClient.asCurrentUser.fieldCaps.mockResolvedValue(
- value as TransportResult
- );
- const ruleAlert = getAlertMock(false, getQueryRuleParams());
- alertServices.savedObjectsClient.get.mockResolvedValue({
- id: 'id',
- type: 'type',
- references: [],
- attributes: ruleAlert,
- });
-
- payload = getPayload(ruleAlert, alertServices) as jest.Mocked;
-
- alert = signalRulesAlertType({
- experimentalFeatures: allowedExperimentalValues,
- logger,
- eventsTelemetry: undefined,
- version,
- ml: mlMock,
- lists: listMock.createSetup(),
- config: createMockConfig(),
- eventLogService,
- });
-
- mockRuleExecutionLogClient.logStatusChange.mockClear();
- (scheduleThrottledNotificationActions as jest.Mock).mockClear();
- });
-
- describe('executor', () => {
- it('should log success status if signals were created', async () => {
- payload.previousStartedAt = null;
- await alert.executor(payload);
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenLastCalledWith(
- expect.objectContaining({
- newStatus: RuleExecutionStatus.succeeded,
- })
- );
- });
-
- it('should warn about the gap between runs if gap is very large', async () => {
- payload.previousStartedAt = moment(payload.startedAt).subtract(100, 'm').toDate();
- await alert.executor(payload);
- expect(logger.warn).toHaveBeenCalled();
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenNthCalledWith(
- 1,
- expect.objectContaining({
- newStatus: RuleExecutionStatus['going to run'],
- })
- );
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenNthCalledWith(
- 2,
- expect.objectContaining({
- newStatus: RuleExecutionStatus.failed,
- metrics: {
- executionGap: expect.any(Object),
- },
- })
- );
- });
-
- it('should set a warning for when rules cannot read ALL provided indices', async () => {
- (checkPrivileges as jest.Mock).mockResolvedValueOnce({
- username: 'elastic',
- has_all_requested: false,
- cluster: {},
- index: {
- 'myfa*': {
- read: true,
- },
- 'anotherindex*': {
- read: true,
- },
- 'some*': {
- read: false,
- },
- },
- application: {},
- });
- const newRuleAlert = getAlertMock(false, getQueryRuleParams());
- newRuleAlert.params.index = ['some*', 'myfa*', 'anotherindex*'];
- payload = getPayload(newRuleAlert, alertServices) as jest.Mocked;
-
- await alert.executor(payload);
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenNthCalledWith(
- 2,
- expect.objectContaining({
- newStatus: RuleExecutionStatus['partial failure'],
- message:
- 'This rule may not have the required read privileges to the following indices/index patterns: ["some*"]',
- })
- );
- });
-
- it('should set a failure status for when rules cannot read ANY provided indices', async () => {
- (checkPrivileges as jest.Mock).mockResolvedValueOnce({
- username: 'elastic',
- has_all_requested: false,
- cluster: {},
- index: {
- 'myfa*': {
- read: false,
- },
- 'some*': {
- read: false,
- },
- },
- application: {},
- });
- const newRuleAlert = getAlertMock(false, getQueryRuleParams());
- newRuleAlert.params.index = ['some*', 'myfa*', 'anotherindex*'];
- payload = getPayload(newRuleAlert, alertServices) as jest.Mocked;
-
- await alert.executor(payload);
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenNthCalledWith(
- 2,
- expect.objectContaining({
- newStatus: RuleExecutionStatus['partial failure'],
- message:
- 'This rule may not have the required read privileges to the following indices/index patterns: ["myfa*","some*"]',
- })
- );
- });
-
- it('should NOT warn about the gap between runs if gap small', async () => {
- payload.previousStartedAt = moment().subtract(10, 'm').toDate();
- await alert.executor(payload);
- expect(logger.warn).toHaveBeenCalledTimes(0);
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenCalledTimes(2);
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenNthCalledWith(
- 1,
- expect.objectContaining({
- newStatus: RuleExecutionStatus['going to run'],
- })
- );
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenNthCalledWith(
- 2,
- expect.objectContaining({
- newStatus: RuleExecutionStatus.succeeded,
- })
- );
- });
-
- it('should call scheduleActions if signalsCount was greater than 0 and rule has actions defined', async () => {
- const ruleAlert = getAlertMock(false, getQueryRuleParams());
- ruleAlert.actions = [
- {
- actionTypeId: '.slack',
- params: {
- message:
- 'Rule generated {{state.signals_count}} signals\n\n{{context.rule.name}}\n{{{context.results_link}}}',
- },
- group: 'default',
- id: '99403909-ca9b-49ba-9d7a-7e5320e68d05',
- },
- ];
-
- alertServices.savedObjectsClient.get.mockResolvedValue({
- id: 'id',
- type: 'type',
- references: [],
- attributes: ruleAlert,
- });
-
- await alert.executor(payload);
- });
-
- it('should resolve results_link when meta is an empty object to use "/app/security"', async () => {
- const ruleAlert = getAlertMock(false, getQueryRuleParams());
- ruleAlert.params.meta = {};
- ruleAlert.actions = [
- {
- actionTypeId: '.slack',
- params: {
- message:
- 'Rule generated {{state.signals_count}} signals\n\n{{context.rule.name}}\n{{{context.results_link}}}',
- },
- group: 'default',
- id: '99403909-ca9b-49ba-9d7a-7e5320e68d05',
- },
- ];
-
- const modifiedPayload = getPayload(
- ruleAlert,
- alertServices
- ) as jest.Mocked;
-
- await alert.executor(modifiedPayload);
-
- expect(scheduleNotificationActions).toHaveBeenCalledWith(
- expect.objectContaining({
- resultsLink: `/app/security/detections/rules/id/${ruleAlert.id}?timerange=(global:(linkTo:!(timeline),timerange:(from:100,kind:absolute,to:100)),timeline:(linkTo:!(global),timerange:(from:100,kind:absolute,to:100)))`,
- })
- );
- });
-
- it('should resolve results_link when meta is undefined use "/app/security"', async () => {
- const ruleAlert = getAlertMock(false, getQueryRuleParams());
- delete ruleAlert.params.meta;
- ruleAlert.actions = [
- {
- actionTypeId: '.slack',
- params: {
- message:
- 'Rule generated {{state.signals_count}} signals\n\n{{context.rule.name}}\n{{{context.results_link}}}',
- },
- group: 'default',
- id: '99403909-ca9b-49ba-9d7a-7e5320e68d05',
- },
- ];
-
- const modifiedPayload = getPayload(
- ruleAlert,
- alertServices
- ) as jest.Mocked;
-
- await alert.executor(modifiedPayload);
-
- expect(scheduleNotificationActions).toHaveBeenCalledWith(
- expect.objectContaining({
- resultsLink: `/app/security/detections/rules/id/${ruleAlert.id}?timerange=(global:(linkTo:!(timeline),timerange:(from:100,kind:absolute,to:100)),timeline:(linkTo:!(global),timerange:(from:100,kind:absolute,to:100)))`,
- })
- );
- });
-
- it('should resolve results_link with a custom link', async () => {
- const ruleAlert = getAlertMock(false, getQueryRuleParams());
- ruleAlert.params.meta = { kibana_siem_app_url: 'http://localhost' };
- ruleAlert.actions = [
- {
- actionTypeId: '.slack',
- params: {
- message:
- 'Rule generated {{state.signals_count}} signals\n\n{{context.rule.name}}\n{{{context.results_link}}}',
- },
- group: 'default',
- id: '99403909-ca9b-49ba-9d7a-7e5320e68d05',
- },
- ];
-
- const modifiedPayload = getPayload(
- ruleAlert,
- alertServices
- ) as jest.Mocked;
-
- await alert.executor(modifiedPayload);
-
- expect(scheduleNotificationActions).toHaveBeenCalledWith(
- expect.objectContaining({
- resultsLink: `http://localhost/detections/rules/id/${ruleAlert.id}?timerange=(global:(linkTo:!(timeline),timerange:(from:100,kind:absolute,to:100)),timeline:(linkTo:!(global),timerange:(from:100,kind:absolute,to:100)))`,
- })
- );
- });
-
- describe('ML rule', () => {
- it('should not call checkPrivileges if ML rule', async () => {
- const ruleAlert = getAlertMock(false, getMlRuleParams());
- alertServices.savedObjectsClient.get.mockResolvedValue({
- id: 'id',
- type: 'type',
- references: [],
- attributes: ruleAlert,
- });
- payload = getPayload(ruleAlert, alertServices) as jest.Mocked;
- payload.previousStartedAt = null;
- (checkPrivileges as jest.Mock).mockClear();
-
- await alert.executor(payload);
- expect(checkPrivileges).toHaveBeenCalledTimes(0);
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenLastCalledWith(
- expect.objectContaining({
- newStatus: RuleExecutionStatus.succeeded,
- })
- );
- });
- });
- });
-
- describe('should catch error', () => {
- it('when bulk indexing failed', async () => {
- const result: SearchAfterAndBulkCreateReturnType = {
- success: false,
- warning: false,
- searchAfterTimes: [],
- bulkCreateTimes: [],
- lastLookBackDate: null,
- createdSignalsCount: 0,
- createdSignals: [],
- warningMessages: [],
- errors: ['Error that bubbled up.'],
- };
- (queryExecutor as jest.Mock).mockResolvedValue(result);
- await alert.executor(payload);
- expect(logger.error).toHaveBeenCalled();
- expect(logger.error.mock.calls[0][0]).toContain(
- 'Bulk Indexing of signals failed: Error that bubbled up. name: "Detect Root/Admin Users" id: "04128c15-0d1b-4716-a4c5-46997ac7f3bd" rule id: "rule-1" signals index: ".siem-signals"'
- );
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenLastCalledWith(
- expect.objectContaining({
- newStatus: RuleExecutionStatus.failed,
- })
- );
- });
-
- it('when error was thrown', async () => {
- (queryExecutor as jest.Mock).mockRejectedValue({});
- await alert.executor(payload);
- expect(logger.error).toHaveBeenCalled();
- expect(logger.error.mock.calls[0][0]).toContain('An error occurred during rule execution');
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenLastCalledWith(
- expect.objectContaining({
- newStatus: RuleExecutionStatus.failed,
- })
- );
- });
-
- it('and log failure with the default message', async () => {
- (queryExecutor as jest.Mock).mockReturnValue(
- elasticsearchClientMock.createErrorTransportRequestPromise(
- new errors.ResponseError(
- elasticsearchClientMock.createApiResponse({
- statusCode: 400,
- body: { error: { type: 'some_error_type' } },
- })
- )
- )
- );
- await alert.executor(payload);
- expect(logger.error).toHaveBeenCalled();
- expect(logger.error.mock.calls[0][0]).toContain('An error occurred during rule execution');
- expect(mockRuleExecutionLogClient.logStatusChange).toHaveBeenLastCalledWith(
- expect.objectContaining({
- newStatus: RuleExecutionStatus.failed,
- })
- );
- });
-
- it('should call scheduleThrottledNotificationActions if result is false to prevent the throttle from being reset', async () => {
- const result: SearchAfterAndBulkCreateReturnType = {
- success: false,
- warning: false,
- searchAfterTimes: [],
- bulkCreateTimes: [],
- lastLookBackDate: null,
- createdSignalsCount: 0,
- createdSignals: [],
- warningMessages: [],
- errors: ['Error that bubbled up.'],
- };
- (queryExecutor as jest.Mock).mockResolvedValue(result);
- const ruleAlert = getAlertMock(false, getQueryRuleParams());
- ruleAlert.throttle = '1h';
- const payLoadWithThrottle = getPayload(
- ruleAlert,
- alertServices
- ) as jest.Mocked;
- payLoadWithThrottle.rule.throttle = '1h';
- alertServices.savedObjectsClient.get.mockResolvedValue({
- id: 'id',
- type: 'type',
- references: [],
- attributes: ruleAlert,
- });
- await alert.executor(payLoadWithThrottle);
- expect(scheduleThrottledNotificationActions).toHaveBeenCalledTimes(1);
- });
-
- it('should NOT call scheduleThrottledNotificationActions if result is false and the throttle is not set', async () => {
- const result: SearchAfterAndBulkCreateReturnType = {
- success: false,
- warning: false,
- searchAfterTimes: [],
- bulkCreateTimes: [],
- lastLookBackDate: null,
- createdSignalsCount: 0,
- createdSignals: [],
- warningMessages: [],
- errors: ['Error that bubbled up.'],
- };
- (queryExecutor as jest.Mock).mockResolvedValue(result);
- await alert.executor(payload);
- expect(scheduleThrottledNotificationActions).toHaveBeenCalledTimes(0);
- });
-
- it('should call scheduleThrottledNotificationActions if an error was thrown to prevent the throttle from being reset', async () => {
- (queryExecutor as jest.Mock).mockRejectedValue({});
- const ruleAlert = getAlertMock(false, getQueryRuleParams());
- ruleAlert.throttle = '1h';
- const payLoadWithThrottle = getPayload(
- ruleAlert,
- alertServices
- ) as jest.Mocked;
- payLoadWithThrottle.rule.throttle = '1h';
- alertServices.savedObjectsClient.get.mockResolvedValue({
- id: 'id',
- type: 'type',
- references: [],
- attributes: ruleAlert,
- });
- await alert.executor(payLoadWithThrottle);
- expect(scheduleThrottledNotificationActions).toHaveBeenCalledTimes(1);
- });
-
- it('should NOT call scheduleThrottledNotificationActions if an error was thrown to prevent the throttle from being reset if throttle is not defined', async () => {
- const result: SearchAfterAndBulkCreateReturnType = {
- success: false,
- warning: false,
- searchAfterTimes: [],
- bulkCreateTimes: [],
- lastLookBackDate: null,
- createdSignalsCount: 0,
- createdSignals: [],
- warningMessages: [],
- errors: ['Error that bubbled up.'],
- };
- (queryExecutor as jest.Mock).mockRejectedValue(result);
- await alert.executor(payload);
- expect(scheduleThrottledNotificationActions).toHaveBeenCalledTimes(0);
- });
- });
-});
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts
deleted file mode 100644
index 4594ce212e0a9..0000000000000
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.ts
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-/* eslint-disable complexity */
-
-import { Logger } from 'src/core/server';
-import isEmpty from 'lodash/isEmpty';
-import * as t from 'io-ts';
-import { validateNonExact, parseScheduleDates } from '@kbn/securitysolution-io-ts-utils';
-import { SIGNALS_ID } from '@kbn/securitysolution-rules';
-
-import { DEFAULT_SEARCH_AFTER_PAGE_SIZE, SERVER_APP_ID } from '../../../../common/constants';
-import { isMlRule } from '../../../../common/machine_learning/helpers';
-import {
- isThresholdRule,
- isEqlRule,
- isThreatMatchRule,
- isQueryRule,
-} from '../../../../common/detection_engine/utils';
-import { SetupPlugins } from '../../../plugin';
-import { getInputIndex } from './get_input_output_index';
-import { SignalRuleAlertTypeDefinition, ThresholdAlertState } from './types';
-import {
- getListsClient,
- getExceptions,
- createSearchAfterReturnType,
- checkPrivileges,
- hasTimestampFields,
- hasReadIndexPrivileges,
- getRuleRangeTuples,
- isMachineLearningParams,
-} from './utils';
-import { siemRuleActionGroups } from './siem_rule_action_groups';
-import {
- scheduleNotificationActions,
- NotificationRuleTypeParams,
-} from '../notifications/schedule_notification_actions';
-import { buildRuleMessageFactory } from './rule_messages';
-import { getNotificationResultsLink } from '../notifications/utils';
-import { TelemetryEventsSender } from '../../telemetry/sender';
-import { eqlExecutor } from './executors/eql';
-import { queryExecutor } from './executors/query';
-import { threatMatchExecutor } from './executors/threat_match';
-import { thresholdExecutor } from './executors/threshold';
-import { mlExecutor } from './executors/ml';
-import {
- eqlRuleParams,
- machineLearningRuleParams,
- queryRuleParams,
- threatRuleParams,
- thresholdRuleParams,
- ruleParams,
- RuleParams,
- savedQueryRuleParams,
- CompleteRule,
-} from '../schemas/rule_schemas';
-import { bulkCreateFactory } from './bulk_create_factory';
-import { wrapHitsFactory } from './wrap_hits_factory';
-import { wrapSequencesFactory } from './wrap_sequences_factory';
-import { ConfigType } from '../../../config';
-import { ExperimentalFeatures } from '../../../../common/experimental_features';
-import { injectReferences, extractReferences } from './saved_object_references';
-import {
- IRuleExecutionLogClient,
- RuleExecutionLogClient,
- truncateMessageList,
-} from '../rule_execution_log';
-import { RuleExecutionStatus } from '../../../../common/detection_engine/schemas/common/schemas';
-import { scheduleThrottledNotificationActions } from '../notifications/schedule_throttle_notification_actions';
-import { IEventLogService } from '../../../../../event_log/server';
-
-export const signalRulesAlertType = ({
- logger,
- eventsTelemetry,
- experimentalFeatures,
- version,
- ml,
- lists,
- config,
- eventLogService,
- indexNameOverride,
- ruleExecutionLogClientOverride,
- refreshOverride,
-}: {
- logger: Logger;
- eventsTelemetry: TelemetryEventsSender | undefined;
- experimentalFeatures: ExperimentalFeatures;
- version: string;
- ml: SetupPlugins['ml'] | undefined;
- lists: SetupPlugins['lists'] | undefined;
- config: ConfigType;
- eventLogService: IEventLogService;
- indexNameOverride?: string;
- refreshOverride?: string;
- ruleExecutionLogClientOverride?: IRuleExecutionLogClient;
-}): SignalRuleAlertTypeDefinition => {
- const { alertMergeStrategy: mergeStrategy, alertIgnoreFields: ignoreFields } = config;
- return {
- id: SIGNALS_ID,
- name: 'SIEM signal',
- actionGroups: siemRuleActionGroups,
- defaultActionGroupId: 'default',
- useSavedObjectReferences: {
- extractReferences: (params) => extractReferences({ logger, params }),
- injectReferences: (params, savedObjectReferences) =>
- injectReferences({ logger, params, savedObjectReferences }),
- },
- validate: {
- params: {
- validate: (object: unknown): RuleParams => {
- const [validated, errors] = validateNonExact(object, ruleParams);
- if (errors != null) {
- throw new Error(errors);
- }
- if (validated == null) {
- throw new Error('Validation of rule params failed');
- }
- return validated;
- },
- },
- },
- producer: SERVER_APP_ID,
- minimumLicenseRequired: 'basic',
- isExportable: false,
- async executor({
- previousStartedAt,
- startedAt,
- state,
- alertId,
- services,
- params,
- spaceId,
- updatedBy: updatedByUser,
- rule,
- }) {
- const { ruleId, maxSignals, meta, outputIndex, timestampOverride, type } = params;
-
- const searchAfterSize = Math.min(maxSignals, DEFAULT_SEARCH_AFTER_PAGE_SIZE);
- let hasError: boolean = false;
- let result = createSearchAfterReturnType();
-
- const ruleStatusClient = ruleExecutionLogClientOverride
- ? ruleExecutionLogClientOverride
- : new RuleExecutionLogClient({
- underlyingClient: config.ruleExecutionLog.underlyingClient,
- savedObjectsClient: services.savedObjectsClient,
- eventLogService,
- logger,
- });
-
- const completeRule: CompleteRule = {
- alertId,
- ruleConfig: rule,
- ruleParams: params,
- };
-
- const {
- actions,
- name,
- schedule: { interval },
- ruleTypeId,
- } = completeRule.ruleConfig;
-
- const refresh = refreshOverride ?? actions.length ? 'wait_for' : false;
- const buildRuleMessage = buildRuleMessageFactory({
- id: alertId,
- ruleId,
- name,
- index: indexNameOverride ?? outputIndex,
- });
-
- logger.debug(buildRuleMessage('[+] Starting Signal Rule execution'));
- logger.debug(buildRuleMessage(`interval: ${interval}`));
- let wroteWarningStatus = false;
- const basicLogArguments = {
- spaceId,
- ruleId: alertId,
- ruleName: name,
- ruleType: ruleTypeId,
- };
-
- await ruleStatusClient.logStatusChange({
- ...basicLogArguments,
- newStatus: RuleExecutionStatus['going to run'],
- });
-
- const notificationRuleParams: NotificationRuleTypeParams = {
- ...params,
- name,
- id: alertId,
- };
-
- // check if rule has permissions to access given index pattern
- // move this collection of lines into a function in utils
- // so that we can use it in create rules route, bulk, etc.
- try {
- if (!isMachineLearningParams(params)) {
- const index = params.index;
- const hasTimestampOverride = timestampOverride != null && !isEmpty(timestampOverride);
- const inputIndices = await getInputIndex({
- services,
- version,
- index,
- experimentalFeatures,
- });
- const privileges = await checkPrivileges(services, inputIndices);
-
- wroteWarningStatus = await hasReadIndexPrivileges({
- ...basicLogArguments,
- privileges,
- logger,
- buildRuleMessage,
- ruleStatusClient,
- });
-
- if (!wroteWarningStatus) {
- const timestampFieldCaps = await services.scopedClusterClient.asCurrentUser.fieldCaps({
- index,
- fields: hasTimestampOverride
- ? ['@timestamp', timestampOverride as string]
- : ['@timestamp'],
- include_unmapped: true,
- });
- wroteWarningStatus = await hasTimestampFields({
- ...basicLogArguments,
- timestampField: hasTimestampOverride ? (timestampOverride as string) : '@timestamp',
- timestampFieldCapsResponse: timestampFieldCaps,
- inputIndices,
- ruleStatusClient,
- logger,
- buildRuleMessage,
- });
- }
- }
- } catch (exc) {
- const errorMessage = buildRuleMessage(`Check privileges failed to execute ${exc}`);
- logger.error(errorMessage);
- await ruleStatusClient.logStatusChange({
- ...basicLogArguments,
- message: errorMessage,
- newStatus: RuleExecutionStatus['partial failure'],
- });
- wroteWarningStatus = true;
- }
- const { tuples, remainingGap } = getRuleRangeTuples({
- logger,
- previousStartedAt,
- from: params.from,
- to: params.to,
- interval,
- maxSignals,
- buildRuleMessage,
- startedAt,
- });
-
- if (remainingGap.asMilliseconds() > 0) {
- const gapString = remainingGap.humanize();
- const gapMessage = buildRuleMessage(
- `${gapString} (${remainingGap.asMilliseconds()}ms) were not queried between this rule execution and the last execution, so signals may have been missed.`,
- 'Consider increasing your look behind time or adding more Kibana instances.'
- );
- logger.warn(gapMessage);
- hasError = true;
-
- await ruleStatusClient.logStatusChange({
- ...basicLogArguments,
- newStatus: RuleExecutionStatus.failed,
- message: gapMessage,
- metrics: { executionGap: remainingGap },
- });
- }
- try {
- const { listClient, exceptionsClient } = getListsClient({
- services,
- updatedByUser,
- spaceId,
- lists,
- savedObjectClient: services.savedObjectsClient,
- });
-
- const exceptionItems = await getExceptions({
- client: exceptionsClient,
- lists: params.exceptionsList ?? [],
- });
-
- const bulkCreate = bulkCreateFactory(
- logger,
- services.scopedClusterClient.asCurrentUser,
- buildRuleMessage,
- refresh,
- indexNameOverride
- );
-
- const wrapHits = wrapHitsFactory({
- completeRule,
- signalsIndex: indexNameOverride ?? params.outputIndex,
- mergeStrategy,
- ignoreFields,
- });
-
- const wrapSequences = wrapSequencesFactory({
- completeRule,
- signalsIndex: params.outputIndex,
- mergeStrategy,
- ignoreFields,
- });
-
- if (isMlRule(type)) {
- const mlRuleCompleteRule = asTypeSpecificCompleteRule(
- completeRule,
- machineLearningRuleParams
- );
- for (const tuple of tuples) {
- result = await mlExecutor({
- completeRule: mlRuleCompleteRule,
- tuple,
- ml,
- listClient,
- exceptionItems,
- services,
- logger,
- buildRuleMessage,
- bulkCreate,
- wrapHits,
- });
- }
- } else if (isThresholdRule(type)) {
- const thresholdCompleteRule = asTypeSpecificCompleteRule(
- completeRule,
- thresholdRuleParams
- );
- for (const tuple of tuples) {
- result = await thresholdExecutor({
- completeRule: thresholdCompleteRule,
- tuple,
- exceptionItems,
- experimentalFeatures,
- services,
- version,
- logger,
- buildRuleMessage,
- startedAt,
- state: state as ThresholdAlertState,
- bulkCreate,
- wrapHits,
- });
- }
- } else if (isThreatMatchRule(type)) {
- const threatCompleteRule = asTypeSpecificCompleteRule(completeRule, threatRuleParams);
- for (const tuple of tuples) {
- result = await threatMatchExecutor({
- completeRule: threatCompleteRule,
- tuple,
- listClient,
- exceptionItems,
- experimentalFeatures,
- services,
- version,
- searchAfterSize,
- logger,
- eventsTelemetry,
- buildRuleMessage,
- bulkCreate,
- wrapHits,
- });
- }
- } else if (isQueryRule(type)) {
- const queryCompleteRule = validateQueryRuleTypes(completeRule);
- for (const tuple of tuples) {
- result = await queryExecutor({
- completeRule: queryCompleteRule,
- tuple,
- listClient,
- exceptionItems,
- experimentalFeatures,
- services,
- version,
- searchAfterSize,
- logger,
- eventsTelemetry,
- buildRuleMessage,
- bulkCreate,
- wrapHits,
- });
- }
- } else if (isEqlRule(type)) {
- const eqlCompleteRule = asTypeSpecificCompleteRule(completeRule, eqlRuleParams);
- for (const tuple of tuples) {
- result = await eqlExecutor({
- completeRule: eqlCompleteRule,
- tuple,
- exceptionItems,
- experimentalFeatures,
- services,
- version,
- searchAfterSize,
- bulkCreate,
- logger,
- wrapHits,
- wrapSequences,
- });
- }
- }
-
- if (result.warningMessages.length) {
- const warningMessage = buildRuleMessage(
- truncateMessageList(result.warningMessages).join()
- );
- await ruleStatusClient.logStatusChange({
- ...basicLogArguments,
- newStatus: RuleExecutionStatus['partial failure'],
- message: warningMessage,
- });
- }
-
- if (result.success) {
- if (actions.length) {
- const fromInMs = parseScheduleDates(`now-${interval}`)?.format('x');
- const toInMs = parseScheduleDates('now')?.format('x');
- const resultsLink = getNotificationResultsLink({
- from: fromInMs,
- to: toInMs,
- id: alertId,
- kibanaSiemAppUrl: (meta as { kibana_siem_app_url?: string } | undefined)
- ?.kibana_siem_app_url,
- });
-
- logger.debug(
- buildRuleMessage(`Found ${result.createdSignalsCount} signals for notification.`)
- );
-
- if (completeRule.ruleConfig.throttle != null) {
- await scheduleThrottledNotificationActions({
- alertInstance: services.alertInstanceFactory(alertId),
- throttle: completeRule.ruleConfig.throttle,
- startedAt,
- id: alertId,
- kibanaSiemAppUrl: (meta as { kibana_siem_app_url?: string } | undefined)
- ?.kibana_siem_app_url,
- outputIndex: indexNameOverride ?? outputIndex,
- ruleId,
- signals: result.createdSignals,
- esClient: services.scopedClusterClient.asCurrentUser,
- notificationRuleParams,
- logger,
- });
- } else if (result.createdSignalsCount) {
- const alertInstance = services.alertInstanceFactory(alertId);
- scheduleNotificationActions({
- alertInstance,
- signalsCount: result.createdSignalsCount,
- signals: result.createdSignals,
- resultsLink,
- ruleParams: notificationRuleParams,
- });
- }
- }
-
- logger.debug(buildRuleMessage('[+] Signal Rule execution completed.'));
- logger.debug(
- buildRuleMessage(
- `[+] Finished indexing ${result.createdSignalsCount} signals into ${
- indexNameOverride ?? outputIndex
- }`
- )
- );
- if (!hasError && !wroteWarningStatus && !result.warning) {
- await ruleStatusClient.logStatusChange({
- ...basicLogArguments,
- newStatus: RuleExecutionStatus.succeeded,
- message: 'succeeded',
- metrics: {
- indexingDurations: result.bulkCreateTimes,
- searchDurations: result.searchAfterTimes,
- lastLookBackDate: result.lastLookBackDate?.toISOString(),
- },
- });
- }
-
- logger.debug(
- buildRuleMessage(
- `[+] Finished indexing ${result.createdSignalsCount} ${
- !isEmpty(tuples)
- ? `signals searched between date ranges ${JSON.stringify(tuples, null, 2)}`
- : ''
- }`
- )
- );
- } else {
- // NOTE: Since this is throttled we have to call it even on an error condition, otherwise it will "reset" the throttle and fire early
- if (completeRule.ruleConfig.throttle != null) {
- await scheduleThrottledNotificationActions({
- alertInstance: services.alertInstanceFactory(alertId),
- throttle: completeRule.ruleConfig.throttle ?? '',
- startedAt,
- id: completeRule.alertId,
- kibanaSiemAppUrl: (meta as { kibana_siem_app_url?: string } | undefined)
- ?.kibana_siem_app_url,
- outputIndex,
- ruleId,
- signals: result.createdSignals,
- esClient: services.scopedClusterClient.asCurrentUser,
- notificationRuleParams,
- logger,
- });
- }
- const errorMessage = buildRuleMessage(
- 'Bulk Indexing of signals failed:',
- truncateMessageList(result.errors).join()
- );
- logger.error(errorMessage);
- await ruleStatusClient.logStatusChange({
- ...basicLogArguments,
- newStatus: RuleExecutionStatus.failed,
- message: errorMessage,
- metrics: {
- indexingDurations: result.bulkCreateTimes,
- searchDurations: result.searchAfterTimes,
- lastLookBackDate: result.lastLookBackDate?.toISOString(),
- },
- });
- }
- } catch (error) {
- // NOTE: Since this is throttled we have to call it even on an error condition, otherwise it will "reset" the throttle and fire early
- if (completeRule.ruleConfig.throttle != null) {
- await scheduleThrottledNotificationActions({
- alertInstance: services.alertInstanceFactory(alertId),
- throttle: completeRule.ruleConfig.throttle ?? '',
- startedAt,
- id: completeRule.alertId,
- kibanaSiemAppUrl: (meta as { kibana_siem_app_url?: string } | undefined)
- ?.kibana_siem_app_url,
- outputIndex,
- ruleId,
- signals: result.createdSignals,
- esClient: services.scopedClusterClient.asCurrentUser,
- notificationRuleParams,
- logger,
- });
- }
- const errorMessage = error.message ?? '(no error message given)';
- const message = buildRuleMessage(
- 'An error occurred during rule execution:',
- `message: "${errorMessage}"`
- );
-
- logger.error(message);
- await ruleStatusClient.logStatusChange({
- ...basicLogArguments,
- newStatus: RuleExecutionStatus.failed,
- message,
- metrics: {
- indexingDurations: result.bulkCreateTimes,
- searchDurations: result.searchAfterTimes,
- lastLookBackDate: result.lastLookBackDate?.toISOString(),
- },
- });
- }
- },
- };
-};
-
-const validateQueryRuleTypes = (completeRule: CompleteRule) => {
- if (completeRule.ruleParams.type === 'query') {
- return asTypeSpecificCompleteRule(completeRule, queryRuleParams);
- } else {
- return asTypeSpecificCompleteRule(completeRule, savedQueryRuleParams);
- }
-};
-
-/**
- * This function takes a generic rule SavedObject and a type-specific schema for the rule params
- * and validates the SavedObject params against the schema. If they validate, it returns a SavedObject
- * where the params have been replaced with the validated params. This eliminates the need for logic that
- * checks if the required type specific fields actually exist on the SO and prevents rule executors from
- * accessing fields that only exist on other rule types.
- *
- * @param completeRule rule typed as an object with all fields from all different rule types
- * @param schema io-ts schema for the specific rule type the SavedObject claims to be
- */
-export const asTypeSpecificCompleteRule = (
- completeRule: CompleteRule,
- schema: T
-) => {
- const [validated, errors] = validateNonExact(completeRule.ruleParams, schema);
- if (validated == null || errors != null) {
- throw new Error(`Rule attempted to execute with invalid params: ${errors}`);
- }
- return {
- ...completeRule,
- ruleParams: validated,
- };
-};
diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts
index dffb984763818..0b7285ca3d444 100644
--- a/x-pack/plugins/security_solution/server/plugin.ts
+++ b/x-pack/plugins/security_solution/server/plugin.ts
@@ -38,8 +38,6 @@ import {
} from './lib/detection_engine/rule_types';
import { initRoutes } from './routes';
import { registerLimitedConcurrencyRoutes } from './routes/limited_concurrency';
-import { isAlertExecutor } from './lib/detection_engine/signals/types';
-import { signalRulesAlertType } from './lib/detection_engine/signals/signal_rule_alert_type';
import { ManifestTask } from './endpoint/lib/artifacts';
import { CheckMetadataTransformsTask } from './endpoint/lib/metadata';
import { initSavedObjects } from './saved_objects';
@@ -281,24 +279,9 @@ export class Plugin implements ISecuritySolutionPlugin {
plugins.features.registerKibanaFeature(getKibanaPrivilegesFeaturePrivileges(ruleTypes));
plugins.features.registerKibanaFeature(getCasesKibanaFeature());
- // Continue to register legacy rules against alerting client exposed through rule-registry
if (plugins.alerting != null) {
- const signalRuleType = signalRulesAlertType({
- logger,
- eventsTelemetry: this.telemetryEventsSender,
- version: pluginContext.env.packageInfo.version,
- ml: plugins.ml,
- lists: plugins.lists,
- config,
- experimentalFeatures,
- eventLogService,
- });
const ruleNotificationType = legacyRulesNotificationAlertType({ logger });
- if (isAlertExecutor(signalRuleType)) {
- plugins.alerting.registerType(signalRuleType);
- }
-
if (legacyIsNotificationAlertExecutor(ruleNotificationType)) {
plugins.alerting.registerType(ruleNotificationType);
}
diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts
index 14c1679d3a1b2..baa9eeb3ce036 100644
--- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts
+++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts
@@ -360,5 +360,18 @@ export default function createGetTests({ getService }: FtrProviderContext) {
'metrics.inventory_threshold.fired'
);
});
+
+ it('8.0 migrates and disables pre-existing rules', async () => {
+ const response = await es.get<{ alert: RawRule }>(
+ {
+ index: '.kibana',
+ id: 'alert:38482620-ef1b-11eb-ad71-7de7959be71c',
+ },
+ { meta: true }
+ );
+ expect(response.statusCode).to.eql(200);
+ expect(response.body._source?.alert?.alertTypeId).to.be('siem.queryRule');
+ expect(response.body._source?.alert?.enabled).to.be(false);
+ });
});
}
diff --git a/x-pack/test/functional/es_archives/alerts/data.json b/x-pack/test/functional/es_archives/alerts/data.json
index 249f14caf28f7..afa54208512f4 100644
--- a/x-pack/test/functional/es_archives/alerts/data.json
+++ b/x-pack/test/functional/es_archives/alerts/data.json
@@ -346,6 +346,7 @@
"consumer" : "alertsFixture",
"params" : {
"ruleId" : "4ec223b9-77fa-4895-8539-6b3e586a2858",
+ "type": "query",
"exceptionsList" : [
{
"id" : "endpoint_list",
From 0619acb91119fc8c97e92b627c6e593921f4de92 Mon Sep 17 00:00:00 2001
From: Nathan Reese
Date: Mon, 10 Jan 2022 12:34:48 -0700
Subject: [PATCH 08/19] [Maps] fix security solution network page (#122447)
* [Maps] fix security solution network page
* fix path
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../components/embeddables/__mocks__/mock.ts | 19 ++++++++++---------
.../components/embeddables/map_config.ts | 10 +++++-----
2 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/__mocks__/mock.ts b/x-pack/plugins/security_solution/public/network/components/embeddables/__mocks__/mock.ts
index 59328a68465fa..db6acd6d2a3bb 100644
--- a/x-pack/plugins/security_solution/public/network/components/embeddables/__mocks__/mock.ts
+++ b/x-pack/plugins/security_solution/public/network/components/embeddables/__mocks__/mock.ts
@@ -7,6 +7,7 @@
import { IndexPatternMapping } from '../types';
import { IndexPatternSavedObject } from '../../../../common/hooks/types';
+import { LAYER_TYPE } from '../../../../../../maps/common';
export const mockIndexPatternIds: IndexPatternMapping[] = [
{ title: 'filebeat-*', id: '8c7323ac-97ad-4b53-ac0a-40f8f691a918' },
@@ -68,7 +69,7 @@ export const mockSourceLayer = {
maxZoom: 24,
alpha: 1,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
joins: [],
};
@@ -125,7 +126,7 @@ export const mockDestinationLayer = {
maxZoom: 24,
alpha: 1,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
};
@@ -180,7 +181,7 @@ export const mockClientLayer = {
maxZoom: 24,
alpha: 1,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
joins: [],
};
@@ -242,7 +243,7 @@ export const mockServerLayer = {
maxZoom: 24,
alpha: 1,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
};
@@ -311,7 +312,7 @@ export const mockLineLayer = {
maxZoom: 24,
alpha: 0.5,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
};
@@ -375,7 +376,7 @@ export const mockClientServerLineLayer = {
maxZoom: 24,
alpha: 0.5,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
};
const mockApmDataStreamClientServerLineLayer = {
@@ -393,7 +394,7 @@ export const mockLayerList = [
alpha: 1,
visible: true,
style: null,
- type: 'VECTOR_TILE',
+ type: LAYER_TYPE.EMS_VECTOR_TILE,
},
mockLineLayer,
mockDestinationLayer,
@@ -410,7 +411,7 @@ export const mockLayerListDouble = [
alpha: 1,
visible: true,
style: null,
- type: 'VECTOR_TILE',
+ type: LAYER_TYPE.EMS_VECTOR_TILE,
},
mockLineLayer,
mockDestinationLayer,
@@ -430,7 +431,7 @@ export const mockLayerListMixed = [
alpha: 1,
visible: true,
style: null,
- type: 'VECTOR_TILE',
+ type: LAYER_TYPE.EMS_VECTOR_TILE,
},
mockLineLayer,
mockDestinationLayer,
diff --git a/x-pack/plugins/security_solution/public/network/components/embeddables/map_config.ts b/x-pack/plugins/security_solution/public/network/components/embeddables/map_config.ts
index 0f2c9fe942bed..348dd996b64c2 100644
--- a/x-pack/plugins/security_solution/public/network/components/embeddables/map_config.ts
+++ b/x-pack/plugins/security_solution/public/network/components/embeddables/map_config.ts
@@ -14,7 +14,7 @@ import {
LayerMappingDetails,
} from './types';
import * as i18n from './translations';
-import { SCALING_TYPES, SOURCE_TYPES } from '../../../../../maps/common';
+import { LAYER_TYPE, SCALING_TYPES, SOURCE_TYPES } from '../../../../../maps/common';
const euiVisColorPalette = euiPaletteColorBlind();
// Update field mappings to modify what fields will be returned to map tooltip
@@ -114,7 +114,7 @@ export const getLayerList = (indexPatternIds: IndexPatternMapping[]) => {
alpha: 1,
visible: true,
style: null,
- type: 'VECTOR_TILE',
+ type: LAYER_TYPE.EMS_VECTOR_TILE,
},
...indexPatternIds.reduce((acc: object[], { title, id }) => {
return [
@@ -184,7 +184,7 @@ export const getSourceLayer = (
maxZoom: 24,
alpha: 1,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
joins: [],
});
@@ -248,7 +248,7 @@ export const getDestinationLayer = (
maxZoom: 24,
alpha: 1,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
});
@@ -332,6 +332,6 @@ export const getLineLayer = (
maxZoom: 24,
alpha: 0.5,
visible: true,
- type: 'VECTOR',
+ type: LAYER_TYPE.GEOJSON_VECTOR,
query: { query: '', language: 'kuery' },
});
From a5072041f23a74f761143300ca65d5e859cd603f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ece=20=C3=96zalp?=
Date: Mon, 10 Jan 2022 15:48:58 -0500
Subject: [PATCH 09/19] fix flake (#122581)
Co-authored-by: Ece Ozalp
---
.../detection_engine/schemas/request/rule_schemas.mock.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.mock.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.mock.ts
index a51c1f77844d5..68371bca04eeb 100644
--- a/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.mock.ts
+++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/request/rule_schemas.mock.ts
@@ -58,6 +58,8 @@ export const getCreateThreatMatchRulesSchemaMock = (
threat_query: '*:*',
threat_index: ['list-index'],
threat_indicator_path: DEFAULT_INDICATOR_SOURCE_PATH,
+ interval: '5m',
+ from: 'now-6m',
threat_mapping: [
{
entries: [
From 4d47cb793b577d1f2f94f338abdd7ce2de94ce3b Mon Sep 17 00:00:00 2001
From: Kevin Logan <56395104+kevinlog@users.noreply.github.com>
Date: Mon, 10 Jan 2022 15:55:52 -0500
Subject: [PATCH 10/19] [Security Solution] Narrow down the skipped tests in
Policy (#122578)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../apps/endpoint/policy_details.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
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 0cf86e891e143..82079fd17b6c6 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
@@ -236,8 +236,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
);
};
- // Failing: See https://github.com/elastic/kibana/issues/100236
- describe.skip('When on the Endpoint Policy Details Page', function () {
+ describe('When on the Endpoint Policy Details Page', function () {
let indexedData: IndexedHostsAndAlertsResponse;
before(async () => {
@@ -539,7 +538,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await pageObjects.policy.waitForCheckboxSelectionChange('policyWindowsEvent_dns', false);
});
- it('should preserve updates done from the Fleet form', async () => {
+ // Failing: See https://github.com/elastic/kibana/issues/100236
+ it.skip('should preserve updates done from the Fleet form', async () => {
// Fleet has its own form inputs, like description. When those are updated, the changes
// are also dispatched to the embedded endpoint Policy form. Update to the Endpoint Policy
// form after that should preserve the changes done on the Fleet form
From b95ed1f1eb25da1f10a341ef3504b3d581778eb8 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 10 Jan 2022 15:16:06 -0600
Subject: [PATCH 11/19] Update dependency core-js to ^3.20.2 (main) (#122497)
* Update dependency core-js to ^3.20.2
* update yarn.lock
Co-authored-by: Renovate Bot
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 9f89b9845ae52..4c037f6e796f4 100644
--- a/package.json
+++ b/package.json
@@ -212,7 +212,7 @@
"constate": "^1.3.2",
"content-disposition": "0.5.3",
"copy-to-clipboard": "^3.0.8",
- "core-js": "^3.20.1",
+ "core-js": "^3.20.2",
"cronstrue": "^1.51.0",
"cytoscape": "^3.10.0",
"cytoscape-dagre": "^2.2.2",
diff --git a/yarn.lock b/yarn.lock
index f35058f15cd8a..d10195d55c6d2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10666,10 +10666,10 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.9:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2"
integrity sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==
-core-js@^3.0.4, core-js@^3.20.1, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3:
- version "3.20.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.1.tgz#eb1598047b7813572f1dc24b7c6a95528c99eef3"
- integrity sha512-btdpStYFQScnNVQ5slVcr858KP0YWYjV16eGJQw8Gg7CWtu/2qNvIM3qVRIR3n1pK2R9NNOrTevbvAYxajwEjg==
+core-js@^3.0.4, core-js@^3.6.5, core-js@^3.8.2, core-js@^3.8.3, core-js@^3.20.2:
+ version "3.20.2"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.2.tgz#46468d8601eafc8b266bd2dd6bf9dee622779581"
+ integrity sha512-nuqhq11DcOAbFBV4zCbKeGbKQsUDRqTX0oqx7AttUBuqe3h20ixsE039QHelbL6P4h+9kytVqyEtyZ6gsiwEYw==
core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0:
version "1.0.2"
From 6bf738fcf0d6444e77c24cd6f1e2a5478155f86c Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Mon, 10 Jan 2022 15:23:28 -0600
Subject: [PATCH 12/19] Update ftr (#122481)
Co-authored-by: Renovate Bot
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
package.json | 4 ++--
yarn.lock | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/package.json b/package.json
index 4c037f6e796f4..e1f6e7aba6e13 100644
--- a/package.json
+++ b/package.json
@@ -716,7 +716,7 @@
"callsites": "^3.1.0",
"chai": "3.5.0",
"chance": "1.0.18",
- "chromedriver": "^96.0.0",
+ "chromedriver": "^97.0.0",
"clean-webpack-plugin": "^3.0.0",
"cmd-shim": "^2.1.0",
"compression-webpack-plugin": "^4.0.0",
@@ -843,7 +843,7 @@
"rxjs-marbles": "^5.0.6",
"sass-loader": "^10.2.0",
"sass-resources-loader": "^2.0.1",
- "selenium-webdriver": "^4.1.0",
+ "selenium-webdriver": "^4.1.1",
"serve-static": "1.14.1",
"shelljs": "^0.8.4",
"simple-git": "1.116.0",
diff --git a/yarn.lock b/yarn.lock
index d10195d55c6d2..273d1912cb5ad 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9830,10 +9830,10 @@ chrome-trace-event@^1.0.2:
dependencies:
tslib "^1.9.0"
-chromedriver@^96.0.0:
- version "96.0.0"
- resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-96.0.0.tgz#c8473498e4c94950fa168187b112019cce9e5c6c"
- integrity sha512-4g6Hn5RHGsbaBmOrJbDlz/hdVPOc22eRsbvoAAMqkZxR2NJCcddHzCw2FAQeW8lX/C7xWVz3nyDsKX3fE9lIIw==
+chromedriver@^97.0.0:
+ version "97.0.0"
+ resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-97.0.0.tgz#7005b1a15a6456558d0fc4d5b72c98c12d1b033d"
+ integrity sha512-SZ9MW+/6/Ypz20CNdRKocsmRM2AJ/YwHaWpA1Np2QVPFUbhjhus6vBtqFD+l8M5qrktLWPQSjTwIsDckNfXIRg==
dependencies:
"@testim/chrome-version" "^1.0.7"
axios "^0.21.2"
@@ -25284,10 +25284,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.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.1.0.tgz#d11e5d43674e2718265a30684bcbf6ec734fd3bd"
- integrity sha512-kUDH4N8WruYprTzvug4Pl73Th+WKb5YiLz8z/anOpHyUNUdM3UzrdTOxmSNaf9AczzBeY+qXihzku8D1lMaKOg==
+selenium-webdriver@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-4.1.1.tgz#da083177d811f36614950e809e2982570f67d02e"
+ integrity sha512-Fr9e9LC6zvD6/j7NO8M1M/NVxFX67abHcxDJoP5w2KN/Xb1SyYLjMVPGgD14U2TOiKe4XKHf42OmFw9g2JgCBQ==
dependencies:
jszip "^3.6.0"
tmp "^0.2.1"
From e4a52b61445490f27816117b200690c5d9045668 Mon Sep 17 00:00:00 2001
From: Brian Seeders
Date: Mon, 10 Jan 2022 16:45:40 -0500
Subject: [PATCH 13/19] [buildkite] Migrate package-testing pipeline from
Jenkins (#122450)
---
.buildkite/pipelines/package_testing.yml | 27 +++++++++++++
.../scripts/steps/package_testing/build.sh | 12 ++++++
.../scripts/steps/package_testing/test.sh | 39 +++++++++++++++++++
3 files changed, 78 insertions(+)
create mode 100644 .buildkite/pipelines/package_testing.yml
create mode 100755 .buildkite/scripts/steps/package_testing/build.sh
create mode 100755 .buildkite/scripts/steps/package_testing/test.sh
diff --git a/.buildkite/pipelines/package_testing.yml b/.buildkite/pipelines/package_testing.yml
new file mode 100644
index 0000000000000..e9e1ca896c949
--- /dev/null
+++ b/.buildkite/pipelines/package_testing.yml
@@ -0,0 +1,27 @@
+steps:
+ - command: .buildkite/scripts/steps/package_testing/build.sh
+ label: Build Packages
+ agents:
+ queue: c2-16
+ timeout_in_minutes: 60
+ if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''"
+
+ - wait
+
+ - command: TEST_PACKAGE=deb .buildkite/scripts/steps/package_testing/test.sh
+ label: Package testing for deb
+ agents:
+ queue: n2-4-virt
+ timeout_in_minutes: 60
+
+ - command: TEST_PACKAGE=rpm .buildkite/scripts/steps/package_testing/test.sh
+ label: Package testing for rpm
+ agents:
+ queue: n2-4-virt
+ timeout_in_minutes: 60
+
+ - command: TEST_PACKAGE=docker .buildkite/scripts/steps/package_testing/test.sh
+ label: Package testing for docker
+ agents:
+ queue: n2-4-virt
+ timeout_in_minutes: 60
diff --git a/.buildkite/scripts/steps/package_testing/build.sh b/.buildkite/scripts/steps/package_testing/build.sh
new file mode 100755
index 0000000000000..0711003f34adf
--- /dev/null
+++ b/.buildkite/scripts/steps/package_testing/build.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+.buildkite/scripts/bootstrap.sh
+
+echo "--- Build Kibana Distribution"
+node scripts/build --all-platforms --debug
+
+cd target
+buildkite-agent artifact upload "./kibana-[0-9]*-docker-image.tar.gz;./*.deb;./*.rpm"
+cd ..
diff --git a/.buildkite/scripts/steps/package_testing/test.sh b/.buildkite/scripts/steps/package_testing/test.sh
new file mode 100755
index 0000000000000..eb2f20eea4525
--- /dev/null
+++ b/.buildkite/scripts/steps/package_testing/test.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+.buildkite/scripts/bootstrap.sh
+
+echo "--- Package Testing for $TEST_PACKAGE"
+
+mkdir -p target
+cd target
+if [[ "$TEST_PACKAGE" == "deb" ]]; then
+ buildkite-agent artifact download 'kibana-*.deb' . --build "${KIBANA_BUILD_ID:-$BUILDKITE_BUILD_ID}"
+ KIBANA_IP_ADDRESS="192.168.50.5"
+elif [[ "$TEST_PACKAGE" == "rpm" ]]; then
+ buildkite-agent artifact download 'kibana-*.rpm' . --build "${KIBANA_BUILD_ID:-$BUILDKITE_BUILD_ID}"
+ KIBANA_IP_ADDRESS="192.168.50.6"
+elif [[ "$TEST_PACKAGE" == "docker" ]]; then
+ buildkite-agent artifact download 'kibana-*-docker-image.tar.gz' . --build "${KIBANA_BUILD_ID:-$BUILDKITE_BUILD_ID}"
+ KIBANA_IP_ADDRESS="192.168.50.7"
+fi
+cd ..
+
+export VAGRANT_CWD=test/package
+vagrant up "$TEST_PACKAGE" --no-provision
+
+node scripts/es snapshot \
+ -E network.bind_host=127.0.0.1,192.168.50.1 \
+ -E discovery.type=single-node \
+ --license=trial &
+while ! timeout 1 bash -c "echo > /dev/tcp/localhost/9200"; do sleep 30; done
+
+vagrant provision "$TEST_PACKAGE"
+
+export TEST_BROWSER_HEADLESS=1
+export TEST_KIBANA_URL="http://elastic:changeme@$KIBANA_IP_ADDRESS:5601"
+export TEST_ES_URL=http://elastic:changeme@192.168.50.1:9200
+
+cd x-pack
+node scripts/functional_test_runner.js --include-tag=smoke
From 1d270503cbd8063bf74e424657ec73f95f28631d Mon Sep 17 00:00:00 2001
From: Dominique Clarke
Date: Mon, 10 Jan 2022 17:05:51 -0500
Subject: [PATCH 14/19] [Exploratory View] add a global filter to exploratory
view when there is only one series (#122301)
* add a global filter to exploratory view when there is only one series
* adjust types
* addjust sample lens attributes
* fix breakdown column order
* update tests
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: shahzad31
---
.../configurations/lens_attributes.test.ts | 7 +++++-
.../configurations/lens_attributes.ts | 22 +++++++++++++++++--
.../test_data/sample_attribute.ts | 3 ++-
.../test_data/sample_attribute_cwv.ts | 3 ++-
.../test_data/sample_attribute_kpi.ts | 2 +-
5 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts
index 9dc27b84bef0e..9c636edaac197 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.test.ts
@@ -482,6 +482,11 @@ describe('Lens Attribute', () => {
});
});
+ it('should not use global filters when there is more than one series', function () {
+ const multiSeriesLensAttr = new LensAttributes([layerConfig, layerConfig]).getJSON();
+ expect(multiSeriesLensAttr.state.query.query).toEqual('transaction.duration.us < 60000000');
+ });
+
describe('Layer breakdowns', function () {
it('should return breakdown column', function () {
const layerConfig1: LayerConfig = {
@@ -521,8 +526,8 @@ describe('Lens Attribute', () => {
expect(lnsAttr.layers.layer0).toEqual({
columnOrder: [
- 'x-axis-column-layer0',
'breakdown-column-layer0',
+ 'x-axis-column-layer0',
'y-axis-column-layer0',
'y-axis-column-layer0X0',
'y-axis-column-layer0X1',
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts
index 6d912e18f180f..f873b1eb5cbab 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/lens_attributes.ts
@@ -102,6 +102,7 @@ export class LensAttributes {
visualization: XYState;
layerConfigs: LayerConfig[];
isMultiSeries: boolean;
+ globalFilter?: { query: string; language: string };
constructor(layerConfigs: LayerConfig[]) {
this.layers = {};
@@ -119,10 +120,27 @@ export class LensAttributes {
this.layerConfigs = layerConfigs;
this.isMultiSeries = layerConfigs.length > 1;
+ this.globalFilter = this.getGlobalFilter(this.isMultiSeries);
this.layers = this.getLayers();
this.visualization = this.getXyState();
}
+ getGlobalFilter(isMultiSeries: boolean) {
+ if (isMultiSeries) {
+ return undefined;
+ }
+ const defaultLayerFilter = this.layerConfigs[0].seriesConfig.query
+ ? ` and ${this.layerConfigs[0].seriesConfig.query.query}`
+ : '';
+ return {
+ query: `${this.getLayerFilters(
+ this.layerConfigs[0],
+ this.layerConfigs.length
+ )}${defaultLayerFilter}`,
+ language: 'kuery',
+ };
+ }
+
getBreakdownColumn({
sourceField,
layerId,
@@ -676,10 +694,10 @@ export class LensAttributes {
layers[layerId] = {
columnOrder: [
- `x-axis-column-${layerId}`,
...(breakdown && sourceField !== USE_BREAK_DOWN_COLUMN && breakdown !== PERCENTILE
? [`breakdown-column-${layerId}`]
: []),
+ `x-axis-column-${layerId}`,
`y-axis-column-${layerId}`,
...Object.keys(this.getChildYAxises(layerConfig, layerId, columnFilter)),
],
@@ -770,7 +788,7 @@ export class LensAttributes {
new Set([...this.layerConfigs.map(({ indexPattern }) => indexPattern.id)])
);
- const query = this.layerConfigs[0].seriesConfig.query;
+ const query = this.globalFilter || this.layerConfigs[0].seriesConfig.query;
return {
title: 'Prefilled from exploratory view app',
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts
index cfbd2a5df0358..1a9c87fc826bd 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute.ts
@@ -155,7 +155,8 @@ export const sampleAttribute = {
filters: [],
query: {
language: 'kuery',
- query: 'transaction.duration.us < 60000000',
+ query:
+ 'transaction.type: page-load and processor.event: transaction and transaction.type : * and transaction.duration.us < 60000000',
},
visualization: {
axisTitlesVisibilitySettings: {
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts
index 4563509eeb19a..5f373de200897 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_cwv.ts
@@ -95,7 +95,8 @@ export const sampleAttributeCoreWebVital = {
filters: [],
query: {
language: 'kuery',
- query: 'transaction.type: "page-load"',
+ query:
+ 'transaction.type: page-load and processor.event: transaction and transaction.type: "page-load"',
},
visualization: {
axisTitlesVisibilitySettings: {
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts
index 668049dcc122b..415b2eb0d4c7a 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/configurations/test_data/sample_attribute_kpi.ts
@@ -57,7 +57,7 @@ export const sampleAttributeKpi = {
filters: [],
query: {
language: 'kuery',
- query: '',
+ query: 'transaction.type: page-load and processor.event: transaction',
},
visualization: {
axisTitlesVisibilitySettings: {
From e8141fc5bda740fd3772f0ced336d85dedc6ff3a Mon Sep 17 00:00:00 2001
From: Dominique Clarke
Date: Mon, 10 Jan 2022 17:07:27 -0500
Subject: [PATCH 15/19] exploratory view - remove add series button tooltip by
managing focus (#122263)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
---
.../series_editor/columns/data_type_select.tsx | 7 ++++++-
.../series_editor/report_metric_options.tsx | 7 ++++++-
.../shared/exploratory_view/views/add_series_button.tsx | 7 ++++++-
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx
index e17d0f9afad4e..778a4737e81b4 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/columns/data_type_select.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { useState } from 'react';
+import React, { useState, useCallback } from 'react';
import {
EuiButton,
EuiPopover,
@@ -33,6 +33,10 @@ export function DataTypesSelect({ seriesId, series }: Props) {
const { setSeries, reportType } = useSeriesStorage();
const [showOptions, setShowOptions] = useState(false);
+ const focusButton = useCallback((ref: HTMLButtonElement) => {
+ ref?.focus();
+ }, []);
+
const onDataTypeChange = (dataType: AppDataType) => {
if (String(dataType) !== SELECT_DATA_TYPE) {
setSeries(seriesId, {
@@ -72,6 +76,7 @@ export function DataTypesSelect({ seriesId, series }: Props) {
onClick={() => setShowOptions((prevState) => !prevState)}
fill
size="s"
+ buttonRef={focusButton}
>
{SELECT_DATA_TYPE_LABEL}
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx
index e3e63af94118e..5eec147379d25 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/report_metric_options.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { useState } from 'react';
+import React, { useState, useCallback } from 'react';
import {
EuiToolTip,
EuiPopover,
@@ -44,6 +44,10 @@ export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) {
});
};
+ const focusButton = useCallback((ref: HTMLButtonElement) => {
+ ref?.focus();
+ }, []);
+
if (!series.dataType) {
return null;
}
@@ -107,6 +111,7 @@ export function ReportMetricOptions({ seriesId, series, seriesConfig }: Props) {
fill
size="s"
isLoading={!indexPattern && loading}
+ buttonRef={focusButton}
>
{SELECT_REPORT_METRIC_LABEL}
diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx
index c4542a47e8291..4c1bc1d7fe3bb 100644
--- a/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx
+++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/views/add_series_button.tsx
@@ -5,7 +5,7 @@
* 2.0.
*/
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useRef } from 'react';
import { EuiToolTip, EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
@@ -18,6 +18,7 @@ import { useExploratoryView } from '../contexts/exploratory_view_config';
export function AddSeriesButton() {
const [editorItems, setEditorItems] = useState([]);
+ const addSeriesButtonRef = useRef(null);
const { getSeries, allSeries, setSeries, reportType } = useSeriesStorage();
const { loading, indexPatterns } = useAppIndexPatternContext();
@@ -32,6 +33,9 @@ export function AddSeriesButton() {
const prevSeries = allSeries?.[0];
const name = `${NEW_SERIES_KEY}-${editorItems.length + 1}`;
const nextSeries = { name } as SeriesUrl;
+ if (addSeriesButtonRef?.current) {
+ addSeriesButtonRef.current.blur();
+ }
const nextSeriesId = allSeries.length;
@@ -73,6 +77,7 @@ export function AddSeriesButton() {
isDisabled={isAddDisabled}
iconType="plusInCircle"
size="s"
+ buttonRef={addSeriesButtonRef}
>
{i18n.translate('xpack.observability.expView.seriesBuilder.addSeries', {
defaultMessage: 'Add series',
From b5d5ba972d467046a1098c552aff83bb7550ea8a Mon Sep 17 00:00:00 2001
From: Lisa Cawley
Date: Mon, 10 Jan 2022 14:24:33 -0800
Subject: [PATCH 16/19] Use doc link service in ILM (#122104)
---
.../client_integration/app/app.helpers.tsx | 9 +++++-
.../edit_policy/init_test_bed.tsx | 2 ++
.../__jest__/policy_table.test.tsx | 5 ++-
.../public/application/index.tsx | 6 +++-
.../components/learn_more_link.tsx | 4 +--
.../components/phases/hot_phase/hot_phase.tsx | 6 ++--
.../no_custom_attributes_messages.tsx | 9 +++---
.../components/node_allocation.tsx | 32 +++++++++----------
.../phases/shared_fields/forcemerge_field.tsx | 7 ++--
.../shared_fields/index_priority_field.tsx | 5 ++-
.../phases/shared_fields/readonly_field.tsx | 5 +--
.../searchable_snapshot_field.tsx | 24 +++++++++-----
.../phases/shared_fields/shrink_field.tsx | 4 ++-
.../shared_fields/snapshot_policies_field.tsx | 4 +--
.../components/timeline/timeline.tsx | 6 +++-
.../sections/edit_policy/edit_policy.tsx | 9 ++----
.../add_policy_to_template_confirm_modal.tsx | 5 ++-
.../application/services/documentation.ts | 28 ----------------
.../public/plugin.tsx | 9 ++----
.../public/types.ts | 2 ++
20 files changed, 92 insertions(+), 89 deletions(-)
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/documentation.ts
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx
index ff9980c1d2777..8d55a3e093a31 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/app/app.helpers.tsx
@@ -8,6 +8,7 @@
import React from 'react';
import { act } from 'react-dom/test-utils';
import { registerTestBed, TestBed, TestBedConfig } from '@kbn/test/jest';
+import { docLinksServiceMock } from 'src/core/public/mocks';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import { createBreadcrumbsMock } from '../../../public/application/services/breadcrumbs.mock';
import { licensingMock } from '../../../../licensing/public/mocks';
@@ -17,7 +18,13 @@ const breadcrumbService = createBreadcrumbsMock();
const AppWithContext = (props: any) => {
return (
-
+
);
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/init_test_bed.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/init_test_bed.tsx
index 54d68edc7382f..251ff234c230e 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/init_test_bed.tsx
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/init_test_bed.tsx
@@ -7,6 +7,7 @@
import React from 'react';
import { registerTestBed, TestBedConfig } from '@kbn/test/jest';
+import { docLinksServiceMock } from 'src/core/public/mocks';
import '../helpers/global_mocks';
@@ -35,6 +36,7 @@ const EditPolicyContainer = ({ appServicesContext, ...rest }: any) => {
services={{
breadcrumbService,
license: licensingMock.createLicense({ license: { type: 'enterprise' } }),
+ docLinks: docLinksServiceMock.createStartContract(),
getUrlForApp: () => {},
...appServicesContext,
}}
diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx
index cf25b1c335ae9..1a45b2c6d93dc 100644
--- a/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx
+++ b/x-pack/plugins/index_lifecycle_management/__jest__/policy_table.test.tsx
@@ -14,6 +14,7 @@ import { findTestSubject, takeMountedSnapshot } from '@elastic/eui/lib/test';
import {
fatalErrorsServiceMock,
injectedMetadataServiceMock,
+ docLinksServiceMock,
} from '../../../../src/core/public/mocks';
import { HttpService } from '../../../../src/core/public/http';
import { usageCollectionPluginMock } from '../../../../src/plugins/usage_collection/public/mocks';
@@ -99,7 +100,9 @@ const testSort = (headerName: string) => {
const TestComponent = ({ testPolicies }: { testPolicies: PolicyFromES[] }) => {
return (
- '' }}>
+ '', docLinks: docLinksServiceMock.createStartContract() }}
+ >
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx
index 933a2fd28e07f..5dd0ca5f1c409 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/index.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/index.tsx
@@ -15,6 +15,7 @@ import {
UnmountCallback,
CoreTheme,
} from 'src/core/public';
+import { DocLinksStart } from 'kibana/public';
import {
CloudSetup,
@@ -35,6 +36,7 @@ export const renderApp = (
breadcrumbService: BreadcrumbService,
license: ILicense,
theme$: Observable,
+ docLinks: DocLinksStart,
cloud?: CloudSetup
): UnmountCallback => {
const { getUrlForApp } = application;
@@ -42,7 +44,9 @@ export const renderApp = (
-
+
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/learn_more_link.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/learn_more_link.tsx
index 5e7923898a99a..660cc753623c9 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/learn_more_link.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/learn_more_link.tsx
@@ -9,8 +9,6 @@ import React, { ReactNode } from 'react';
import { EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
-import { createDocLink } from '../../../services/documentation';
-
interface Props {
docPath: string;
text?: ReactNode;
@@ -23,7 +21,7 @@ export const LearnMoreLink: React.FunctionComponent = ({ docPath, text })
);
return (
-
+
{content}
);
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
index 3e67cabf570a4..8905200779d23 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/hot_phase/hot_phase.tsx
@@ -11,7 +11,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { EuiSpacer, EuiCallOut, EuiTextColor, EuiSwitch, EuiText } from '@elastic/eui';
-import { useFormData } from '../../../../../../shared_imports';
+import { useFormData, useKibana } from '../../../../../../shared_imports';
import { i18nTexts } from '../../../i18n_texts';
@@ -52,6 +52,8 @@ export const HotPhase: FunctionComponent = () => {
const showEmptyRolloverFieldsError = useRolloverValueRequiredValidation();
+ const { docLinks } = useKibana().services;
+
return (
{
defaultMessage="Learn more"
/>
}
- docPath="ilm-rollover.html"
+ docPath={docLinks.links.elasticsearch.ilmRollover}
/>
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_custom_attributes_messages.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_custom_attributes_messages.tsx
index d31818e3557b1..01f10cf2d98ce 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_custom_attributes_messages.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/no_custom_attributes_messages.tsx
@@ -10,9 +10,6 @@ import { EuiLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { DocLinksStart } from 'src/core/public';
-
-import { getNodeAllocationMigrationLink } from '../../../../../../../services/documentation';
-
export interface Props {
docLinks: DocLinksStart;
}
@@ -28,7 +25,11 @@ export const nodeAllocationMigrationGuidance = ({ docLinks }: Props) => (
defaultMessage="To allocate data to particular data nodes, {roleBasedGuidance} or configure custom node attributes in elasticsearch.yml."
values={{
roleBasedGuidance: (
-
+
{i18n.translate(
'xpack.indexLifecycleMgmt.editPolicy.defaultToDataNodesDescription.migrationGuidanceMessage',
{
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx
index 323f5144ac837..a2bad060a5893 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/data_tier_allocation_field/components/node_allocation.tsx
@@ -11,7 +11,7 @@ import { get } from 'lodash';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiButtonEmpty, EuiText, EuiSpacer } from '@elastic/eui';
-import { SelectField, useFormData } from '../../../../../../../../shared_imports';
+import { SelectField, useFormData, useKibana } from '../../../../../../../../shared_imports';
import { UseField } from '../../../../../form';
@@ -21,18 +21,6 @@ import { NodeAttrsDetails } from './node_attrs_details';
import { SharedProps } from './types';
-const learnMoreLink = (
-
- }
- docPath="modules-cluster.html#cluster-shard-allocation-settings"
- />
-);
-
const i18nTexts = {
allocateToDataNodesOption: i18n.translate(
'xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.allocateToDataNodesOption',
@@ -52,7 +40,8 @@ export const NodeAllocation: FunctionComponent = ({
const [formData] = useFormData({
watch: [allocationNodeAttributePath],
});
-
+ const { docLinks } = useKibana().services;
+ const shardAllocationSettingsUrl = docLinks.links.elasticsearch.shardAllocationSettings;
const selectedAllocationNodeAttribute = get(formData, allocationNodeAttributePath);
const [selectedNodeAttrsForDetails, setSelectedNodeAttrsForDetails] = useState(
@@ -79,7 +68,6 @@ export const NodeAllocation: FunctionComponent = ({
}
nodeAllocationOptions = nodeAllocationOptions.concat(nodeOptions);
-
return (
<>
@@ -87,7 +75,19 @@ export const NodeAllocation: FunctionComponent = ({
+ }
+ docPath={shardAllocationSettingsUrl}
+ />
+ ),
+ }}
/>
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx
index d6f5e97c166e4..04a57fd2d9ace 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/forcemerge_field.tsx
@@ -10,8 +10,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
import uuid from 'uuid';
import { EuiCheckbox, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui';
-import { NumericField } from '../../../../../../shared_imports';
-
+import { NumericField, useKibana } from '../../../../../../shared_imports';
import { i18nTexts } from '../../../i18n_texts';
import { useEditPolicyContext } from '../../../edit_policy_context';
@@ -31,6 +30,8 @@ export const ForcemergeField: React.FunctionComponent = ({ phase }) => {
return policy.phases[phase]?.actions?.forcemerge != null;
}, [policy, phase]);
+ const { docLinks } = useKibana().services;
+
return (
= ({ phase }) => {
id="xpack.indexLifecycleMgmt.editPolicy.forceMerge.enableExplanationText"
defaultMessage="Reduce the number of segments in each index shard and clean up deleted documents."
/>{' '}
-
+
>
}
titleSize="xs"
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index_priority_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index_priority_field.tsx
index 1665e4a360ad0..309e283c14d7c 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index_priority_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index_priority_field.tsx
@@ -17,6 +17,7 @@ import { useEditPolicyContext } from '../../../edit_policy_context';
import { UseField } from '../../../form';
import { LearnMoreLink, DescribedFormRow } from '../..';
+import { useKibana } from '../../../../../../shared_imports';
interface Props {
phase: PhaseExceptDelete;
@@ -33,6 +34,8 @@ export const IndexPriorityField: FunctionComponent = ({ phase }) => {
);
}, [isNewPolicy, policy.phases, phase]);
+ const { docLinks } = useKibana().services;
+
return (
= ({ phase }) => {
defaultMessage="Set the priority for recovering your indices after a node restart.
Indices with higher priorities are recovered before indices with lower priorities."
/>{' '}
-
+
}
titleSize="xs"
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/readonly_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/readonly_field.tsx
index 85805f1a266af..4283f357bff88 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/readonly_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/readonly_field.tsx
@@ -10,12 +10,13 @@ import { FormattedMessage } from '@kbn/i18n-react';
import { EuiTextColor } from '@elastic/eui';
import { LearnMoreLink } from '../../learn_more_link';
import { ToggleFieldWithDescribedFormRow } from '../../described_form_row';
-
+import { useKibana } from '../../../../../../shared_imports';
interface Props {
phase: 'hot' | 'warm' | 'cold';
}
export const ReadonlyField: React.FunctionComponent = ({ phase }) => {
+ const { docLinks } = useKibana().services;
return (
= ({ phase }) => {
id="xpack.indexLifecycleMgmt.editPolicy.readonlyDescription"
defaultMessage="Enable to make the index and index metadata read only, disable to allow writes and metadata changes."
/>{' '}
-
+
}
fullWidth
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx
index 3cfb83878812f..ac15441a49590 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx
@@ -25,7 +25,11 @@ export interface Props {
canBeDisabled?: boolean;
}
-const geti18nTexts = (phase: Props['phase']) => {
+const geti18nTexts = (
+ phase: Props['phase'],
+ fullyMountedSearchableSnapshotLink: string,
+ partiallyMountedSearchableSnapshotLink: string
+) => {
switch (phase) {
// Hot and cold phases both create fully mounted snapshots.
case 'hot':
@@ -42,7 +46,7 @@ const geti18nTexts = (phase: Props['phase']) => {
id="xpack.indexLifecycleMgmt.editPolicy.fullyMountedSearchableSnapshotField.description"
defaultMessage="Convert to a fully-mounted index that contains a complete copy of your data and is backed by a snapshot. You can reduce the number of replicas and rely on the snapshot for resiliency. {learnMoreLink}"
values={{
- learnMoreLink: ,
+ learnMoreLink: ,
}}
/>
),
@@ -66,9 +70,7 @@ const geti18nTexts = (phase: Props['phase']) => {
id="xpack.indexLifecycleMgmt.editPolicy.frozenPhase.partiallyMountedSearchableSnapshotField.description"
defaultMessage="Convert to a partially-mounted index that caches the index metadata. Data is retrieved from the snapshot as needed to process search requests. This minimizes the index footprint while keeping all of your data fully searchable. {learnMoreLink}"
values={{
- learnMoreLink: (
-
- ),
+ learnMoreLink: ,
}}
/>
),
@@ -85,7 +87,7 @@ export const SearchableSnapshotField: FunctionComponent = ({
canBeDisabled = true,
}) => {
const {
- services: { cloud, getUrlForApp },
+ services: { cloud, docLinks, getUrlForApp },
} = useKibana();
const { policy, license, isNewPolicy } = useEditPolicyContext();
const { isUsingSearchableSnapshotInHotPhase } = useConfiguration();
@@ -109,8 +111,14 @@ export const SearchableSnapshotField: FunctionComponent = ({
policy.phases[phase]?.actions?.searchable_snapshot?.snapshot_repository
)
);
-
- const i18nTexts = geti18nTexts(phase);
+ const fullyMountedSearchableSnapshotLink = docLinks.links.elasticsearch.ilmSearchableSnapshot;
+ const partiallyMountedSearchableSnapshotLink =
+ docLinks.links.elasticsearch.searchableSnapshotSharedCache;
+ const i18nTexts = geti18nTexts(
+ phase,
+ fullyMountedSearchableSnapshotLink,
+ partiallyMountedSearchableSnapshotLink
+ );
useEffect(() => {
if (isDisabledDueToLicense) {
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx
index 9439afd1c071d..adcc33fdc8697 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/shrink_field.tsx
@@ -19,6 +19,7 @@ import { i18nTexts } from '../../../i18n_texts';
import { LearnMoreLink, DescribedFormRow } from '../../';
import { byteSizeUnits } from '../../../constants';
import { UnitField } from './unit_field';
+import { useKibana } from '../../../../../../shared_imports';
interface Props {
phase: 'hot' | 'warm';
@@ -35,6 +36,7 @@ export const ShrinkField: FunctionComponent = ({ phase }) => {
const path = `phases.${phase}.actions.shrink.${
isUsingShardSize ? 'max_primary_shard_size' : 'number_of_shards'
}`;
+ const { docLinks } = useKibana().services;
return (
= ({ phase }) => {
id="xpack.indexLifecycleMgmt.editPolicy.shrinkIndexExplanationText"
defaultMessage="Shrink the index to a new index with fewer primary shards."
/>{' '}
-
+
}
titleSize="xs"
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx
index 89e43b2675854..791a70ae6212d 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/snapshot_policies_field.tsx
@@ -29,7 +29,7 @@ const waitForSnapshotFormField = 'phases.delete.actions.wait_for_snapshot.policy
export const SnapshotPoliciesField: React.FunctionComponent = () => {
const {
- services: { getUrlForApp },
+ services: { docLinks, getUrlForApp },
} = useKibana();
const { error, isLoading, data, resendRequest } = useLoadSnapshotPolicies();
const [formData] = useFormData({
@@ -159,7 +159,7 @@ export const SnapshotPoliciesField: React.FunctionComponent = () => {
id="xpack.indexLifecycleMgmt.editPolicy.deletePhase.waitForSnapshotDescription"
defaultMessage="Specify a snapshot policy to be executed before the deletion of the index. This ensures that a snapshot of the deleted index is available."
/>{' '}
-
+
>
}
titleSize="xs"
diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx
index b04445162e48b..d56f69248e2c1 100644
--- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/timeline/timeline.tsx
@@ -11,6 +11,8 @@ import { FormattedMessage } from '@kbn/i18n-react';
import React, { FunctionComponent, memo } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiText, EuiIconTip } from '@elastic/eui';
+import { useKibana } from '../../../../../shared_imports';
+
import { PhaseExceptDelete } from '../../../../../../common/types';
import {
@@ -141,6 +143,8 @@ export const Timeline: FunctionComponent = memo(
) : null;
+ const { docLinks } = useKibana().services;
+
return (
@@ -151,7 +155,7 @@ export const Timeline: FunctionComponent = memo(
{i18nTexts.description}
{
} = useEditPolicyContext();
const {
- services: { cloud },
+ services: { cloud, docLinks },
} = useKibana();
const [isClonedPolicy, setIsClonedPolicy] = useState(false);
@@ -166,11 +165,7 @@ export const EditPolicy: React.FunctionComponent = () => {
}
bottomBorder
rightSideItems={[
-
+
= (
}
);
+ const { docLinks } = useKibana().services;
+
return (
= (
all indices which match the index template."
/>{' '}
`${_esDocBasePath}${docPath}`;
-export const getNodeAllocationMigrationLink = ({ links }: DocLinksStart) =>
- `${links.elasticsearch.migrateIndexAllocationFilters}`;
diff --git a/x-pack/plugins/index_lifecycle_management/public/plugin.tsx b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx
index d59fd4f20e63f..7700518506cea 100644
--- a/x-pack/plugins/index_lifecycle_management/public/plugin.tsx
+++ b/x-pack/plugins/index_lifecycle_management/public/plugin.tsx
@@ -11,7 +11,6 @@ import { CoreSetup, PluginInitializerContext, Plugin } from 'src/core/public';
import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public';
import { PLUGIN } from '../common/constants';
import { init as initHttp } from './application/services/http';
-import { init as initDocumentation } from './application/services/documentation';
import { init as initUiMetric } from './application/services/ui_metric';
import { init as initNotification } from './application/services/notification';
import { BreadcrumbService } from './application/services/breadcrumbs';
@@ -55,8 +54,8 @@ export class IndexLifecycleManagementPlugin
const {
chrome: { docTitle },
i18n: { Context: I18nContext },
- docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION },
application,
+ docLinks,
} = coreStart;
const license = await licensing.license$.pipe(first()).toPromise();
@@ -64,11 +63,6 @@ export class IndexLifecycleManagementPlugin
docTitle.change(PLUGIN.TITLE);
this.breadcrumbService.setup(setBreadcrumbs);
- // Initialize additional services.
- initDocumentation(
- `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`
- );
-
const { renderApp } = await import('./application');
const unmountAppCallback = renderApp(
@@ -79,6 +73,7 @@ export class IndexLifecycleManagementPlugin
this.breadcrumbService,
license,
theme$,
+ docLinks,
cloud
);
diff --git a/x-pack/plugins/index_lifecycle_management/public/types.ts b/x-pack/plugins/index_lifecycle_management/public/types.ts
index 0339d124e1279..6c8239fd44da3 100644
--- a/x-pack/plugins/index_lifecycle_management/public/types.ts
+++ b/x-pack/plugins/index_lifecycle_management/public/types.ts
@@ -6,6 +6,7 @@
*/
import { ApplicationStart } from 'kibana/public';
+import { DocLinksStart } from 'src/core/public';
import { HomePublicPluginSetup } from '../../../../src/plugins/home/public';
import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public';
import { ManagementSetup } from '../../../../src/plugins/management/public';
@@ -40,4 +41,5 @@ export interface AppServicesContext {
license: ILicense;
cloud?: CloudSetup;
getUrlForApp: ApplicationStart['getUrlForApp'];
+ docLinks: DocLinksStart;
}
From b8e9b884033256ca51bc28270db2166cc3682d63 Mon Sep 17 00:00:00 2001
From: Clint Andrew Hall
Date: Mon, 10 Jan 2022 17:35:16 -0500
Subject: [PATCH 17/19] [storybook] Enable Shared UX Storybook build in CI
(#122598)
---
.../scripts/steps/storybooks/build_and_upload.js | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/.buildkite/scripts/steps/storybooks/build_and_upload.js b/.buildkite/scripts/steps/storybooks/build_and_upload.js
index 86bfb4eeebf94..328c769d81c66 100644
--- a/.buildkite/scripts/steps/storybooks/build_and_upload.js
+++ b/.buildkite/scripts/steps/storybooks/build_and_upload.js
@@ -14,12 +14,11 @@ const path = require('path');
const STORYBOOKS = [
'apm',
'canvas',
- 'codeeditor',
'ci_composite',
+ 'codeeditor',
'custom_integrations',
- 'url_template_editor',
- 'dashboard',
'dashboard_enhanced',
+ 'dashboard',
'data_enhanced',
'embeddable',
'expression_error',
@@ -31,11 +30,13 @@ const STORYBOOKS = [
'expression_tagcloud',
'fleet',
'infra',
- 'security_solution',
- 'ui_actions_enhanced',
+ 'lists',
'observability',
'presentation',
- 'lists',
+ 'security_solution',
+ 'shared_ux',
+ 'ui_actions_enhanced',
+ 'url_template_editor',
];
const GITHUB_CONTEXT = 'Build and Publish Storybooks';
From af7f28fc5dcf92baeb1af65533aefa0e617d9fed Mon Sep 17 00:00:00 2001
From: Lee Drengenberg
Date: Mon, 10 Jan 2022 17:00:49 -0600
Subject: [PATCH 18/19] have to select elasticsearch cluster for stack
_monitoring_metricbeat test (#122583)
* have to select elasticsearch cluster for the same test now
* remove unused browser component
* add ;
---
.../apps/monitoring/_monitoring_metricbeat.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js b/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js
index 79b3b98aafddd..7c1a93eef8fb6 100644
--- a/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js
+++ b/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js
@@ -13,6 +13,7 @@ export default ({ getService, getPageObjects }) => {
const testSubjects = getService('testSubjects');
const isSaml = !!process.env.VM.includes('saml') || !!process.env.VM.includes('oidc');
const clusterOverview = getService('monitoringClusterOverview');
+ const find = getService('find');
before(async () => {
await browser.setWindowSize(1200, 800);
@@ -30,6 +31,7 @@ export default ({ getService, getPageObjects }) => {
});
it('should have Monitoring already enabled', async () => {
+ await find.clickByLinkText('elasticsearch');
await testSubjects.click('esOverview');
});
From 1b971c90c32ff660173ac49bfcea69e11014c1a7 Mon Sep 17 00:00:00 2001
From: Scotty Bollinger
Date: Mon, 10 Jan 2022 17:03:45 -0600
Subject: [PATCH 19/19] [Enterprise Search] Update CODEOWNERS (#122590)
---
.github/CODEOWNERS | 26 +-------------------------
1 file changed, 1 insertion(+), 25 deletions(-)
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 0858731b4eaf1..a02a9681e482f 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -339,32 +339,8 @@
#CC# /x-pack/plugins/stack_alerts @elastic/kibana-alerting-services
# Enterprise Search
-# Shared
-/x-pack/plugins/enterprise_search/* @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/common/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/public/* @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/public/applications/* @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/public/applications/enterprise_search/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/public/applications/shared/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/public/applications/__mocks__/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/server/* @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/server/lib/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/server/__mocks__/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/server/collectors/enterprise_search/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/server/collectors/lib/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/server/routes/enterprise_search/ @elastic/enterprise-search-frontend
-/x-pack/plugins/enterprise_search/server/saved_objects/enterprise_search/ @elastic/enterprise-search-frontend
+/x-pack/plugins/enterprise_search @elastic/enterprise-search-frontend
/x-pack/test/functional_enterprise_search/ @elastic/enterprise-search-frontend
-# App Search
-/x-pack/plugins/enterprise_search/public/applications/app_search/ @elastic/app-search-frontend
-/x-pack/plugins/enterprise_search/server/routes/app_search/ @elastic/app-search-frontend
-/x-pack/plugins/enterprise_search/server/collectors/app_search/ @elastic/app-search-frontend
-/x-pack/plugins/enterprise_search/server/saved_objects/app_search/ @elastic/app-search-frontend
-# Workplace Search
-/x-pack/plugins/enterprise_search/public/applications/workplace_search/ @elastic/workplace-search-frontend
-/x-pack/plugins/enterprise_search/server/routes/workplace_search/ @elastic/workplace-search-frontend
-/x-pack/plugins/enterprise_search/server/collectors/workplace_search/ @elastic/workplace-search-frontend
-/x-pack/plugins/enterprise_search/server/saved_objects/workplace_search/ @elastic/workplace-search-frontend
# Management Experience - Deployment Management
/src/plugins/dev_tools/ @elastic/platform-deployment-management