From 104b1607b7ac2dc86d711876d70631029f431392 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Fri, 15 Apr 2022 14:38:58 +0100 Subject: [PATCH 01/68] fix(NA): use correct rule on yarn_install force at @kbn/pm --- packages/kbn-pm/dist/index.js | 2 +- packages/kbn-pm/src/commands/bootstrap.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 46686c2d7b791..691495e0a7922 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -11871,7 +11871,7 @@ const BootstrapCommand = { await time('force install dependencies', async () => { await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["removeYarnIntegrityFileIfExists"])(Object(path__WEBPACK_IMPORTED_MODULE_0__["resolve"])(kibanaProjectPath, 'node_modules')); await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['clean', '--expunge']); - await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['run', '@yarn//:yarn'], runOffline, { + await Object(_utils_bazel__WEBPACK_IMPORTED_MODULE_9__["runBazel"])(['run', '@nodejs//:yarn'], runOffline, { env: { SASS_BINARY_SITE: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-sass', RE2_DOWNLOAD_MIRROR: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-re2' diff --git a/packages/kbn-pm/src/commands/bootstrap.ts b/packages/kbn-pm/src/commands/bootstrap.ts index 2dd59d499b585..a1dd4d38cfb8a 100644 --- a/packages/kbn-pm/src/commands/bootstrap.ts +++ b/packages/kbn-pm/src/commands/bootstrap.ts @@ -72,7 +72,7 @@ export const BootstrapCommand: ICommand = { await time('force install dependencies', async () => { await removeYarnIntegrityFileIfExists(resolve(kibanaProjectPath, 'node_modules')); await runBazel(['clean', '--expunge']); - await runBazel(['run', '@yarn//:yarn'], runOffline, { + await runBazel(['run', '@nodejs//:yarn'], runOffline, { env: { SASS_BINARY_SITE: 'https://us-central1-elastic-kibana-184716.cloudfunctions.net/kibana-ci-proxy-cache/node-sass', From 3bc9c42485f4504887ce5d073283e04044a494cf Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Tue, 3 May 2022 16:49:37 -0400 Subject: [PATCH 02/68] [CI] Use GCS buckets for bazel remote caching (#131345) --- .buildkite/scripts/common/setup_bazel.sh | 36 +++++++++++++------ .../steps/bazel_cache/bootstrap_mac.sh | 2 +- .../steps/on_merge_ts_refs_api_docs.sh | 2 +- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/.buildkite/scripts/common/setup_bazel.sh b/.buildkite/scripts/common/setup_bazel.sh index 96cd04fa612fd..e3791dfa393c7 100755 --- a/.buildkite/scripts/common/setup_bazel.sh +++ b/.buildkite/scripts/common/setup_bazel.sh @@ -11,8 +11,29 @@ cat < $KIBANA_DIR/.bazelrc build --build_metadata=ROLE=CI EOF -if [[ "${BAZEL_CACHE_MODE:-none}" == read* ]]; then - echo "[bazel] enabling caching" +BAZEL_CACHE_MODE=${BAZEL_CACHE_MODE:-gcs} + +if [[ "$BAZEL_CACHE_MODE" == "gcs" ]]; then + echo "[bazel] enabling caching with GCS buckets" + + BAZEL_REGION="us-central1" + if [[ "$(curl -is metadata.google.internal || true)" ]]; then + # projects/1003139005402/zones/us-central1-a -> us-central1-a -> us-central1 + BAZEL_REGION=$(curl -sH Metadata-Flavor:Google http://metadata.google.internal/computeMetadata/v1/instance/zone | rev | cut -d'/' -f1 | cut -c3- | rev) + fi + + BAZEL_BUCKET="kibana-ci-bazel_$BAZEL_REGION" + + echo "[bazel] using GCS bucket: $BAZEL_BUCKET" + +cat <> $KIBANA_DIR/.bazelrc + build --remote_cache=https://storage.googleapis.com/$BAZEL_BUCKET + build --google_default_credentials +EOF +fi + +if [[ "$BAZEL_CACHE_MODE" == "buildbuddy" ]]; then + echo "[bazel] enabling caching with Buildbuddy" cat <> $KIBANA_DIR/.bazelrc build --bes_results_url=https://app.buildbuddy.io/invocation/ build --bes_backend=grpcs://remote.buildbuddy.io @@ -22,14 +43,7 @@ cat <> $KIBANA_DIR/.bazelrc EOF fi -if [[ "${BAZEL_CACHE_MODE:-none}" == "read" ]]; then - echo "[bazel] cache set to read-only" -cat <> $KIBANA_DIR/.bazelrc - build --noremote_upload_local_results -EOF -fi - -if [[ "${BAZEL_CACHE_MODE:-none}" != @(read|read-write|none|) ]]; then - echo "invalid value for BAZEL_CACHE_MODE received ($BAZEL_CACHE_MODE), expected one of [read,read-write,none]" +if [[ "$BAZEL_CACHE_MODE" != @(gcs|buildbuddy|none|) ]]; then + echo "invalid value for BAZEL_CACHE_MODE received ($BAZEL_CACHE_MODE), expected one of [gcs,buildbuddy,none]" exit 1 fi diff --git a/.buildkite/scripts/steps/bazel_cache/bootstrap_mac.sh b/.buildkite/scripts/steps/bazel_cache/bootstrap_mac.sh index 1417137f0b6f0..62aabf496fd8a 100755 --- a/.buildkite/scripts/steps/bazel_cache/bootstrap_mac.sh +++ b/.buildkite/scripts/steps/bazel_cache/bootstrap_mac.sh @@ -2,7 +2,7 @@ set -euo pipefail -export BAZEL_CACHE_MODE=read-write +export BAZEL_CACHE_MODE=buildbuddy export DISABLE_BOOTSTRAP_VALIDATION=true # Since our Mac agents are currently static, diff --git a/.buildkite/scripts/steps/on_merge_ts_refs_api_docs.sh b/.buildkite/scripts/steps/on_merge_ts_refs_api_docs.sh index 6d08fbb2c6835..5659db50e1404 100755 --- a/.buildkite/scripts/steps/on_merge_ts_refs_api_docs.sh +++ b/.buildkite/scripts/steps/on_merge_ts_refs_api_docs.sh @@ -2,7 +2,7 @@ set -euo pipefail -export BAZEL_CACHE_MODE=read-write # Populate bazel remote cache for linux +export BAZEL_CACHE_MODE=buildbuddy # Populate Buildbuddy bazel remote cache for linux export BUILD_TS_REFS_CACHE_ENABLE=true export BUILD_TS_REFS_CACHE_CAPTURE=true export DISABLE_BOOTSTRAP_VALIDATION=true From 28092ef609a9dd92193bd68691378ee67ef304fb Mon Sep 17 00:00:00 2001 From: mgiota Date: Tue, 3 May 2022 23:27:09 +0200 Subject: [PATCH 03/68] [Actionable Observability] Add license modal to rules table (#131232) * Add fix license link * fix localization * fix CI error * fix more translation issues Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../rules/components/execution_status.tsx | 44 ++++++++++++++- .../rules/components/manage_license_model.tsx | 55 +++++++++++++++++++ .../public/pages/rules/index.tsx | 6 +- .../observability/public/pages/rules/types.ts | 2 + 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/observability/public/pages/rules/components/manage_license_model.tsx diff --git a/x-pack/plugins/observability/public/pages/rules/components/execution_status.tsx b/x-pack/plugins/observability/public/pages/rules/components/execution_status.tsx index 81dfe9ebd1606..c0c7413aa9c15 100644 --- a/x-pack/plugins/observability/public/pages/rules/components/execution_status.tsx +++ b/x-pack/plugins/observability/public/pages/rules/components/execution_status.tsx @@ -5,14 +5,22 @@ * 2.0. */ -import React from 'react'; -import { EuiHealth, EuiToolTip, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import React, { useState } from 'react'; +import { EuiHealth, EuiToolTip, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; import { RuleExecutionStatusErrorReasons } from '@kbn/alerting-plugin/common'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { ManageLicenseModal } from './manage_license_model'; import { getHealthColor, rulesStatusesTranslationsMapping } from '../config'; import { RULE_STATUS_LICENSE_ERROR } from '../translations'; import { ExecutionStatusProps } from '../types'; +import { useKibana } from '../../../utils/kibana_react'; -export function ExecutionStatus({ executionStatus }: ExecutionStatusProps) { +export function ExecutionStatus({ executionStatus, item, licenseType }: ExecutionStatusProps) { + const { http } = useKibana().services; + const [manageLicenseModalOpts, setManageLicenseModalOpts] = useState<{ + licenseType: string; + ruleTypeId: string; + } | null>(null); const healthColor = getHealthColor(executionStatus.status); const tooltipMessage = executionStatus.status === 'error' ? `Error: ${executionStatus?.error?.message}` : null; @@ -38,6 +46,36 @@ export function ExecutionStatus({ executionStatus }: ExecutionStatusProps) { return ( {healthWithTooltip} + {isLicenseError && ( + + + setManageLicenseModalOpts({ + licenseType, + ruleTypeId: item.ruleTypeId, + }) + } + > + + + + )} + {manageLicenseModalOpts && ( + { + window.open(`${http.basePath.get()}/app/management/stack/license_management`, '_blank'); + setManageLicenseModalOpts(null); + }} + onCancel={() => setManageLicenseModalOpts(null)} + /> + )} ); } diff --git a/x-pack/plugins/observability/public/pages/rules/components/manage_license_model.tsx b/x-pack/plugins/observability/public/pages/rules/components/manage_license_model.tsx new file mode 100644 index 0000000000000..e273c7d5a3044 --- /dev/null +++ b/x-pack/plugins/observability/public/pages/rules/components/manage_license_model.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiConfirmModal } from '@elastic/eui'; +import { capitalize } from 'lodash'; + +interface Props { + licenseType: string; + ruleTypeId: string; + onConfirm: () => void; + onCancel: () => void; +} + +export function ManageLicenseModal({ licenseType, ruleTypeId, onConfirm, onCancel }: Props) { + const licenseRequired = capitalize(licenseType); + return ( + +

+ +

+
+ ); +} diff --git a/x-pack/plugins/observability/public/pages/rules/index.tsx b/x-pack/plugins/observability/public/pages/rules/index.tsx index 693c5dd11f4d1..3d005c30fc747 100644 --- a/x-pack/plugins/observability/public/pages/rules/index.tsx +++ b/x-pack/plugins/observability/public/pages/rules/index.tsx @@ -205,7 +205,11 @@ function RulesPage() { width: '120px', 'data-test-subj': 'rulesTableCell-status', render: (_executionStatus: RuleExecutionStatus, item: RuleTableItem) => ( - + ), }, { diff --git a/x-pack/plugins/observability/public/pages/rules/types.ts b/x-pack/plugins/observability/public/pages/rules/types.ts index cbcd97919cddc..8b3e337b99bd8 100644 --- a/x-pack/plugins/observability/public/pages/rules/types.ts +++ b/x-pack/plugins/observability/public/pages/rules/types.ts @@ -45,6 +45,8 @@ export interface StatusFilterProps { export interface ExecutionStatusProps { executionStatus: RuleExecutionStatus; + item: RuleTableItem; + licenseType: string; } export interface LastRunProps { From 07985db97a4f926e798fa9f3ca59085856d10aaa Mon Sep 17 00:00:00 2001 From: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com> Date: Tue, 3 May 2022 15:57:25 -0700 Subject: [PATCH 04/68] [RAM] Add shareable rule status filter (#130705) * rule state filter * turn off experiment * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Status filter API call * Fix tests * rename state to status, added tests * Address comments and fix tests * Revert experiment flag * Remove unused translations * Addressed comments Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .../public/hooks/use_fetch_rules.ts | 2 +- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - .../common/experimental_features.ts | 1 + .../rule_status_filter_sandbox.tsx | 26 ++++ .../shareable_components_sandbox.tsx | 2 + .../lib/rule_api/aggregate.test.ts | 80 +++++++++++ .../application/lib/rule_api/aggregate.ts | 13 +- .../lib/rule_api/map_filters_to_kql.test.ts | 56 +++++++- .../lib/rule_api/map_filters_to_kql.ts | 41 +++++- .../application/lib/rule_api/rules.test.ts | 97 +++++++++++++ .../public/application/lib/rule_api/rules.ts | 13 +- .../public/application/sections/index.tsx | 3 + .../sections/rule_details/components/rule.tsx | 2 +- .../rule_execution_status_filter.tsx | 107 +++++++++++++++ .../components/rule_status_filter.test.tsx | 64 +++++++++ .../components/rule_status_filter.tsx | 127 ++++++++---------- .../rules_list/components/rules_list.test.tsx | 41 ++++++ .../rules_list/components/rules_list.tsx | 32 ++++- .../common/get_experimental_features.test.tsx | 5 + .../public/common/get_rule_status_filter.tsx | 14 ++ .../public/common/types.ts | 2 + .../triggers_actions_ui/public/mocks.ts | 4 + .../triggers_actions_ui/public/plugin.ts | 6 + .../triggers_actions_ui/public/types.ts | 6 +- .../apps/triggers_actions_ui/alerts_list.ts | 63 ++++++++- .../apps/triggers_actions_ui/index.ts | 1 + .../triggers_actions_ui/rule_status_filter.ts | 54 ++++++++ x-pack/test/functional_with_es_ssl/config.ts | 1 + .../lib/alert_api_actions.ts | 13 ++ 31 files changed, 785 insertions(+), 94 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rule_status_filter_sandbox.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_execution_status_filter.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.test.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/common/get_rule_status_filter.tsx create mode 100644 x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rule_status_filter.ts diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts index 00cb58e504bdc..a09626654e6f8 100644 --- a/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts +++ b/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts @@ -42,7 +42,7 @@ export function useFetchRules({ page, searchText, typesFilter: typesFilter.length > 0 ? typesFilter : OBSERVABILITY_RULE_TYPES, - ruleStatusesFilter: ruleLastResponseFilter, + ruleExecutionStatusesFilter: ruleLastResponseFilter, sort, }); setRulesState((oldState) => ({ diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 66cae51a7b414..9bc497a66f473 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -29364,7 +29364,6 @@ "xpack.triggersActionsUI.sections.rulesList.ruleStatusActive": "Actif", "xpack.triggersActionsUI.sections.rulesList.ruleStatusDropdownMenuLabel": "Modifier le statut de la règle ou répéter", "xpack.triggersActionsUI.sections.rulesList.ruleStatusError": "Erreur", - "xpack.triggersActionsUI.sections.rulesList.ruleStatusFilterLabel": "Dernière réponse", "xpack.triggersActionsUI.sections.rulesList.ruleStatusLicenseError": "Erreur de licence", "xpack.triggersActionsUI.sections.rulesList.ruleStatusOk": "Ok", "xpack.triggersActionsUI.sections.rulesList.ruleStatusPending": "En attente", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 70b2f076d5f8c..9c22df3fdabb2 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -29433,7 +29433,6 @@ "xpack.triggersActionsUI.sections.rulesList.ruleStatusActive": "アクティブ", "xpack.triggersActionsUI.sections.rulesList.ruleStatusDropdownMenuLabel": "ルールステータスまたはスヌーズを変更", "xpack.triggersActionsUI.sections.rulesList.ruleStatusError": "エラー", - "xpack.triggersActionsUI.sections.rulesList.ruleStatusFilterLabel": "前回の応答", "xpack.triggersActionsUI.sections.rulesList.ruleStatusLicenseError": "ライセンスエラー", "xpack.triggersActionsUI.sections.rulesList.ruleStatusOk": "OK", "xpack.triggersActionsUI.sections.rulesList.ruleStatusPending": "保留中", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e249662ac511b..6c6a5d60ed320 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -29468,7 +29468,6 @@ "xpack.triggersActionsUI.sections.rulesList.ruleStatusActive": "活动", "xpack.triggersActionsUI.sections.rulesList.ruleStatusDropdownMenuLabel": "更改规则状态或暂停", "xpack.triggersActionsUI.sections.rulesList.ruleStatusError": "错误", - "xpack.triggersActionsUI.sections.rulesList.ruleStatusFilterLabel": "上次响应", "xpack.triggersActionsUI.sections.rulesList.ruleStatusLicenseError": "许可证错误", "xpack.triggersActionsUI.sections.rulesList.ruleStatusOk": "确定", "xpack.triggersActionsUI.sections.rulesList.ruleStatusPending": "待处理", diff --git a/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts b/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts index 21835a5977216..0a0b8cdeab208 100644 --- a/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts +++ b/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts @@ -15,6 +15,7 @@ export const allowedExperimentalValues = Object.freeze({ rulesListDatagrid: true, internalAlertsTable: false, internalShareableComponentsSandbox: false, + ruleStatusFilter: false, rulesDetailLogs: true, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rule_status_filter_sandbox.tsx b/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rule_status_filter_sandbox.tsx new file mode 100644 index 0000000000000..99ddd8daf16ac --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/rule_status_filter_sandbox.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useState } from 'react'; +import { RuleStatusFilterProps } from '../../../types'; +import { getRuleStatusFilterLazy } from '../../../common/get_rule_status_filter'; + +export const RuleStatusFilterSandbox = () => { + const [selectedStatuses, setSelectedStatuses] = useState< + RuleStatusFilterProps['selectedStatuses'] + >([]); + + return ( +
+ {getRuleStatusFilterLazy({ + selectedStatuses, + onChange: setSelectedStatuses, + })} +
Selected states: {JSON.stringify(selectedStatuses)}
+
+ ); +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/shareable_components_sandbox.tsx b/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/shareable_components_sandbox.tsx index d756804bbd406..bedcbb03045a5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/shareable_components_sandbox.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/internal/shareable_components_sandbox/shareable_components_sandbox.tsx @@ -7,12 +7,14 @@ import React from 'react'; import { RuleStatusDropdownSandbox } from './rule_status_dropdown_sandbox'; +import { RuleStatusFilterSandbox } from './rule_status_filter_sandbox'; import { RuleTagBadgeSandbox } from './rule_tag_badge_sandbox'; export const InternalShareableComponentsSandbox: React.FC<{}> = () => { return ( <> + ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts index 46653e5bc3911..ab8f1b565c888 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.test.ts @@ -209,4 +209,84 @@ describe('loadRuleAggregations', () => { ] `); }); + + test('should call aggregate API with ruleStatusesFilter', async () => { + const resolvedValue = { + rule_execution_status: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }; + http.get.mockResolvedValue(resolvedValue); + + let result = await loadRuleAggregations({ + http, + ruleStatusesFilter: ['enabled'], + }); + + expect(result).toEqual({ + ruleExecutionStatus: { + ok: 4, + active: 2, + error: 1, + pending: 1, + unknown: 0, + }, + }); + + expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_aggregate", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.enabled:(true) and not (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)", + "search": undefined, + "search_fields": undefined, + }, + }, + ] + `); + + result = await loadRuleAggregations({ + http, + ruleStatusesFilter: ['enabled', 'snoozed'], + }); + + expect(http.get.mock.calls[1]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_aggregate", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.enabled:(true) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)", + "search": undefined, + "search_fields": undefined, + }, + }, + ] + `); + + result = await loadRuleAggregations({ + http, + ruleStatusesFilter: ['enabled', 'disabled', 'snoozed'], + }); + + expect(http.get.mock.calls[1]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_aggregate", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.enabled:(true) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)", + "search": undefined, + "search_fields": undefined, + }, + }, + ] + `); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts index c7bcd438ef697..9548445d0df9c 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/aggregate.ts @@ -6,7 +6,7 @@ */ import { HttpSetup } from '@kbn/core/public'; import { AsApiContract, RewriteRequestCase } from '@kbn/actions-plugin/common'; -import { RuleAggregations } from '../../../types'; +import { RuleAggregations, RuleStatus } from '../../../types'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; import { mapFiltersToKql } from './map_filters_to_kql'; @@ -29,15 +29,22 @@ export async function loadRuleAggregations({ searchText, typesFilter, actionTypesFilter, + ruleExecutionStatusesFilter, ruleStatusesFilter, }: { http: HttpSetup; searchText?: string; typesFilter?: string[]; actionTypesFilter?: string[]; - ruleStatusesFilter?: string[]; + ruleExecutionStatusesFilter?: string[]; + ruleStatusesFilter?: RuleStatus[]; }): Promise { - const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, ruleStatusesFilter }); + const filters = mapFiltersToKql({ + typesFilter, + actionTypesFilter, + ruleExecutionStatusesFilter, + ruleStatusesFilter, + }); const res = await http.get>( `${INTERNAL_BASE_ALERTING_API_PATH}/rules/_aggregate`, { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.test.ts index e1dd14a7a9fde..df762d05e0eff 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.test.ts @@ -32,14 +32,62 @@ describe('mapFiltersToKql', () => { ]); }); - test('should handle ruleStatusesFilter', () => { + test('should handle ruleExecutionStatusesFilter', () => { expect( mapFiltersToKql({ - ruleStatusesFilter: ['alert', 'statuses', 'filter'], + ruleExecutionStatusesFilter: ['alert', 'statuses', 'filter'], }) ).toEqual(['alert.attributes.executionStatus.status:(alert or statuses or filter)']); }); + test('should handle ruleStatusesFilter', () => { + expect( + mapFiltersToKql({ + ruleStatusesFilter: ['enabled'], + }) + ).toEqual([ + 'alert.attributes.enabled:(true) and not (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)', + ]); + + expect( + mapFiltersToKql({ + ruleStatusesFilter: ['disabled'], + }) + ).toEqual([ + 'alert.attributes.enabled:(false) and not (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)', + ]); + + expect( + mapFiltersToKql({ + ruleStatusesFilter: ['snoozed'], + }) + ).toEqual(['(alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)']); + + expect( + mapFiltersToKql({ + ruleStatusesFilter: ['enabled', 'snoozed'], + }) + ).toEqual([ + 'alert.attributes.enabled:(true) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)', + ]); + + expect( + mapFiltersToKql({ + ruleStatusesFilter: ['disabled', 'snoozed'], + }) + ).toEqual([ + 'alert.attributes.enabled:(false) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)', + ]); + + expect( + mapFiltersToKql({ + ruleStatusesFilter: ['enabled', 'disabled', 'snoozed'], + }) + ).toEqual([ + 'alert.attributes.enabled:(true or false) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)', + ]); + }); + test('should handle typesFilter and actionTypesFilter', () => { expect( mapFiltersToKql({ @@ -52,12 +100,12 @@ describe('mapFiltersToKql', () => { ]); }); - test('should handle typesFilter, actionTypesFilter and ruleStatusesFilter', () => { + test('should handle typesFilter, actionTypesFilter and ruleExecutionStatusesFilter', () => { expect( mapFiltersToKql({ typesFilter: ['type', 'filter'], actionTypesFilter: ['action', 'types', 'filter'], - ruleStatusesFilter: ['alert', 'statuses', 'filter'], + ruleExecutionStatusesFilter: ['alert', 'statuses', 'filter'], }) ).toEqual([ 'alert.attributes.alertTypeId:(type or filter)', diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.ts index d7b22a7a4aee4..0e64f5500454f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/map_filters_to_kql.ts @@ -5,16 +5,34 @@ * 2.0. */ +import { RuleStatus } from '../../../types'; + +const getEnablementFilter = (ruleStatusFilter: RuleStatus[] = []) => { + const enablementFilters = ruleStatusFilter.reduce((result, filter) => { + if (filter === 'enabled') { + return [...result, 'true']; + } + if (filter === 'disabled') { + return [...result, 'false']; + } + return result; + }, []); + return `alert.attributes.enabled:(${enablementFilters.join(' or ')})`; +}; + export const mapFiltersToKql = ({ typesFilter, actionTypesFilter, + ruleExecutionStatusesFilter, ruleStatusesFilter, }: { typesFilter?: string[]; actionTypesFilter?: string[]; - ruleStatusesFilter?: string[]; + ruleExecutionStatusesFilter?: string[]; + ruleStatusesFilter?: RuleStatus[]; }): string[] => { const filters = []; + if (typesFilter && typesFilter.length) { filters.push(`alert.attributes.alertTypeId:(${typesFilter.join(' or ')})`); } @@ -29,8 +47,27 @@ export const mapFiltersToKql = ({ ].join('') ); } + if (ruleExecutionStatusesFilter && ruleExecutionStatusesFilter.length) { + filters.push( + `alert.attributes.executionStatus.status:(${ruleExecutionStatusesFilter.join(' or ')})` + ); + } + if (ruleStatusesFilter && ruleStatusesFilter.length) { - filters.push(`alert.attributes.executionStatus.status:(${ruleStatusesFilter.join(' or ')})`); + const enablementFilter = getEnablementFilter(ruleStatusesFilter); + const snoozedFilter = `(alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)`; + const hasEnablement = + ruleStatusesFilter.includes('enabled') || ruleStatusesFilter.includes('disabled'); + const hasSnoozed = ruleStatusesFilter.includes('snoozed'); + + if (hasEnablement && !hasSnoozed) { + filters.push(`${enablementFilter} and not ${snoozedFilter}`); + } else if (!hasEnablement && hasSnoozed) { + filters.push(snoozedFilter); + } else { + filters.push(`${enablementFilter} or ${snoozedFilter}`); + } } + return filters; }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts index 5f6c6e938a0a7..8adc92738b7c6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.test.ts @@ -239,4 +239,101 @@ describe('loadRules', () => { ] `); }); + + test('should call find API with ruleStatusesilter', async () => { + const resolvedValue = { + page: 1, + per_page: 10, + total: 0, + data: [], + }; + http.get.mockResolvedValue(resolvedValue); + + let result = await loadRules({ + http, + ruleStatusesFilter: ['enabled', 'snoozed'], + page: { index: 0, size: 10 }, + }); + expect(result).toEqual({ + page: 1, + perPage: 10, + total: 0, + data: [], + }); + expect(http.get.mock.calls[0]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.enabled:(true) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)", + "page": 1, + "per_page": 10, + "search": undefined, + "search_fields": undefined, + "sort_field": "name", + "sort_order": "asc", + }, + }, + ] + `); + + result = await loadRules({ + http, + ruleStatusesFilter: ['disabled'], + page: { index: 0, size: 10 }, + }); + expect(result).toEqual({ + page: 1, + perPage: 10, + total: 0, + data: [], + }); + expect(http.get.mock.calls[1]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.enabled:(false) and not (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)", + "page": 1, + "per_page": 10, + "search": undefined, + "search_fields": undefined, + "sort_field": "name", + "sort_order": "asc", + }, + }, + ] + `); + + result = await loadRules({ + http, + ruleStatusesFilter: ['enabled', 'disabled', 'snoozed'], + page: { index: 0, size: 10 }, + }); + expect(result).toEqual({ + page: 1, + perPage: 10, + total: 0, + data: [], + }); + expect(http.get.mock.calls[2]).toMatchInlineSnapshot(` + Array [ + "/internal/alerting/rules/_find", + Object { + "query": Object { + "default_search_operator": "AND", + "filter": "alert.attributes.enabled:(true or false) or (alert.attributes.muteAll:true OR alert.attributes.snoozeEndTime > now)", + "page": 1, + "per_page": 10, + "search": undefined, + "search_fields": undefined, + "sort_field": "name", + "sort_order": "asc", + }, + }, + ] + `); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts index 52ba09a5c0adf..bdbdcf2f094b2 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/rule_api/rules.ts @@ -7,7 +7,7 @@ import { HttpSetup } from '@kbn/core/public'; import { AsApiContract } from '@kbn/actions-plugin/common'; import { INTERNAL_BASE_ALERTING_API_PATH } from '../../constants'; -import { Rule, Pagination, Sorting } from '../../../types'; +import { Rule, Pagination, Sorting, RuleStatus } from '../../../types'; import { mapFiltersToKql } from './map_filters_to_kql'; import { transformRule } from './common_transformations'; @@ -21,6 +21,7 @@ export async function loadRules({ searchText, typesFilter, actionTypesFilter, + ruleExecutionStatusesFilter, ruleStatusesFilter, sort = { field: 'name', direction: 'asc' }, }: { @@ -29,7 +30,8 @@ export async function loadRules({ searchText?: string; typesFilter?: string[]; actionTypesFilter?: string[]; - ruleStatusesFilter?: string[]; + ruleExecutionStatusesFilter?: string[]; + ruleStatusesFilter?: RuleStatus[]; sort?: Sorting; }): Promise<{ page: number; @@ -37,7 +39,12 @@ export async function loadRules({ total: number; data: Rule[]; }> { - const filters = mapFiltersToKql({ typesFilter, actionTypesFilter, ruleStatusesFilter }); + const filters = mapFiltersToKql({ + typesFilter, + actionTypesFilter, + ruleExecutionStatusesFilter, + ruleStatusesFilter, + }); const res = await http.get< AsApiContract<{ page: number; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx index 0e59e3c8ca38f..e41c2a73a5124 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/index.tsx @@ -32,6 +32,9 @@ export const ActionForm = suspendedComponentWithProps( export const RuleStatusDropdown = suspendedComponentWithProps( lazy(() => import('./rules_list/components/rule_status_dropdown')) ); +export const RuleStatusFilter = suspendedComponentWithProps( + lazy(() => import('./rules_list/components/rule_status_filter')) +); export const RuleTagBadge = suspendedComponentWithProps( lazy(() => import('./rules_list/components/rule_tag_badge')) ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx index ad6ef32ab82be..9d62fc2f8e37a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_details/components/rule.tsx @@ -33,7 +33,7 @@ import { withBulkRuleOperations, } from '../../common/components/with_bulk_rule_api_operations'; import './rule.scss'; -import { getHealthColor } from '../../rules_list/components/rule_status_filter'; +import { getHealthColor } from '../../rules_list/components/rule_execution_status_filter'; import { rulesStatusesTranslationsMapping, ALERT_STATUS_LICENSE_ERROR, diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_execution_status_filter.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_execution_status_filter.tsx new file mode 100644 index 0000000000000..9acb8489fa09a --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_execution_status_filter.tsx @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { + EuiFilterGroup, + EuiPopover, + EuiFilterButton, + EuiFilterSelectItem, + EuiHealth, +} from '@elastic/eui'; +import { RuleExecutionStatuses, RuleExecutionStatusValues } from '@kbn/alerting-plugin/common'; +import { rulesStatusesTranslationsMapping } from '../translations'; + +interface RuleExecutionStatusFilterProps { + selectedStatuses: string[]; + onChange?: (selectedRuleStatusesIds: string[]) => void; +} + +export const RuleExecutionStatusFilter: React.FunctionComponent = ({ + selectedStatuses, + onChange, +}: RuleExecutionStatusFilterProps) => { + const [selectedValues, setSelectedValues] = useState(selectedStatuses); + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + + useEffect(() => { + if (onChange) { + onChange(selectedValues); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedValues]); + + useEffect(() => { + setSelectedValues(selectedStatuses); + }, [selectedStatuses]); + + return ( + + setIsPopoverOpen(false)} + button={ + 0} + numActiveFilters={selectedValues.length} + numFilters={selectedValues.length} + onClick={() => setIsPopoverOpen(!isPopoverOpen)} + data-test-subj="ruleExecutionStatusFilterButton" + > + + + } + > +
+ {[...RuleExecutionStatusValues].sort().map((item: RuleExecutionStatuses) => { + const healthColor = getHealthColor(item); + return ( + { + const isPreviouslyChecked = selectedValues.includes(item); + if (isPreviouslyChecked) { + setSelectedValues(selectedValues.filter((val) => val !== item)); + } else { + setSelectedValues(selectedValues.concat(item)); + } + }} + checked={selectedValues.includes(item) ? 'on' : undefined} + data-test-subj={`ruleExecutionStatus${item}FilterOption`} + > + {rulesStatusesTranslationsMapping[item]} + + ); + })} +
+
+
+ ); +}; + +export function getHealthColor(status: RuleExecutionStatuses) { + switch (status) { + case 'active': + return 'success'; + case 'error': + return 'danger'; + case 'ok': + return 'primary'; + case 'pending': + return 'accent'; + case 'warning': + return 'warning'; + default: + return 'subdued'; + } +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.test.tsx new file mode 100644 index 0000000000000..f1f2957f9cada --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { EuiFilterButton, EuiFilterSelectItem } from '@elastic/eui'; +import { RuleStatusFilter } from './rule_status_filter'; + +const onChangeMock = jest.fn(); + +describe('rule_state_filter', () => { + beforeEach(() => { + onChangeMock.mockReset(); + }); + + it('renders correctly', () => { + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find(EuiFilterSelectItem).exists()).toBeFalsy(); + expect(wrapper.find(EuiFilterButton).exists()).toBeTruthy(); + + expect(wrapper.find('.euiNotificationBadge').text()).toEqual('0'); + }); + + it('can open the popover correctly', () => { + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find('[data-test-subj="ruleStateFilterSelect"]').exists()).toBeFalsy(); + + wrapper.find(EuiFilterButton).simulate('click'); + + const statusItems = wrapper.find(EuiFilterSelectItem); + expect(statusItems.length).toEqual(3); + }); + + it('can select statuses', () => { + const wrapper = mountWithIntl( + + ); + + wrapper.find(EuiFilterButton).simulate('click'); + + wrapper.find(EuiFilterSelectItem).at(0).simulate('click'); + expect(onChangeMock).toHaveBeenCalledWith(['enabled']); + + wrapper.setProps({ + selectedStatuses: ['enabled'], + }); + + wrapper.find(EuiFilterSelectItem).at(0).simulate('click'); + expect(onChangeMock).toHaveBeenCalledWith([]); + + wrapper.find(EuiFilterSelectItem).at(1).simulate('click'); + expect(onChangeMock).toHaveBeenCalledWith(['enabled', 'disabled']); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.tsx index cbb1a7f5455da..6d286ec6d09d7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rule_status_filter.tsx @@ -4,82 +4,87 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import React, { useEffect, useState } from 'react'; +import React, { useState, useCallback } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiFilterGroup, - EuiPopover, - EuiFilterButton, - EuiFilterSelectItem, - EuiHealth, -} from '@elastic/eui'; -import { RuleExecutionStatuses, RuleExecutionStatusValues } from '@kbn/alerting-plugin/common'; -import { rulesStatusesTranslationsMapping } from '../translations'; +import { EuiFilterButton, EuiPopover, EuiFilterGroup, EuiFilterSelectItem } from '@elastic/eui'; +import { RuleStatus } from '../../../../types'; + +const statuses: RuleStatus[] = ['enabled', 'disabled', 'snoozed']; + +const optionStyles = { + textTransform: 'capitalize' as const, +}; -interface RuleStatusFilterProps { - selectedStatuses: string[]; - onChange?: (selectedRuleStatusesIds: string[]) => void; +const getOptionDataTestSubj = (status: RuleStatus) => `ruleStatusFilterOption-${status}`; + +export interface RuleStatusFilterProps { + selectedStatuses: RuleStatus[]; + dataTestSubj?: string; + selectDataTestSubj?: string; + buttonDataTestSubj?: string; + optionDataTestSubj?: (status: RuleStatus) => string; + onChange: (selectedStatuses: RuleStatus[]) => void; } -export const RuleStatusFilter: React.FunctionComponent = ({ - selectedStatuses, - onChange, -}: RuleStatusFilterProps) => { - const [selectedValues, setSelectedValues] = useState(selectedStatuses); +export const RuleStatusFilter = (props: RuleStatusFilterProps) => { + const { + selectedStatuses = [], + dataTestSubj = 'ruleStatusFilter', + selectDataTestSubj = 'ruleStatusFilterSelect', + buttonDataTestSubj = 'ruleStatusFilterButton', + optionDataTestSubj = getOptionDataTestSubj, + onChange = () => {}, + } = props; + const [isPopoverOpen, setIsPopoverOpen] = useState(false); - useEffect(() => { - if (onChange) { - onChange(selectedValues); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [selectedValues]); + const onFilterItemClick = useCallback( + (newOption: RuleStatus) => () => { + if (selectedStatuses.includes(newOption)) { + onChange(selectedStatuses.filter((option) => option !== newOption)); + return; + } + onChange([...selectedStatuses, newOption]); + }, + [selectedStatuses, onChange] + ); - useEffect(() => { - setSelectedValues(selectedStatuses); - }, [selectedStatuses]); + const onClick = useCallback(() => { + setIsPopoverOpen((prevIsOpen) => !prevIsOpen); + }, [setIsPopoverOpen]); return ( - + setIsPopoverOpen(false)} button={ 0} - numActiveFilters={selectedValues.length} - numFilters={selectedValues.length} - onClick={() => setIsPopoverOpen(!isPopoverOpen)} - data-test-subj="ruleStatusFilterButton" + hasActiveFilters={selectedStatuses.length > 0} + numActiveFilters={selectedStatuses.length} + numFilters={selectedStatuses.length} + onClick={onClick} > } > -
- {[...RuleExecutionStatusValues].sort().map((item: RuleExecutionStatuses) => { - const healthColor = getHealthColor(item); +
+ {statuses.map((status) => { return ( { - const isPreviouslyChecked = selectedValues.includes(item); - if (isPreviouslyChecked) { - setSelectedValues(selectedValues.filter((val) => val !== item)); - } else { - setSelectedValues(selectedValues.concat(item)); - } - }} - checked={selectedValues.includes(item) ? 'on' : undefined} - data-test-subj={`ruleStatus${item}FilerOption`} + key={status} + style={optionStyles} + data-test-subj={optionDataTestSubj(status)} + onClick={onFilterItemClick(status)} + checked={selectedStatuses.includes(status) ? 'on' : undefined} > - {rulesStatusesTranslationsMapping[item]} + {status} ); })} @@ -89,19 +94,5 @@ export const RuleStatusFilter: React.FunctionComponent = ); }; -export function getHealthColor(status: RuleExecutionStatuses) { - switch (status) { - case 'active': - return 'success'; - case 'error': - return 'danger'; - case 'ok': - return 'primary'; - case 'pending': - return 'accent'; - case 'warning': - return 'warning'; - default: - return 'subdued'; - } -} +// eslint-disable-next-line import/no-default-export +export { RuleStatusFilter as default }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx index 727898d42a076..52c6e2d3ed149 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.test.tsx @@ -20,6 +20,7 @@ import { parseDuration, } from '@kbn/alerting-plugin/common'; import { getFormattedDuration, getFormattedMilliseconds } from '../../../lib/monitoring_utils'; +import { getIsExperimentalFeatureEnabled } from '../../../../common/get_experimental_features'; import { useKibana } from '../../../../common/lib/kibana'; jest.mock('../../../../common/lib/kibana'); @@ -59,6 +60,9 @@ jest.mock('../../../lib/capabilities', () => ({ hasShowActionsCapability: jest.fn(() => true), hasExecuteActionsCapability: jest.fn(() => true), })); +jest.mock('../../../../common/get_experimental_features', () => ({ + getIsExperimentalFeatureEnabled: jest.fn(), +})); const { loadRules, loadRuleTypes, loadRuleAggregations } = jest.requireMock('../../../lib/rule_api'); const { loadActionTypes, loadAllActions } = jest.requireMock('../../../lib/action_connector_api'); @@ -95,6 +99,10 @@ ruleTypeRegistry.list.mockReturnValue([ruleType]); actionTypeRegistry.list.mockReturnValue([]); const useKibanaMock = useKibana as jest.Mocked; +beforeEach(() => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => false); +}); + describe('rules_list component empty', () => { let wrapper: ReactWrapper; async function setup() { @@ -801,6 +809,39 @@ describe('rules_list component with items', () => { 'Warning: 6' ); }); + + it('does not render the status filter if the feature flag is off', async () => { + await setup(); + expect(wrapper.find('[data-test-subj="ruleStatusFilter"]').exists()).toBeFalsy(); + }); + + it('renders the status filter if the experiment is on', async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + await setup(); + expect(wrapper.find('[data-test-subj="ruleStatusFilter"]').exists()).toBeTruthy(); + }); + + it('can filter by rule states', async () => { + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation(() => true); + loadRules.mockReset(); + await setup(); + + expect(loadRules.mock.calls[0][0].ruleStatusesFilter).toEqual([]); + + wrapper.find('[data-test-subj="ruleStatusFilterButton"] button').simulate('click'); + + wrapper.find('[data-test-subj="ruleStatusFilterOption-enabled"]').first().simulate('click'); + + expect(loadRules.mock.calls[1][0].ruleStatusesFilter).toEqual(['enabled']); + + wrapper.find('[data-test-subj="ruleStatusFilterOption-snoozed"]').first().simulate('click'); + + expect(loadRules.mock.calls[2][0].ruleStatusesFilter).toEqual(['enabled', 'snoozed']); + + wrapper.find('[data-test-subj="ruleStatusFilterOption-snoozed"]').first().simulate('click'); + + expect(loadRules.mock.calls[3][0].ruleStatusesFilter).toEqual(['enabled']); + }); }); describe('rules_list component empty with show only capability', () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx index 57c59f3f09782..b1255600b68de 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/rules_list.tsx @@ -58,6 +58,7 @@ import { RuleTableItem, RuleType, RuleTypeIndex, + RuleStatus, Pagination, Percentiles, TriggersActionsUiConfig, @@ -68,7 +69,7 @@ import { RuleQuickEditButtonsWithApi as RuleQuickEditButtons } from '../../commo import { CollapsedItemActionsWithApi as CollapsedItemActions } from './collapsed_item_actions'; import { TypeFilter } from './type_filter'; import { ActionTypeFilter } from './action_type_filter'; -import { RuleStatusFilter, getHealthColor } from './rule_status_filter'; +import { RuleExecutionStatusFilter, getHealthColor } from './rule_execution_status_filter'; import { loadRules, loadRuleAggregations, @@ -98,6 +99,8 @@ import { RuleDurationFormat } from './rule_duration_format'; import { shouldShowDurationWarning } from '../../../lib/execution_duration_utils'; import { getFormattedSuccessRatio } from '../../../lib/monitoring_utils'; import { triggersActionsUiConfig } from '../../../../common/lib/config_api'; +import { RuleStatusFilter } from './rule_status_filter'; +import { getIsExperimentalFeatureEnabled } from '../../../../common/get_experimental_features'; const ENTER_KEY = 13; @@ -153,7 +156,8 @@ export const RulesList: React.FunctionComponent = () => { const [inputText, setInputText] = useState(); const [typesFilter, setTypesFilter] = useState([]); const [actionTypesFilter, setActionTypesFilter] = useState([]); - const [ruleStatusesFilter, setRuleStatusesFilter] = useState([]); + const [ruleExecutionStatusesFilter, setRuleExecutionStatusesFilter] = useState([]); + const [ruleStatusesFilter, setRuleStatusesFilter] = useState([]); const [ruleFlyoutVisible, setRuleFlyoutVisibility] = useState(false); const [editFlyoutVisible, setEditFlyoutVisibility] = useState(false); const [currentRuleToEdit, setCurrentRuleToEdit] = useState(null); @@ -163,6 +167,8 @@ export const RulesList: React.FunctionComponent = () => { ); const [showErrors, setShowErrors] = useState(false); + const isRuleStatusFilterEnabled = getIsExperimentalFeatureEnabled('ruleStatusFilter'); + useEffect(() => { (async () => { setConfig(await triggersActionsUiConfig({ http })); @@ -225,6 +231,7 @@ export const RulesList: React.FunctionComponent = () => { percentileOptions, JSON.stringify(typesFilter), JSON.stringify(actionTypesFilter), + JSON.stringify(ruleExecutionStatusesFilter), JSON.stringify(ruleStatusesFilter), ]); @@ -284,6 +291,7 @@ export const RulesList: React.FunctionComponent = () => { searchText, typesFilter, actionTypesFilter, + ruleExecutionStatusesFilter, ruleStatusesFilter, sort, }); @@ -302,6 +310,7 @@ export const RulesList: React.FunctionComponent = () => { isEmpty(searchText) && isEmpty(typesFilter) && isEmpty(actionTypesFilter) && + isEmpty(ruleExecutionStatusesFilter) && isEmpty(ruleStatusesFilter) ); @@ -328,6 +337,7 @@ export const RulesList: React.FunctionComponent = () => { searchText, typesFilter, actionTypesFilter, + ruleExecutionStatusesFilter, ruleStatusesFilter, }); if (rulesAggs?.ruleExecutionStatus) { @@ -930,6 +940,15 @@ export const RulesList: React.FunctionComponent = () => { ); }; + const getRuleStatusFilter = () => { + if (isRuleStatusFilterEnabled) { + return [ + , + ]; + } + return []; + }; + const toolsRight = [ { }) )} />, + ...getRuleStatusFilter(), setActionTypesFilter(ids)} />, - setRuleStatusesFilter(ids)} + selectedStatuses={ruleExecutionStatusesFilter} + onChange={(ids: string[]) => setRuleExecutionStatusesFilter(ids)} />, { }} />   - setRuleStatusesFilter(['error'])}> + setRuleExecutionStatusesFilter(['error'])}> { rulesListDatagrid: true, internalAlertsTable: true, rulesDetailLogs: true, + ruleStatusFilter: true, internalShareableComponentsSandbox: true, }, }); @@ -38,6 +39,10 @@ describe('getIsExperimentalFeatureEnabled', () => { expect(result).toEqual(true); + result = getIsExperimentalFeatureEnabled('ruleStatusFilter'); + + expect(result).toEqual(true); + expect(() => getIsExperimentalFeatureEnabled('doesNotExist' as any)).toThrowError( `Invalid enable value doesNotExist. Allowed values are: ${allowedExperimentalValueKeys.join( ', ' diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_rule_status_filter.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_rule_status_filter.tsx new file mode 100644 index 0000000000000..77ac3fc51d703 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_rule_status_filter.tsx @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { RuleStatusFilter } from '../application/sections'; +import type { RuleStatusFilterProps } from '../application/sections/rules_list/components/rule_status_filter'; + +export const getRuleStatusFilterLazy = (props: RuleStatusFilterProps) => { + return ; +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/common/types.ts b/x-pack/plugins/triggers_actions_ui/public/common/types.ts index 4aca07ad5482e..610962706661a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/common/types.ts @@ -24,3 +24,5 @@ export interface GroupByType { value: string; validNormalizedTypes: string[]; } + +export type { RuleStatus } from '../types'; diff --git a/x-pack/plugins/triggers_actions_ui/public/mocks.ts b/x-pack/plugins/triggers_actions_ui/public/mocks.ts index 959d959ef855a..cb79a1509a6c1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/mocks.ts +++ b/x-pack/plugins/triggers_actions_ui/public/mocks.ts @@ -26,6 +26,7 @@ import { } from './types'; import { getAlertsTableLazy } from './common/get_alerts_table'; import { getRuleStatusDropdownLazy } from './common/get_rule_status_dropdown'; +import { getRuleStatusFilterLazy } from './common/get_rule_status_filter'; import { getRuleTagBadgeLazy } from './common/get_rule_tag_badge'; function createStartMock(): TriggersAndActionsUIPublicPluginStart { @@ -65,6 +66,9 @@ function createStartMock(): TriggersAndActionsUIPublicPluginStart { getRuleStatusDropdown: (props) => { return getRuleStatusDropdownLazy(props); }, + getRuleStatusFilter: (props) => { + return getRuleStatusFilterLazy(props); + }, getRuleTagBadge: (props) => { return getRuleTagBadgeLazy(props); }, diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index e2c3be96271b9..1d9c3c07e44ca 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -31,6 +31,7 @@ import { getAddAlertFlyoutLazy } from './common/get_add_alert_flyout'; import { getEditAlertFlyoutLazy } from './common/get_edit_alert_flyout'; import { getAlertsTableLazy } from './common/get_alerts_table'; import { getRuleStatusDropdownLazy } from './common/get_rule_status_dropdown'; +import { getRuleStatusFilterLazy } from './common/get_rule_status_filter'; import { getRuleTagBadgeLazy } from './common/get_rule_tag_badge'; import { ExperimentalFeaturesService } from './common/experimental_features_service'; import { @@ -47,6 +48,7 @@ import type { ConnectorEditFlyoutProps, AlertsTableProps, RuleStatusDropdownProps, + RuleStatusFilterProps, RuleTagBadgeProps, AlertsTableConfigurationRegistry, } from './types'; @@ -78,6 +80,7 @@ export interface TriggersAndActionsUIPublicPluginStart { ) => ReactElement; getAlertsTable: (props: AlertsTableProps) => ReactElement; getRuleStatusDropdown: (props: RuleStatusDropdownProps) => ReactElement; + getRuleStatusFilter: (props: RuleStatusFilterProps) => ReactElement; getRuleTagBadge: (props: RuleTagBadgeProps) => ReactElement; } @@ -252,6 +255,9 @@ export class Plugin getRuleStatusDropdown: (props: RuleStatusDropdownProps) => { return getRuleStatusDropdownLazy(props); }, + getRuleStatusFilter: (props: RuleStatusFilterProps) => { + return getRuleStatusFilterLazy(props); + }, getRuleTagBadge: (props: RuleTagBadgeProps) => { return getRuleTagBadgeLazy(props); }, diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index c59692ebad271..25efbfb6ecc38 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -48,7 +48,8 @@ import { import { RuleRegistrySearchRequestPagination } from '@kbn/rule-registry-plugin/common'; import { TypeRegistry } from './application/type_registry'; import type { ComponentOpts as RuleStatusDropdownProps } from './application/sections/rules_list/components/rule_status_dropdown'; -import { RuleTagBadgeProps } from './application/sections/rules_list/components/rule_tag_badge'; +import type { RuleStatusFilterProps } from './application/sections/rules_list/components/rule_status_filter'; +import type { RuleTagBadgeProps } from './application/sections/rules_list/components/rule_tag_badge'; // In Triggers and Actions we treat all `Alert`s as `SanitizedRule` // so the `Params` is a black-box of Record @@ -81,6 +82,7 @@ export type { ResolvedRule, SanitizedRule, RuleStatusDropdownProps, + RuleStatusFilterProps, RuleTagBadgeProps, }; export type { ActionType, AsApiContract }; @@ -429,3 +431,5 @@ export interface AlertsTableConfigurationRegistry { id: string; columns: EuiDataGridColumn[]; } + +export type RuleStatus = 'enabled' | 'disabled' | 'snoozed'; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts index 581edecc3d8bc..49a3fada3dbef 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts @@ -14,6 +14,7 @@ import { createFailingAlert, disableAlert, muteAlert, + snoozeAlert, } from '../../lib/alert_api_actions'; import { ObjectRemover } from '../../lib/object_remover'; import { generateUniqueKey } from '../../lib/get_test_data'; @@ -462,8 +463,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const refreshResults = await pageObjects.triggersActionsUI.getAlertsListWithStatus(); expect(refreshResults.map((item: any) => item.status).sort()).to.eql(['Error', 'Ok']); }); - await testSubjects.click('ruleStatusFilterButton'); - await testSubjects.click('ruleStatuserrorFilerOption'); // select Error status filter + await testSubjects.click('ruleExecutionStatusFilterButton'); + await testSubjects.click('ruleExecutionStatuserrorFilterOption'); // select Error status filter await retry.try(async () => { const filterErrorOnlyResults = await pageObjects.triggersActionsUI.getAlertsListWithStatus(); @@ -600,5 +601,63 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.missingOrFail('centerJustifiedSpinner'); }); + + it('should filter alerts by the rule status', async () => { + const assertRulesLength = async (length: number) => { + return await retry.try(async () => { + const rules = await pageObjects.triggersActionsUI.getAlertsList(); + expect(rules.length).to.equal(length); + }); + }; + + // Enabled alert + await createAlert({ + supertest, + objectRemover, + }); + const disabledAlert = await createAlert({ + supertest, + objectRemover, + }); + const snoozedAlert = await createAlert({ + supertest, + objectRemover, + }); + + await disableAlert({ + supertest, + alertId: disabledAlert.id, + }); + await snoozeAlert({ + supertest, + alertId: snoozedAlert.id, + }); + + await refreshAlertsList(); + await assertRulesLength(3); + + // Select enabled + await testSubjects.click('ruleStatusFilterButton'); + await testSubjects.click('ruleStatusFilterOption-enabled'); + await assertRulesLength(1); + + // Select disabled + await testSubjects.click('ruleStatusFilterOption-enabled'); + await testSubjects.click('ruleStatusFilterOption-disabled'); + await assertRulesLength(1); + + // Select snoozed + await testSubjects.click('ruleStatusFilterOption-disabled'); + await testSubjects.click('ruleStatusFilterOption-snoozed'); + await assertRulesLength(1); + + // Select disabled and snoozed + await testSubjects.click('ruleStatusFilterOption-disabled'); + await assertRulesLength(2); + + // Select all 3 + await testSubjects.click('ruleStatusFilterOption-enabled'); + await assertRulesLength(3); + }); }); }; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts index 270232d1aa0fd..9c57f29c6f707 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts @@ -17,6 +17,7 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => { loadTestFile(require.resolve('./connectors')); loadTestFile(require.resolve('./alerts_table')); loadTestFile(require.resolve('./rule_status_dropdown')); + loadTestFile(require.resolve('./rule_status_filter')); loadTestFile(require.resolve('./rule_tag_badge')); }); }; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rule_status_filter.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rule_status_filter.ts new file mode 100644 index 0000000000000..0afdc932b0289 --- /dev/null +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rule_status_filter.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']); + const esArchiver = getService('esArchiver'); + + describe('Rule status filter', () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); + await PageObjects.common.navigateToUrlWithBrowserHistory( + 'triggersActions', + '/__components_sandbox' + ); + }); + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); + }); + + it('should load from the shareable lazy loader', async () => { + await testSubjects.find('ruleStatusFilter'); + const exists = await testSubjects.exists('ruleStatusFilter'); + expect(exists).to.be(true); + }); + + it('should allow rule statuses to be filtered', async () => { + const ruleStatusFilter = await testSubjects.find('ruleStatusFilter'); + let badge = await ruleStatusFilter.findByCssSelector('.euiFilterButton__notification'); + expect(await badge.getVisibleText()).to.be('0'); + + await testSubjects.click('ruleStatusFilter'); + await testSubjects.click('ruleStatusFilterOption-enabled'); + + badge = await ruleStatusFilter.findByCssSelector('.euiFilterButton__notification'); + expect(await badge.getVisibleText()).to.be('1'); + + await testSubjects.click('ruleStatusFilterOption-disabled'); + + badge = await ruleStatusFilter.findByCssSelector('.euiFilterButton__notification'); + expect(await badge.getVisibleText()).to.be('2'); + + await testSubjects.click('ruleStatusFilterOption-enabled'); + expect(await badge.getVisibleText()).to.be('1'); + }); + }); +}; diff --git a/x-pack/test/functional_with_es_ssl/config.ts b/x-pack/test/functional_with_es_ssl/config.ts index 5243b97898578..4783ad683c0cf 100644 --- a/x-pack/test/functional_with_es_ssl/config.ts +++ b/x-pack/test/functional_with_es_ssl/config.ts @@ -74,6 +74,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { `--xpack.trigger_actions_ui.enableExperimental=${JSON.stringify([ 'internalAlertsTable', 'internalShareableComponentsSandbox', + 'ruleStatusFilter', ])}`, `--xpack.alerting.rules.minimumScheduleInterval.value="2s"`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, diff --git a/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts b/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts index 40e567c299826..ab15d4b2ec3f4 100644 --- a/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts +++ b/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts @@ -8,6 +8,8 @@ import type { ObjectRemover } from './object_remover'; import { getTestAlertData, getTestActionData } from './get_test_data'; +const FUTURE_SNOOZE_TIME = '9999-12-31T06:00:00.000Z'; + export async function createAlertManualCleanup({ supertest, overwrites = {}, @@ -85,3 +87,14 @@ export async function disableAlert({ supertest, alertId }: { supertest: any; ale .set('kbn-xsrf', 'foo'); return alert; } + +export async function snoozeAlert({ supertest, alertId }: { supertest: any; alertId: string }) { + const { body: alert } = await supertest + .post(`/internal/alerting/rule/${alertId}/_snooze`) + .set('kbn-xsrf', 'foo') + .set('content-type', 'application/json') + .send({ + snooze_end_time: FUTURE_SNOOZE_TIME, + }); + return alert; +} From 01e12ec1d6e6abfa91f027ce959525beb4e161e7 Mon Sep 17 00:00:00 2001 From: Clint Andrew Hall Date: Tue, 3 May 2022 18:24:22 -0500 Subject: [PATCH 05/68] [storybook] Watch for changes in packages (#131467) * [storybook] Watch for changes in packages * Update default_config.ts --- packages/kbn-storybook/src/lib/default_config.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/kbn-storybook/src/lib/default_config.ts b/packages/kbn-storybook/src/lib/default_config.ts index 3caf879c48cbb..0f0b8070ff8b0 100644 --- a/packages/kbn-storybook/src/lib/default_config.ts +++ b/packages/kbn-storybook/src/lib/default_config.ts @@ -14,6 +14,12 @@ import { REPO_ROOT } from './constants'; import { default as WebpackConfig } from '../webpack.config'; const toPath = (_path: string) => path.join(REPO_ROOT, _path); + +// This ignore pattern excludes all of node_modules EXCEPT for `@kbn`. This allows for +// changes to packages to cause a refresh in Storybook. +const IGNORE_PATTERN = + /[/\\]node_modules[/\\](?!@kbn[/\\][^/\\]+[/\\](?!node_modules)([^/\\]+))([^/\\]+[/\\][^/\\]+)/; + export const defaultConfig: StorybookConfig = { addons: ['@kbn/storybook/preset', '@storybook/addon-a11y', '@storybook/addon-essentials'], stories: ['../**/*.stories.tsx', '../**/*.stories.mdx'], @@ -45,6 +51,11 @@ export const defaultConfig: StorybookConfig = { } config.node = { fs: 'empty' }; + config.watch = true; + config.watchOptions = { + ...config.watchOptions, + ignored: [IGNORE_PATTERN], + }; // Remove when @storybook has moved to @emotion v11 // https://github.com/storybookjs/storybook/issues/13145 From 4b19c72dde5350cc4cd6f868dc12886e3b5b6ea1 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Tue, 3 May 2022 18:03:48 -0700 Subject: [PATCH 06/68] Improve saved objects migrations failure errors and logs (#131359) --- .../resolving-migration-failures.asciidoc | 2 +- packages/kbn-doc-links/src/get_doc_links.ts | 2 + packages/kbn-doc-links/src/types.ts | 2 + ...grations_state_action_machine.test.ts.snap | 12 + .../migrations/actions/initialize_action.ts | 7 +- .../actions/integration_tests/actions.test.ts | 279 +++++++++--------- .../migrations/initial_state.test.ts | 4 + ...luster_routing_allocation_disabled.test.ts | 6 +- .../migrations/model/extract_errors.test.ts | 35 ++- .../migrations/model/extract_errors.ts | 29 ++ .../migrations/model/model.test.ts | 5 +- .../saved_objects/migrations/model/model.ts | 37 ++- .../server/saved_objects/migrations/state.ts | 3 +- 13 files changed, 258 insertions(+), 165 deletions(-) diff --git a/docs/setup/upgrade/resolving-migration-failures.asciidoc b/docs/setup/upgrade/resolving-migration-failures.asciidoc index 3cbfb4c9c2abe..f90a9f541f3eb 100644 --- a/docs/setup/upgrade/resolving-migration-failures.asciidoc +++ b/docs/setup/upgrade/resolving-migration-failures.asciidoc @@ -171,7 +171,7 @@ Upgrade migrations fail because routing allocation is disabled or restricted (`c [source,sh] -------------------------------------------- -Unable to complete saved object migrations for the [.kibana] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue. To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {"transient": {"cluster.routing.allocation.enable": null}, "persistent": {"cluster.routing.allocation.enable": null}} +Unable to complete saved object migrations for the [.kibana] index: [unsupported_cluster_routing_allocation] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue. To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {"transient": {"cluster.routing.allocation.enable": null}, "persistent": {"cluster.routing.allocation.enable": null}} -------------------------------------------- To get around the issue, remove the transient and persisted routing allocation settings: diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 74549f4e32b57..14fd80c3a8552 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -648,6 +648,8 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { }, kibanaUpgradeSavedObjects: { resolveMigrationFailures: `${KIBANA_DOCS}resolve-migrations-failures.html`, + repeatedTimeoutRequests: `${KIBANA_DOCS}resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail`, + routingAllocationDisabled: `${KIBANA_DOCS}resolve-migrations-failures.html#routing-allocation-disabled`, }, }); }; diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index bf378c4cf2dd1..4a5a9fdeb9576 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -403,5 +403,7 @@ export interface DocLinks { }; readonly kibanaUpgradeSavedObjects: { readonly resolveMigrationFailures: string; + readonly repeatedTimeoutRequests: string; + readonly routingAllocationDisabled: string; }; } diff --git a/src/core/server/saved_objects/migrations/__snapshots__/migrations_state_action_machine.test.ts.snap b/src/core/server/saved_objects/migrations/__snapshots__/migrations_state_action_machine.test.ts.snap index b1dcd51bbdd0d..d26021d28b0e5 100644 --- a/src/core/server/saved_objects/migrations/__snapshots__/migrations_state_action_machine.test.ts.snap +++ b/src/core/server/saved_objects/migrations/__snapshots__/migrations_state_action_machine.test.ts.snap @@ -33,7 +33,9 @@ Object { ], "maxBatchSizeBytes": 100000000, "migrationDocLinks": Object { + "repeatedTimeoutRequests": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail", "resolveMigrationFailures": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html", + "routingAllocationDisabled": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#routing-allocation-disabled", }, "outdatedDocuments": Array [], "outdatedDocumentsQuery": Object { @@ -197,7 +199,9 @@ Object { ], "maxBatchSizeBytes": 100000000, "migrationDocLinks": Object { + "repeatedTimeoutRequests": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail", "resolveMigrationFailures": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html", + "routingAllocationDisabled": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#routing-allocation-disabled", }, "outdatedDocuments": Array [], "outdatedDocumentsQuery": Object { @@ -365,7 +369,9 @@ Object { ], "maxBatchSizeBytes": 100000000, "migrationDocLinks": Object { + "repeatedTimeoutRequests": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail", "resolveMigrationFailures": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html", + "routingAllocationDisabled": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#routing-allocation-disabled", }, "outdatedDocuments": Array [], "outdatedDocumentsQuery": Object { @@ -537,7 +543,9 @@ Object { ], "maxBatchSizeBytes": 100000000, "migrationDocLinks": Object { + "repeatedTimeoutRequests": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail", "resolveMigrationFailures": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html", + "routingAllocationDisabled": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#routing-allocation-disabled", }, "outdatedDocuments": Array [], "outdatedDocumentsQuery": Object { @@ -735,7 +743,9 @@ Object { ], "maxBatchSizeBytes": 100000000, "migrationDocLinks": Object { + "repeatedTimeoutRequests": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail", "resolveMigrationFailures": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html", + "routingAllocationDisabled": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#routing-allocation-disabled", }, "outdatedDocuments": Array [ Object { @@ -910,7 +920,9 @@ Object { ], "maxBatchSizeBytes": 100000000, "migrationDocLinks": Object { + "repeatedTimeoutRequests": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail", "resolveMigrationFailures": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html", + "routingAllocationDisabled": "https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#routing-allocation-disabled", }, "outdatedDocuments": Array [ Object { diff --git a/src/core/server/saved_objects/migrations/actions/initialize_action.ts b/src/core/server/saved_objects/migrations/actions/initialize_action.ts index 73502382c9ca0..281e3a0a4f3e0 100644 --- a/src/core/server/saved_objects/migrations/actions/initialize_action.ts +++ b/src/core/server/saved_objects/migrations/actions/initialize_action.ts @@ -29,6 +29,7 @@ export interface InitActionParams { export interface UnsupportedClusterRoutingAllocation { type: 'unsupported_cluster_routing_allocation'; + message: string; } export const checkClusterRoutingAllocationEnabledTask = @@ -53,7 +54,11 @@ export const checkClusterRoutingAllocationEnabledTask = [...clusterRoutingAllocations].every((s: string) => s === 'all'); // if set, only allow 'all' if (!clusterRoutingAllocationEnabled) { - return Either.left({ type: 'unsupported_cluster_routing_allocation' as const }); + return Either.left({ + type: 'unsupported_cluster_routing_allocation' as const, + message: + '[unsupported_cluster_routing_allocation] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue.', + }); } else { return Either.right({}); } diff --git a/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts b/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts index 5e840d87ea1ab..9846e5f48dc21 100644 --- a/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts +++ b/src/core/server/saved_objects/migrations/actions/integration_tests/actions.test.ts @@ -167,6 +167,7 @@ describe('migration actions', () => { Object { "_tag": "Left", "left": Object { + "message": "[unsupported_cluster_routing_allocation] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue.", "type": "unsupported_cluster_routing_allocation", }, } @@ -187,6 +188,7 @@ describe('migration actions', () => { Object { "_tag": "Left", "left": Object { + "message": "[unsupported_cluster_routing_allocation] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue.", "type": "unsupported_cluster_routing_allocation", }, } @@ -207,6 +209,7 @@ describe('migration actions', () => { Object { "_tag": "Left", "left": Object { + "message": "[unsupported_cluster_routing_allocation] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue.", "type": "unsupported_cluster_routing_allocation", }, } @@ -395,14 +398,14 @@ describe('migration actions', () => { timeout: '1s', }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "message": "[index_not_yellow_timeout] Timeout waiting for the status of the [red_index] index to become 'yellow'", - "type": "index_not_yellow_timeout", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "message": "[index_not_yellow_timeout] Timeout waiting for the status of the [red_index] index to become 'yellow'", + "type": "index_not_yellow_timeout", + }, + } + `); }); }); @@ -422,14 +425,14 @@ describe('migration actions', () => { }); expect.assertions(1); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": Object { - "acknowledged": true, - "shardsAcknowledged": true, - }, - } - `); + Object { + "_tag": "Right", + "right": Object { + "acknowledged": true, + "shardsAcknowledged": true, + }, + } + `); }); it('resolves right after waiting for index status to be yellow if clone target already existed', async () => { expect.assertions(2); @@ -488,14 +491,14 @@ describe('migration actions', () => { expect.assertions(1); const task = cloneIndex({ client, source: 'no_such_index', target: 'clone_target_3' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "index": "no_such_index", - "type": "index_not_found_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "index": "no_such_index", + "type": "index_not_found_exception", + }, + } + `); }); it('resolves left with a index_not_yellow_timeout if clone target already exists but takes longer than the specified timeout before turning yellow', async () => { // Create a red index @@ -524,14 +527,14 @@ describe('migration actions', () => { })(); await expect(cloneIndexPromise).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "message": "[index_not_yellow_timeout] Timeout waiting for the status of the [clone_red_index] index to become 'yellow'", - "type": "index_not_yellow_timeout", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "message": "[index_not_yellow_timeout] Timeout waiting for the status of the [clone_red_index] index to become 'yellow'", + "type": "index_not_yellow_timeout", + }, + } + `); // Now that we know timeouts work, make the index yellow again and call cloneIndex a second time to verify that it completes @@ -552,14 +555,14 @@ describe('migration actions', () => { })(); await expect(cloneIndexPromise2).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": Object { - "acknowledged": true, - "shardsAcknowledged": true, - }, - } - `); + Object { + "_tag": "Right", + "right": Object { + "acknowledged": true, + "shardsAcknowledged": true, + }, + } + `); }); }); @@ -577,11 +580,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); const results = ( (await searchForOutdatedDocuments(client, { @@ -617,11 +620,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); const results = ( (await searchForOutdatedDocuments(client, { @@ -650,11 +653,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); const results = ( (await searchForOutdatedDocuments(client, { batchSize: 1000, @@ -685,11 +688,11 @@ describe('migration actions', () => { })()) as Either.Right; let task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); // reindex without a script res = (await reindex({ @@ -702,11 +705,11 @@ describe('migration actions', () => { })()) as Either.Right; task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); // Assert that documents weren't overridden by the second, unscripted reindex const results = ( @@ -761,11 +764,11 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "reindex_succeeded", + } + `); // Assert that existing documents weren't overridden, but that missing // documents were added by the reindex const results = ( @@ -818,13 +821,13 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: reindexTaskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "incompatible_mapping_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "incompatible_mapping_exception", + }, + } + `); }); it('resolves left incompatible_mapping_exception if all reindex failures are due to a mapper_parsing_exception', async () => { expect.assertions(1); @@ -857,13 +860,13 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: reindexTaskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "incompatible_mapping_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "incompatible_mapping_exception", + }, + } + `); }); it('resolves left index_not_found_exception if source index does not exist', async () => { expect.assertions(1); @@ -879,14 +882,14 @@ describe('migration actions', () => { })()) as Either.Right; const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "index": "no_such_index", - "type": "index_not_found_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "index": "no_such_index", + "type": "index_not_found_exception", + }, + } + `); }); it('resolves left target_index_had_write_block if all failures are due to a write block', async () => { expect.assertions(1); @@ -902,13 +905,13 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "target_index_had_write_block", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "target_index_had_write_block", + }, + } + `); }); it('resolves left if requireAlias=true and the target is not an alias', async () => { expect.assertions(1); @@ -924,14 +927,14 @@ describe('migration actions', () => { const task = waitForReindexTask({ client, taskId: res.right.taskId, timeout: '10s' }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "index": "existing_index_with_write_block", - "type": "index_not_found_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "index": "existing_index_with_write_block", + "type": "index_not_found_exception", + }, + } + `); }); it('resolves left wait_for_task_completion_timeout when the task does not finish within the timeout', async () => { @@ -983,11 +986,11 @@ describe('migration actions', () => { targetIndex: 'reindex_target_7', }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "verify_reindex_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "verify_reindex_succeeded", + } + `); }); it('resolves left if source and target indices have different amount of documents', async () => { expect.assertions(1); @@ -997,13 +1000,13 @@ describe('migration actions', () => { targetIndex: 'existing_index_2', }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "verify_reindex_failed", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "verify_reindex_failed", + }, + } + `); }); it('rejects if source or target index does not exist', async () => { expect.assertions(2); @@ -1630,11 +1633,11 @@ describe('migration actions', () => { }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Right", - "right": "bulk_index_succeeded", - } - `); + Object { + "_tag": "Right", + "right": "bulk_index_succeeded", + } + `); }); it('resolves right even if there were some version_conflict_engine_exception', async () => { const existingDocs = ( @@ -1675,13 +1678,13 @@ describe('migration actions', () => { refresh: 'wait_for', })() ).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "target_index_had_write_block", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "target_index_had_write_block", + }, + } + `); }); it('resolves left request_entity_too_large_exception when the payload is too large', async () => { @@ -1697,13 +1700,13 @@ describe('migration actions', () => { transformedDocs: newDocs, }); await expect(task()).resolves.toMatchInlineSnapshot(` - Object { - "_tag": "Left", - "left": Object { - "type": "request_entity_too_large_exception", - }, - } - `); + Object { + "_tag": "Left", + "left": Object { + "type": "request_entity_too_large_exception", + }, + } + `); }); }); }); diff --git a/src/core/server/saved_objects/migrations/initial_state.test.ts b/src/core/server/saved_objects/migrations/initial_state.test.ts index 0fff4ddb06895..2ad3dc38e6d65 100644 --- a/src/core/server/saved_objects/migrations/initial_state.test.ts +++ b/src/core/server/saved_objects/migrations/initial_state.test.ts @@ -116,6 +116,10 @@ describe('createInitialState', () => { migrationDocLinks: { resolveMigrationFailures: 'https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html', + repeatedTimeoutRequests: + 'https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#_repeated_time_out_requests_that_eventually_fail', + routingAllocationDisabled: + 'https://www.elastic.co/guide/en/kibana/test-branch/resolve-migrations-failures.html#routing-allocation-disabled', }, }); }); diff --git a/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts b/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts index ea70478d6ce7b..37b278fe9ccf0 100644 --- a/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts +++ b/src/core/server/saved_objects/migrations/integration_tests/cluster_routing_allocation_disabled.test.ts @@ -114,7 +114,7 @@ describe('unsupported_cluster_routing_allocation', () => { await root.setup(); await expect(root.start()).rejects.toThrowError( - /Unable to complete saved object migrations for the \[\.kibana.*\] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\. To proceed, please remove the cluster routing allocation settings with PUT \/_cluster\/settings {"transient": {"cluster\.routing\.allocation\.enable": null}, "persistent": {"cluster\.routing\.allocation\.enable": null}}/ + /Unable to complete saved object migrations for the \[\.kibana\] index: \[unsupported_cluster_routing_allocation\] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\. To proceed, please remove the cluster routing allocation settings with PUT \/_cluster\/settings {\"transient\": {\"cluster\.routing\.allocation\.enable\": null}, \"persistent\": {\"cluster\.routing\.allocation\.enable\": null}}\. Refer to https:\/\/www.elastic.co\/guide\/en\/kibana\/master\/resolve-migrations-failures.html#routing-allocation-disabled for more information on how to resolve the issue\./ ); await retryAsync( @@ -126,7 +126,7 @@ describe('unsupported_cluster_routing_allocation', () => { .map((str) => JSON5.parse(str)) as LogRecord[]; expect( records.find((rec) => - /^Unable to complete saved object migrations for the \[\.kibana.*\] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\./.test( + /^Unable to complete saved object migrations for the \[\.kibana.*\] index: \[unsupported_cluster_routing_allocation\] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\./.test( rec.message ) ) @@ -149,7 +149,7 @@ describe('unsupported_cluster_routing_allocation', () => { await root.setup(); await expect(root.start()).rejects.toThrowError( - /Unable to complete saved object migrations for the \[\.kibana.*\] index: The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\. To proceed, please remove the cluster routing allocation settings with PUT \/_cluster\/settings {"transient": {"cluster\.routing\.allocation\.enable": null}, "persistent": {"cluster\.routing\.allocation\.enable": null}}/ + /Unable to complete saved object migrations for the \[\.kibana\] index: \[unsupported_cluster_routing_allocation\] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue\. To proceed, please remove the cluster routing allocation settings with PUT \/_cluster\/settings {\"transient\": {\"cluster\.routing\.allocation\.enable\": null}, \"persistent\": {\"cluster\.routing\.allocation\.enable\": null}}\. Refer to https:\/\/www.elastic.co\/guide\/en\/kibana\/master\/resolve-migrations-failures.html#routing-allocation-disabled for more information on how to resolve the issue\./ ); }); }); diff --git a/src/core/server/saved_objects/migrations/model/extract_errors.test.ts b/src/core/server/saved_objects/migrations/model/extract_errors.test.ts index a028c40ca6597..e434a5001a6ae 100644 --- a/src/core/server/saved_objects/migrations/model/extract_errors.test.ts +++ b/src/core/server/saved_objects/migrations/model/extract_errors.test.ts @@ -6,7 +6,11 @@ * Side Public License, v 1. */ -import { extractUnknownDocFailureReason } from './extract_errors'; +import { + extractUnknownDocFailureReason, + fatalReasonClusterRoutingAllocationUnsupported, + fatalReasonDocumentExceedsMaxBatchSizeBytes, +} from './extract_errors'; describe('extractUnknownDocFailureReason', () => { it('generates the correct error message', () => { @@ -37,3 +41,32 @@ describe('extractUnknownDocFailureReason', () => { `); }); }); + +describe('fatalReasonDocumentExceedsMaxBatchSizeBytes', () => { + it('generate the correct error message', () => { + expect( + fatalReasonDocumentExceedsMaxBatchSizeBytes({ + _id: 'abc', + docSizeBytes: 106954752, + maxBatchSizeBytes: 104857600, + }) + ).toMatchInlineSnapshot( + `"The document with _id \\"abc\\" is 106954752 bytes which exceeds the configured maximum batch size of 104857600 bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value."` + ); + }); +}); + +describe('fatalReasonClusterRoutingAllocationUnsupported', () => { + it('generates the correct error message', () => { + const errorMessages = fatalReasonClusterRoutingAllocationUnsupported({ + errorMessage: '[some-error] message', + docSectionLink: 'linkToDocsSection', + }); + expect(errorMessages.fatalReason).toMatchInlineSnapshot( + `"[some-error] message To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {\\"transient\\": {\\"cluster.routing.allocation.enable\\": null}, \\"persistent\\": {\\"cluster.routing.allocation.enable\\": null}}. Refer to linkToDocsSection for more information on how to resolve the issue."` + ); + expect(errorMessages.logsErrorMessage).toMatchInlineSnapshot( + `"[some-error] message Ensure that the persistent and transient Elasticsearch configuration option 'cluster.routing.allocation.enable' is not set or set it to a value of 'all'. Refer to linkToDocsSection for more information on how to resolve the issue."` + ); + }); +}); diff --git a/src/core/server/saved_objects/migrations/model/extract_errors.ts b/src/core/server/saved_objects/migrations/model/extract_errors.ts index 95d10603caa80..f41009ab2127c 100644 --- a/src/core/server/saved_objects/migrations/model/extract_errors.ts +++ b/src/core/server/saved_objects/migrations/model/extract_errors.ts @@ -51,3 +51,32 @@ export function extractUnknownDocFailureReason( `'` ); } + +/** + * Constructs migration failure message string for doc exceeds max batch size in bytes + */ +export const fatalReasonDocumentExceedsMaxBatchSizeBytes = ({ + _id, + docSizeBytes, + maxBatchSizeBytes, +}: { + _id: string; + docSizeBytes: number; + maxBatchSizeBytes: number; +}) => + `The document with _id "${_id}" is ${docSizeBytes} bytes which exceeds the configured maximum batch size of ${maxBatchSizeBytes} bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.`; + +/** + * Constructs migration failure message and logs message strings when an unsupported cluster routing allocation is configured. + * The full errorMessage is "[unsupported_cluster_routing_allocation] The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue." + */ +export const fatalReasonClusterRoutingAllocationUnsupported = ({ + errorMessage, + docSectionLink, +}: { + errorMessage: string; + docSectionLink: string; +}) => ({ + fatalReason: `${errorMessage} To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {"transient": {"cluster.routing.allocation.enable": null}, "persistent": {"cluster.routing.allocation.enable": null}}. Refer to ${docSectionLink} for more information on how to resolve the issue.`, + logsErrorMessage: `${errorMessage} Ensure that the persistent and transient Elasticsearch configuration option 'cluster.routing.allocation.enable' is not set or set it to a value of 'all'. Refer to ${docSectionLink} for more information on how to resolve the issue.`, +}); diff --git a/src/core/server/saved_objects/migrations/model/model.test.ts b/src/core/server/saved_objects/migrations/model/model.test.ts index b80e2bceae846..e44995ac8d30e 100644 --- a/src/core/server/saved_objects/migrations/model/model.test.ts +++ b/src/core/server/saved_objects/migrations/model/model.test.ts @@ -96,6 +96,8 @@ describe('migrations v2 model', () => { excludeFromUpgradeFilterHooks: {}, migrationDocLinks: { resolveMigrationFailures: 'resolveMigrationFailures', + repeatedTimeoutRequests: 'repeatedTimeoutRequests', + routingAllocationDisabled: 'routingAllocationDisabled', }, }; @@ -283,12 +285,13 @@ describe('migrations v2 model', () => { test('INIT -> FATAL when cluster routing allocation is not enabled', () => { const res: ResponseType<'INIT'> = Either.left({ type: 'unsupported_cluster_routing_allocation', + message: '[unsupported_cluster_routing_allocation]', }); const newState = model(initState, res) as FatalState; expect(newState.controlState).toEqual('FATAL'); expect(newState.reason).toMatchInlineSnapshot( - `"The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue. To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {\\"transient\\": {\\"cluster.routing.allocation.enable\\": null}, \\"persistent\\": {\\"cluster.routing.allocation.enable\\": null}}"` + `"[unsupported_cluster_routing_allocation] To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {\\"transient\\": {\\"cluster.routing.allocation.enable\\": null}, \\"persistent\\": {\\"cluster.routing.allocation.enable\\": null}}. Refer to routingAllocationDisabled for more information on how to resolve the issue."` ); }); test("INIT -> FATAL when .kibana points to newer version's index", () => { diff --git a/src/core/server/saved_objects/migrations/model/model.ts b/src/core/server/saved_objects/migrations/model/model.ts index e711f62bcd8d6..cff23f0eeda65 100644 --- a/src/core/server/saved_objects/migrations/model/model.ts +++ b/src/core/server/saved_objects/migrations/model/model.ts @@ -21,7 +21,12 @@ import { setProgressTotal, } from './progress'; import { delayRetryState, resetRetryState } from './retry_state'; -import { extractTransformFailuresReason, extractUnknownDocFailureReason } from './extract_errors'; +import { + extractTransformFailuresReason, + extractUnknownDocFailureReason, + fatalReasonDocumentExceedsMaxBatchSizeBytes, + fatalReasonClusterRoutingAllocationUnsupported, +} from './extract_errors'; import type { ExcludeRetryableEsError } from './types'; import { getAliases, @@ -33,17 +38,7 @@ import { } from './helpers'; import { createBatches } from './create_batches'; -const FATAL_REASON_REQUEST_ENTITY_TOO_LARGE = `While indexing a batch of saved objects, Elasticsearch returned a 413 Request Entity Too Large exception. Ensure that the Kibana configuration option 'migrations.maxBatchSizeBytes' is set to a value that is lower than or equal to the Elasticsearch 'http.max_content_length' configuration option.`; -const fatalReasonDocumentExceedsMaxBatchSizeBytes = ({ - _id, - docSizeBytes, - maxBatchSizeBytes, -}: { - _id: string; - docSizeBytes: number; - maxBatchSizeBytes: number; -}) => - `The document with _id "${_id}" is ${docSizeBytes} bytes which exceeds the configured maximum batch size of ${maxBatchSizeBytes} bytes. To proceed, please increase the 'migrations.maxBatchSizeBytes' Kibana configuration option and ensure that the Elasticsearch 'http.max_content_length' configuration option is set to an equal or larger value.`; +export const FATAL_REASON_REQUEST_ENTITY_TOO_LARGE = `While indexing a batch of saved objects, Elasticsearch returned a 413 Request Entity Too Large exception. Ensure that the Kibana configuration option 'migrations.maxBatchSizeBytes' is set to a value that is lower than or equal to the Elasticsearch 'http.max_content_length' configuration option.`; export const model = (currentState: State, resW: ResponseType): State => { // The action response `resW` is weakly typed, the type includes all action @@ -73,15 +68,19 @@ export const model = (currentState: State, resW: ResponseType): if (Either.isLeft(res)) { const left = res.left; if (isLeftTypeof(left, 'unsupported_cluster_routing_allocation')) { + const initErrorMessages = fatalReasonClusterRoutingAllocationUnsupported({ + errorMessage: left.message, + docSectionLink: stateP.migrationDocLinks.routingAllocationDisabled, + }); return { ...stateP, controlState: 'FATAL', - reason: `The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue. To proceed, please remove the cluster routing allocation settings with PUT /_cluster/settings {"transient": {"cluster.routing.allocation.enable": null}, "persistent": {"cluster.routing.allocation.enable": null}}`, + reason: initErrorMessages.fatalReason, logs: [ ...stateP.logs, { level: 'error', - message: `The elasticsearch cluster has cluster routing allocation incorrectly set for migrations to continue. Ensure that the persistent and transient Elasticsearch configuration option 'cluster.routing.allocation.enable' is not set or set it to a value of 'all'.`, + message: initErrorMessages.logsErrorMessage, }, ], }; @@ -244,7 +243,7 @@ export const model = (currentState: State, resW: ResponseType): // we get a response. // If the cluster hit the low watermark for disk usage the LEGACY_CREATE_REINDEX_TARGET action will // continue to timeout and eventually lead to a failed migration. - const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.resolveMigrationFailures} for information on how to resolve the issue.`; + const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.repeatedTimeoutRequests} for information on how to resolve the issue.`; return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); } else { return throwBadResponse(stateP, left); @@ -366,7 +365,7 @@ export const model = (currentState: State, resW: ResponseType): // we get a response. // In the event of retries running out, we link to the docs to help with diagnosing // the problem. - const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.resolveMigrationFailures} for information on how to resolve the issue.`; + const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.repeatedTimeoutRequests} for information on how to resolve the issue.`; return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); } else { return throwBadResponse(stateP, left); @@ -461,7 +460,7 @@ export const model = (currentState: State, resW: ResponseType): // // If there is a problem CREATE_REINDEX_TEMP action will // continue to timeout and eventually lead to a failed migration. - const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.resolveMigrationFailures} for information on how to resolve the issue.`; + const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.repeatedTimeoutRequests} for information on how to resolve the issue.`; return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); } else { return throwBadResponse(stateP, left); @@ -696,7 +695,7 @@ export const model = (currentState: State, resW: ResponseType): // `_cluster/allocation/explain?index=${targetIndex}` API. // Unless the root cause is identified and addressed, the request will // continue to timeout and eventually lead to a failed migration. - const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.resolveMigrationFailures} for information on how to resolve the issue.`; + const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.repeatedTimeoutRequests} for information on how to resolve the issue.`; return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); } else { throwBadResponse(stateP, left); @@ -951,7 +950,7 @@ export const model = (currentState: State, resW: ResponseType): // If the cluster hit the low watermark for disk usage the action will continue to timeout. // Unless the disk space is addressed, the LEGACY_CREATE_REINDEX_TARGET action will // continue to timeout and eventually lead to a failed migration. - const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.resolveMigrationFailures} for information on how to resolve the issue.`; + const retryErrorMessage = `${left.message} Refer to ${stateP.migrationDocLinks.repeatedTimeoutRequests} for information on how to resolve the issue.`; return delayRetryState(stateP, retryErrorMessage, stateP.retryAttempts); } else { return throwBadResponse(stateP, left); diff --git a/src/core/server/saved_objects/migrations/state.ts b/src/core/server/saved_objects/migrations/state.ts index 6630b5ee57808..dee6839d6b902 100644 --- a/src/core/server/saved_objects/migrations/state.ts +++ b/src/core/server/saved_objects/migrations/state.ts @@ -8,6 +8,7 @@ import * as Option from 'fp-ts/lib/Option'; import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { DocLinks } from '@kbn/doc-links'; import { ControlState } from './state_action_machine'; import { AliasAction } from './actions'; import { IndexMapping } from '../mappings'; @@ -125,7 +126,7 @@ export interface BaseState extends ControlState { /** * DocLinks for savedObjects. to reference online documentation */ - readonly migrationDocLinks: Record; + readonly migrationDocLinks: DocLinks['kibanaUpgradeSavedObjects']; } export interface InitState extends BaseState { From b7d42ea04cf24c334c25b8cc55c2c1e7708cb7f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20G=C3=B3mez?= Date: Wed, 4 May 2022 09:23:37 +0200 Subject: [PATCH 07/68] [Unified observability] Add tour step to guided setup (#131149) --- .../observability_status_progress.tsx | 7 +- .../public/pages/overview/index.tsx | 74 ++++++++++++++++--- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/observability/public/components/app/observability_status/observability_status_progress.tsx b/x-pack/plugins/observability/public/components/app/observability_status/observability_status_progress.tsx index 04e77669e963c..050da44457969 100644 --- a/x-pack/plugins/observability/public/components/app/observability_status/observability_status_progress.tsx +++ b/x-pack/plugins/observability/public/components/app/observability_status/observability_status_progress.tsx @@ -24,9 +24,11 @@ import { useGuidedSetupProgress } from '../../../hooks/use_guided_setup_progress interface ObservabilityStatusProgressProps { onViewDetailsClick: () => void; + onDismissClick?: () => void; } export function ObservabilityStatusProgress({ onViewDetailsClick, + onDismissClick, }: ObservabilityStatusProgressProps) { const { hasDataMap, isAllRequestsComplete } = useHasData(); const trackMetric = useUiTracker({ app: 'observability-overview' }); @@ -52,8 +54,11 @@ export function ObservabilityStatusProgress({ const dismissGuidedSetup = useCallback(() => { dismissGuidedSetupProgress(); + if (onDismissClick) { + onDismissClick(); + } trackMetric({ metric: 'guided_setup_progress_dismiss' }); - }, [dismissGuidedSetupProgress, trackMetric]); + }, [dismissGuidedSetupProgress, trackMetric, onDismissClick]); const showDetails = () => { onViewDetailsClick(); diff --git a/x-pack/plugins/observability/public/pages/overview/index.tsx b/x-pack/plugins/observability/public/pages/overview/index.tsx index 6733c90dd0f7a..9ceabf7c3111a 100644 --- a/x-pack/plugins/observability/public/pages/overview/index.tsx +++ b/x-pack/plugins/observability/public/pages/overview/index.tsx @@ -5,16 +5,18 @@ * 2.0. */ import { + EuiButton, + EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, - EuiSpacer, - EuiHorizontalRule, - EuiButton, EuiFlyout, - EuiFlyoutHeader, - EuiTitle, EuiFlyoutBody, + EuiFlyoutHeader, + EuiHorizontalRule, + EuiSpacer, EuiText, + EuiTitle, + EuiTourStep, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; @@ -94,6 +96,8 @@ export function OverviewPage({ routeParams }: Props) { const { hasAnyData, isAllRequestsComplete } = useHasData(); const refetch = useRef<() => void>(); + const [isGuidedSetupTourVisible, setGuidedSetupTourVisible] = useState(false); + const hideGuidedSetupTour = useCallback(() => setGuidedSetupTourVisible(false), []); const { isGuidedSetupProgressDismissed } = useGuidedSetupProgress(); const bucketSize = useMemo( @@ -113,9 +117,9 @@ export function OverviewPage({ routeParams }: Props) { if (isGuidedSetupProgressDismissed) { trackMetric({ metric: 'guided_setup_view_details_after_dismiss' }); } - + hideGuidedSetupTour(); setIsFlyoutVisible(true); - }, [trackMetric, isGuidedSetupProgressDismissed]); + }, [trackMetric, isGuidedSetupProgressDismissed, hideGuidedSetupTour]); const onTimeRangeRefresh = useCallback(() => { return refetch.current && refetch.current(); @@ -162,6 +166,8 @@ export function OverviewPage({ routeParams }: Props) { ? { children: ( @@ -173,7 +179,10 @@ export function OverviewPage({ routeParams }: Props) { {hasData && ( <> - setIsFlyoutVisible(true)} /> + setIsFlyoutVisible(true)} + onDismissClick={() => setGuidedSetupTourVisible(true)} + /> void; handleGuidedSetupClick: () => void; onTimeRangeRefresh: () => void; } -function PageHeader({ handleGuidedSetupClick, onTimeRangeRefresh }: PageHeaderProps) { +function PageHeader({ + showTour = false, + onTourDismiss, + handleGuidedSetupClick, + onTimeRangeRefresh, +}: PageHeaderProps) { const { relativeStart, relativeEnd, refreshInterval, refreshPaused } = useDatePickerContext(); + const buttonRef = useRef(); + return ( @@ -287,12 +305,48 @@ function PageHeader({ handleGuidedSetupClick, onTimeRangeRefresh }: PageHeaderPr /> - + + {showTour ? ( + buttonRef.current} + isStepOpen + title={i18n.translate('xpack.observability.overview.guidedSetupTourTitle', { + defaultMessage: 'Guided setup is always available', + })} + content={ + + + + } + step={1} + stepsTotal={1} + maxWidth={400} + onFinish={onTourDismiss} + footerAction={ + + + + } + /> + ) : null} ); From f2f90ba9fd7d26e418d6cc4b422e938e19e21b11 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 4 May 2022 09:53:08 +0200 Subject: [PATCH 08/68] [Lens] Improved interval input (#131372) --- .../definitions/date_histogram.test.tsx | 99 +++-- .../operations/definitions/date_histogram.tsx | 380 ++++++++---------- .../translations/translations/fr-FR.json | 10 - .../translations/translations/ja-JP.json | 10 - .../translations/translations/zh-CN.json | 10 - 5 files changed, 226 insertions(+), 283 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx index d4491fbba00cf..e1e5f39a8cc48 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import type { DateHistogramIndexPatternColumn } from './date_histogram'; import { dateHistogramOperation } from '.'; -import { shallow } from 'enzyme'; +import { mount, shallow } from 'enzyme'; import { EuiSwitch } from '@elastic/eui'; import { unifiedSearchPluginMock } from '@kbn/unified-search-plugin/public/mocks'; import type { IUiSettingsClient, SavedObjectsClientContract, HttpSetup } from '@kbn/core/public'; @@ -18,6 +18,7 @@ import { dataPluginMock, getCalculateAutoTimeExpression } from '@kbn/data-plugin import { createMockedIndexPattern } from '../../mocks'; import type { IndexPatternLayer, IndexPattern } from '../../types'; import { getFieldByNameFactory } from '../../pure_helpers'; +import { act } from 'react-dom/test-utils'; const dataStart = dataPluginMock.createStartContract(); const unifiedSearchStart = unifiedSearchPluginMock.createStartContract(); @@ -312,8 +313,9 @@ describe('date_histogram', () => { /> ); - expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual(42); - expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('w'); + expect( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('selectedOptions') + ).toEqual([expect.objectContaining({ label: '42w' })]); }); it('should render current value for other index pattern', () => { @@ -348,11 +350,12 @@ describe('date_histogram', () => { /> ); - expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual(''); - expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('d'); + expect( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('selectedOptions') + ).toEqual([expect.objectContaining({ key: 'd' })]); }); - it('should render disabled switch and no time interval control for auto interval', () => { + it('should render time interval control set to auto for auto interval', () => { const thirdLayer: IndexPatternLayer = { indexPatternId: '1', columnOrder: ['col1'], @@ -382,9 +385,9 @@ describe('date_histogram', () => { indexPattern={indexPattern1} /> ); - expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy(); - expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').exists()).toBeFalsy(); - expect(instance.find(EuiSwitch).at(1).prop('checked')).toBe(false); + expect( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('selectedOptions') + ).toEqual([expect.objectContaining({ key: 'auto' })]); }); it('should allow switching to manual interval', () => { @@ -461,7 +464,7 @@ describe('date_histogram', () => { ); instance .find(EuiSwitch) - .at(2) + .at(1) .simulate('change', { target: { checked: false }, }); @@ -502,16 +505,14 @@ describe('date_histogram', () => { indexPattern={{ ...indexPattern1, timeFieldName: undefined }} /> ); - instance - .find(EuiSwitch) - .at(1) - .simulate('change', { - target: { checked: false }, - }); + ( + instance + .find('[data-test-subj="lensDateHistogramInterval"]') + .prop('onChange') as unknown as (v: Array<{ key: string }>) => void + )([{ key: 'auto' }]); expect(updateLayerSpy).toHaveBeenCalled(); const newLayer = updateLayerSpy.mock.calls[0][0]; expect(newLayer).toHaveProperty('columns.col1.params.ignoreTimeRange', false); - expect(newLayer).toHaveProperty('columns.col1.params.interval', 'auto'); }); it('turns off drop partial bucket on tuning off time range ignore', () => { @@ -560,12 +561,14 @@ describe('date_histogram', () => { currentColumn={layer.columns.col1 as DateHistogramIndexPatternColumn} /> ); - instance.find('[data-test-subj="lensDateHistogramValue"]').simulate('change', { - target: { - value: '2', - }, - }); - expect(updateLayerSpy).toHaveBeenCalledWith(layerWithInterval('1w')); + ( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('onCreateOption') as ( + s: string + ) => void + )('2w'); + expect( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid') + ).toBeTruthy(); }); it('should display error if an invalid interval is specified', () => { @@ -580,7 +583,9 @@ describe('date_histogram', () => { currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn} /> ); - expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy(); + expect( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid') + ).toBeTruthy(); }); it('should not display error if interval value is blank', () => { @@ -595,7 +600,9 @@ describe('date_histogram', () => { currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn} /> ); - expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeFalsy(); + expect( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid') + ).toBeFalsy(); }); it('should display error if interval value is 0', () => { @@ -610,12 +617,14 @@ describe('date_histogram', () => { currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn} /> ); - expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy(); + expect( + instance.find('[data-test-subj="lensDateHistogramInterval"]').prop('isInvalid') + ).toBeTruthy(); }); - it('should update the unit', () => { + it('should update the unit', async () => { const updateLayerSpy = jest.fn(); - const instance = shallow( + const instance = mount( { currentColumn={layer.columns.col1 as DateHistogramIndexPatternColumn} /> ); - instance.find('[data-test-subj="lensDateHistogramUnit"]').simulate('change', { - target: { - value: 'd', - }, + act(() => { + ( + instance + .find('[data-test-subj="lensDateHistogramInterval"]') + .at(0) + .prop('onCreateOption') as (s: string) => void + )('42d'); }); - expect(updateLayerSpy).toHaveBeenCalledWith(layerWithInterval('42d')); + expect(updateLayerSpy.mock.calls[0][0](layer)).toEqual(layerWithInterval('42d')); }); it('should update the value', () => { const updateLayerSpy = jest.fn(); const testLayer = layerWithInterval('42d'); - const instance = shallow( + const instance = mount( { currentColumn={testLayer.columns.col1 as DateHistogramIndexPatternColumn} /> ); - instance.find('[data-test-subj="lensDateHistogramValue"]').simulate('change', { - target: { - value: '9', - }, - }); - expect(updateLayerSpy).toHaveBeenCalledWith(layerWithInterval('9d')); + act(() => + ( + instance + .find('[data-test-subj="lensDateHistogramInterval"]') + .at(0) + .prop('onCreateOption') as (s: string) => void + )('9d') + ); + expect(updateLayerSpy.mock.calls[0][0](layer)).toEqual(layerWithInterval('9d')); }); it('should not render options if they are restricted', () => { @@ -695,7 +710,7 @@ describe('date_histogram', () => { /> ); - expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy(); + expect(instance.find('[data-test-subj="lensDateHistogramInterval"]').exists()).toBeFalsy(); }); it('should allow the drop of partial buckets', () => { @@ -735,7 +750,7 @@ describe('date_histogram', () => { target: { checked: true }, }); expect(updateLayerSpy).toHaveBeenCalled(); - const newLayer = updateLayerSpy.mock.calls[0][0]; + const newLayer = updateLayerSpy.mock.calls[0][0](layer); expect(newLayer).toHaveProperty('columns.col1.params.dropPartials', true); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx index 56b82dc03101c..3b6d75879640d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx @@ -5,31 +5,27 @@ * 2.0. */ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiBasicTable, EuiCode, - EuiFieldNumber, - EuiFlexGroup, - EuiFlexItem, + EuiComboBox, EuiFormRow, EuiIconTip, - EuiSelect, - EuiSpacer, EuiSwitch, EuiSwitchEvent, - EuiTextColor, } from '@elastic/eui'; import { AggFunctionsMapping, + AggParamOption, IndexPatternAggRestrictions, search, UI_SETTINGS, } from '@kbn/data-plugin/public'; -import { extendedBoundsToAst } from '@kbn/data-plugin/common'; +import { extendedBoundsToAst, intervalOptions } from '@kbn/data-plugin/common'; import { buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { updateColumnParam } from '../layer_helpers'; import { OperationDefinition, ParamEditorProps } from '.'; @@ -184,54 +180,81 @@ export const dateHistogramOperation: OperationDefinition< const intervalIsRestricted = field!.aggregationRestrictions && field!.aggregationRestrictions.date_histogram; - const interval = parseInterval(currentColumn.params.interval); + const [intervalInput, setIntervalInput] = useState(currentColumn.params.interval); + const interval = intervalInput === autoInterval ? autoInterval : parseInterval(intervalInput); // We force the interval value to 1 if it's empty, since that is the ES behavior, // and the isValidInterval function doesn't handle the empty case properly. Fixing // isValidInterval involves breaking changes in other areas. - const isValid = isValidInterval( - `${interval.value === '' ? '1' : interval.value}${interval.unit}`, - restrictedInterval(field!.aggregationRestrictions) - ); + const isValid = + (!currentColumn.params.ignoreTimeRange && intervalInput === autoInterval) || + (interval !== autoInterval && + intervalInput !== '' && + isValidInterval( + `${interval.value === '' ? '1' : interval.value}${interval.unit}`, + restrictedInterval(field!.aggregationRestrictions) + )); - const onChangeAutoInterval = useCallback( + const onChangeDropPartialBuckets = useCallback( (ev: EuiSwitchEvent) => { - const { fromDate, toDate } = dateRange; - const value = ev.target.checked - ? data.search.aggs.calculateAutoTimeExpression({ from: fromDate, to: toDate }) || '1h' - : autoInterval; - updateLayer( + updateLayer((newLayer) => updateColumnParam({ - layer: updateColumnParam({ layer, columnId, paramName: 'interval', value }), + layer: newLayer, columnId, - paramName: 'ignoreTimeRange', - value: false, + paramName: 'dropPartials', + value: ev.target.checked, }) ); }, - [dateRange, data.search.aggs, updateLayer, layer, columnId] + [columnId, updateLayer] ); - const onChangeDropPartialBuckets = useCallback( - (ev: EuiSwitchEvent) => { - updateLayer( - updateColumnParam({ - layer, - columnId, - paramName: 'dropPartials', - value: ev.target.checked, - }) + const setInterval = useCallback( + (newInterval: typeof interval) => { + const isCalendarInterval = + newInterval !== autoInterval && calendarOnlyIntervals.has(newInterval.unit); + const value = + newInterval === autoInterval + ? autoInterval + : `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`; + + updateLayer((newLayer) => + updateColumnParam({ layer: newLayer, columnId, paramName: 'interval', value }) ); }, - [columnId, layer, updateLayer] + [columnId, updateLayer] ); - const setInterval = (newInterval: typeof interval) => { - const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit); - const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`; + const options = (intervalOptions || []) + .filter((option) => option.val !== autoInterval) + .map((option: AggParamOption) => { + return { label: option.display, key: option.val }; + }, []); - updateLayer(updateColumnParam({ layer, columnId, paramName: 'interval', value })); - }; + options.unshift({ + label: i18n.translate('xpack.lens.indexPattern.autoIntervalLabel', { + defaultMessage: 'Auto ({interval})', + values: { + interval: + data.search.aggs.calculateAutoTimeExpression({ + from: dateRange.fromDate, + to: dateRange.toDate, + }) || '1h', + }, + }), + key: autoInterval, + }); + + const definedOption = options.find((o) => o.key === intervalInput); + const selectedOptions = definedOption + ? [definedOption] + : [{ label: intervalInput, key: intervalInput }]; + + useEffect(() => { + if (isValid && intervalInput !== currentColumn.params.interval) { + setInterval(parseInterval(intervalInput)); + } + }, [intervalInput, isValid, currentColumn.params.interval, setInterval]); const bindToGlobalTimePickerValue = indexPattern.timeFieldName === field?.name || !currentColumn.params.ignoreTimeRange; @@ -260,187 +283,122 @@ export const dateHistogramOperation: OperationDefinition< /> - {!intervalIsRestricted && ( - - + {intervalIsRestricted ? ( + - - )} - {currentColumn.params.interval !== autoInterval && ( - <> - - {intervalIsRestricted ? ( - - ) : ( - <> - - - { - const newInterval = { - ...interval, - value: e.target.value, - }; - setInterval(newInterval); - }} - step={1} - /> - - - { - const newInterval = { - ...interval, - unit: e.target.value, - }; - setInterval(newInterval); - }} - isInvalid={!isValid} - options={[ - { - value: 'ms', - text: i18n.translate( - 'xpack.lens.indexPattern.dateHistogram.milliseconds', - { - defaultMessage: 'milliseconds', - } - ), - }, - { - value: 's', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', { - defaultMessage: 'seconds', - }), - }, - { - value: 'm', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', { - defaultMessage: 'minutes', - }), - }, - { - value: 'h', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', { - defaultMessage: 'hours', - }), - }, - { - value: 'd', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', { - defaultMessage: 'days', - }), - }, - { - value: 'w', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', { - defaultMessage: 'week', - }), - }, - { - value: 'M', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', { - defaultMessage: 'month', - }), - }, - // Quarterly intervals appear to be unsupported by esaggs - { - value: 'y', - text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', { - defaultMessage: 'year', - }), - }, - ]} - /> - - - {!isValid && ( - <> - - - {i18n.translate('xpack.lens.indexPattern.invalidInterval', { - defaultMessage: 'Invalid interval value', - })} - - - )} - - )} - - - - {i18n.translate( - 'xpack.lens.indexPattern.dateHistogram.bindToGlobalTimePicker', - { - defaultMessage: 'Bind to global time picker', - } - )}{' '} - - - } - disabled={indexPattern.timeFieldName === field?.name} - checked={bindToGlobalTimePickerValue} - onChange={() => { + ) : ( + { + const newValue = opts.length ? opts[0].key! : ''; + setIntervalInput(newValue); + if (newValue === autoInterval && currentColumn.params.ignoreTimeRange) { updateLayer( updateColumnParam({ layer, columnId, paramName: 'ignoreTimeRange', - value: !currentColumn.params.ignoreTimeRange, + value: false, }) ); - }} - compressed - /> - - - )} + } + }} + onCreateOption={(customValue: string) => setIntervalInput(customValue.trim())} + options={options} + selectedOptions={selectedOptions} + singleSelection={{ asPlainText: true }} + placeholder={i18n.translate( + 'xpack.lens.indexPattern.dateHistogram.selectIntervalPlaceholder', + { + defaultMessage: 'Select an interval', + } + )} + /> + )} + + + + {i18n.translate('xpack.lens.indexPattern.dateHistogram.bindToGlobalTimePicker', { + defaultMessage: 'Bind to global time picker', + })}{' '} + + + } + disabled={indexPattern.timeFieldName === field?.name} + checked={bindToGlobalTimePickerValue} + onChange={() => { + let newLayer = updateColumnParam({ + layer, + columnId, + paramName: 'ignoreTimeRange', + value: !currentColumn.params.ignoreTimeRange, + }); + if ( + !currentColumn.params.ignoreTimeRange && + currentColumn.params.interval === autoInterval + ) { + const newFixedInterval = + data.search.aggs.calculateAutoTimeExpression({ + from: dateRange.fromDate, + to: dateRange.toDate, + }) || '1h'; + newLayer = updateColumnParam({ + layer: newLayer, + columnId, + paramName: 'interval', + value: newFixedInterval, + }); + setIntervalInput(newFixedInterval); + } + updateLayer(newLayer); + }} + compressed + /> + Date: Wed, 4 May 2022 10:02:54 +0200 Subject: [PATCH 09/68] [Vega] Adjust vega doc for usage of ems files (#130948) * adjust vega doc * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Nick Peihl --- docs/user/dashboard/vega-reference.asciidoc | 43 ++++++++++++++------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/docs/user/dashboard/vega-reference.asciidoc b/docs/user/dashboard/vega-reference.asciidoc index b593eacf703fb..95b1ffb27b476 100644 --- a/docs/user/dashboard/vega-reference.asciidoc +++ b/docs/user/dashboard/vega-reference.asciidoc @@ -242,12 +242,17 @@ experimental[] Access the Elastic Map Service files via the same mechanism: url: { // "type" defaults to "elasticsearch" otherwise %type%: emsfile - // Name of the file, exactly as in the Region map visualization + // Name of the file, exactly as in https://maps.elastic.co name: World Countries } -// The result is a geojson file, get its features to use -// this data source with the "shape" marks +// The result is either a topojson file or a geojson file. +// Refer to the Default format for the file at https://maps.elastic.co +// Get its features to use this data source with the "shape" marks // https://vega.github.io/vega/docs/marks/shape/ +// For a topojson file use +format: {type: "topojson", feature: "data"} + +// For a geojson file use format: {property: "features"} ---- @@ -310,16 +315,28 @@ experimental[] You can use the *Vega* https://vega.github.io/vega/docs/data/[dat [source,yaml] ---- -url: { - // "type" defaults to "elasticsearch" otherwise - %type%: emsfile - // Name of the file, exactly as in the Region map visualization - name: World Countries -} -// The result is a geojson file, get its features to use -// this data source with the "shape" marks -// https://vega.github.io/vega/docs/marks/shape/ -format: {property: "features"} + "data": [ + { + "name": "countries", + "url": { + // "type" defaults to "elasticsearch" otherwise + %type%: emsfile + // Name of the file, exactly as in the Region map visualization + name: World Countries + }, + // The result is a topojson file, get its features to use + // this data source with the "shape" marks + // https://vega.github.io/vega/docs/marks/shape/ + "format": {"type": "topojson", "feature": "data"}, + } + ], + "marks": [ + { + "type": "shape", + "from": {"data": "countries"}, + "transform": [{"type": "geoshape", "projection": "projection"}] + } + ] ---- [float] From 41c629639bf94e9492ae2ddb64312c296943f507 Mon Sep 17 00:00:00 2001 From: CohenIdo <90558359+CohenIdo@users.noreply.github.com> Date: Wed, 4 May 2022 11:58:19 +0300 Subject: [PATCH 10/68] [Cloud Security] fetch all rules templates --- .../fleet_integration.test.ts | 18 ++++++++++++++++++ .../fleet_integration/fleet_integration.ts | 5 ++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts index 69e13ab8c5065..82d831c362fbb 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.test.ts @@ -66,6 +66,24 @@ describe('create CSP rules with post package create callback', () => { ]); }); + it('validate that all rules templates are fetched', async () => { + const mockPackagePolicy = createPackagePolicyMock(); + mockPackagePolicy.package!.name = CLOUD_SECURITY_POSTURE_PACKAGE_NAME; + mockSoClient.find.mockResolvedValueOnce({ + saved_objects: [ + { + type: 'csp-rule-template', + id: 'csp_rule_template-41308bcdaaf665761478bb6f0d745a5c', + attributes: { ...ruleAttributes }, + }, + ], + pit_id: undefined, + } as unknown as SavedObjectsFindResponse); + await onPackagePolicyPostCreateCallback(logger, mockPackagePolicy, mockSoClient); + + expect(mockSoClient.find.mock.calls[0][0]).toMatchObject({ perPage: 10000 }); + }); + it('should not create rules when the package policy is not csp package', async () => { const mockPackagePolicy = createPackagePolicyMock(); mockPackagePolicy.package!.name = 'not_csp_package'; diff --git a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts index da45a53256bde..347730b589672 100644 --- a/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/cloud_security_posture/server/fleet_integration/fleet_integration.ts @@ -46,7 +46,10 @@ export const onPackagePolicyPostCreateCallback = async ( } // Create csp-rules from the generic asset const existingRuleTemplates: SavedObjectsFindResponse = - await savedObjectsClient.find({ type: cloudSecurityPostureRuleTemplateSavedObjectType }); + await savedObjectsClient.find({ + type: cloudSecurityPostureRuleTemplateSavedObjectType, + perPage: 10000, + }); if (existingRuleTemplates.total === 0) { return; From 07c8da05c290e6694c1865c3e0cc392d92011303 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 4 May 2022 12:00:16 +0300 Subject: [PATCH 11/68] [Cases] Fix `find` method of the cases UI client. (#131407) --- x-pack/plugins/cases/common/ui/types.ts | 17 ++----- .../cases/public/api/__mocks__/index.ts | 17 +++++++ x-pack/plugins/cases/public/api/decoders.ts | 28 ++++++++++ x-pack/plugins/cases/public/api/index.test.ts | 32 ++++++++++++ x-pack/plugins/cases/public/api/index.ts | 45 ++++++++++++++++ x-pack/plugins/cases/public/api/utils.test.ts | 42 +++++++++++++++ x-pack/plugins/cases/public/api/utils.ts | 43 ++++++++++++++++ .../cases/public/client/api/index.test.ts | 4 +- .../plugins/cases/public/client/api/index.ts | 11 ++-- .../cases/public/common/lib/kibana/hooks.ts | 2 +- .../public/components/all_cases/table.tsx | 4 +- .../components/all_cases/utility_bar.tsx | 4 +- .../cases/public/containers/__mocks__/api.ts | 4 +- .../cases/public/containers/api.test.tsx | 25 ++++++--- x-pack/plugins/cases/public/containers/api.ts | 41 +++++---------- .../cases/public/containers/configure/api.ts | 9 +--- .../plugins/cases/public/containers/mock.ts | 4 +- .../cases/public/containers/use_get_cases.tsx | 14 ++--- .../containers/use_get_cases_status.test.tsx | 20 +++++--- .../containers/use_get_cases_status.tsx | 17 ++++--- .../plugins/cases/public/containers/utils.ts | 51 +------------------ x-pack/plugins/cases/public/mocks.ts | 2 +- x-pack/plugins/cases/public/types.ts | 5 +- .../use_cases_by_status.test.tsx | 21 ++++---- .../cases_by_status/use_cases_by_status.tsx | 37 +++++++------- 25 files changed, 330 insertions(+), 169 deletions(-) create mode 100644 x-pack/plugins/cases/public/api/__mocks__/index.ts create mode 100644 x-pack/plugins/cases/public/api/decoders.ts create mode 100644 x-pack/plugins/cases/public/api/index.test.ts create mode 100644 x-pack/plugins/cases/public/api/index.ts create mode 100644 x-pack/plugins/cases/public/api/utils.test.ts create mode 100644 x-pack/plugins/cases/public/api/utils.ts diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index 4e5671a946506..54074d7295b45 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -17,6 +17,8 @@ import { CommentResponse, CaseResponse, CommentResponseAlertsType, + CasesFindResponse, + CasesStatusResponse, } from '../api'; import { SnakeToCamelCase } from '../types'; @@ -61,6 +63,8 @@ export type AlertComment = SnakeToCamelCase; export type CaseUserActions = SnakeToCamelCase; export type CaseExternalService = SnakeToCamelCase; export type Case = Omit, 'comments'> & { comments: Comment[] }; +export type Cases = Omit, 'cases'> & { cases: Case[] }; +export type CasesStatus = SnakeToCamelCase; export interface ResolvedCase { case: Case; @@ -84,19 +88,6 @@ export interface FilterOptions { owner: string[]; } -export interface CasesStatus { - countClosedCases: number | null; - countOpenCases: number | null; - countInProgressCases: number | null; -} - -export interface AllCases extends CasesStatus { - cases: Case[]; - page: number; - perPage: number; - total: number; -} - export type SingleCaseMetrics = SingleCaseMetricsResponse; export type SingleCaseMetricsFeature = | 'alerts.count' diff --git a/x-pack/plugins/cases/public/api/__mocks__/index.ts b/x-pack/plugins/cases/public/api/__mocks__/index.ts new file mode 100644 index 0000000000000..a1df651240224 --- /dev/null +++ b/x-pack/plugins/cases/public/api/__mocks__/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CasesFindRequest } from '../../../common/api'; +import { HTTPService } from '..'; +import { casesStatus } from '../../containers/mock'; +import { CasesStatus } from '../../containers/types'; + +export const getCasesStatus = async ({ + http, + signal, + query, +}: HTTPService & { query: CasesFindRequest }): Promise => Promise.resolve(casesStatus); diff --git a/x-pack/plugins/cases/public/api/decoders.ts b/x-pack/plugins/cases/public/api/decoders.ts new file mode 100644 index 0000000000000..5275555ce9345 --- /dev/null +++ b/x-pack/plugins/cases/public/api/decoders.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { fold } from 'fp-ts/lib/Either'; +import { identity } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; + +import { createToasterPlainError } from '../containers/utils'; +import { throwErrors } from '../../common'; +import { + CasesFindResponse, + CasesFindResponseRt, + CasesStatusResponse, + CasesStatusResponseRt, +} from '../../common/api'; + +export const decodeCasesFindResponse = (respCases?: CasesFindResponse) => + pipe(CasesFindResponseRt.decode(respCases), fold(throwErrors(createToasterPlainError), identity)); + +export const decodeCasesStatusResponse = (respCase?: CasesStatusResponse) => + pipe( + CasesStatusResponseRt.decode(respCase), + fold(throwErrors(createToasterPlainError), identity) + ); diff --git a/x-pack/plugins/cases/public/api/index.test.ts b/x-pack/plugins/cases/public/api/index.test.ts new file mode 100644 index 0000000000000..ed0bed55f6c97 --- /dev/null +++ b/x-pack/plugins/cases/public/api/index.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { httpServiceMock } from '@kbn/core/public/mocks'; +import { getCases } from '.'; +import { allCases, allCasesSnake } from '../containers/mock'; + +describe('api', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('getCases', () => { + const http = httpServiceMock.createStartContract({ basePath: '' }); + http.get.mockResolvedValue(allCasesSnake); + + it('should return the correct response', async () => { + expect(await getCases({ http, query: { from: 'now-1d' } })).toEqual(allCases); + }); + + it('should have been called with the correct path', async () => { + await getCases({ http, query: { perPage: 10 } }); + expect(http.get).toHaveBeenCalledWith('/api/cases/_find', { + query: { perPage: 10 }, + }); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/api/index.ts b/x-pack/plugins/cases/public/api/index.ts new file mode 100644 index 0000000000000..33eb4ba6576c9 --- /dev/null +++ b/x-pack/plugins/cases/public/api/index.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { HttpStart } from '@kbn/core/public'; +import { Cases, CasesStatus } from '../../common/ui'; +import { CASE_FIND_URL, CASE_STATUS_URL } from '../../common/constants'; +import { + CasesFindRequest, + CasesFindResponse, + CasesStatusRequest, + CasesStatusResponse, +} from '../../common/api'; +import { convertAllCasesToCamel, convertToCamelCase } from './utils'; +import { decodeCasesFindResponse, decodeCasesStatusResponse } from './decoders'; + +export interface HTTPService { + http: HttpStart; + signal?: AbortSignal; +} + +export const getCases = async ({ + http, + signal, + query, +}: HTTPService & { query: CasesFindRequest }): Promise => { + const res = await http.get(CASE_FIND_URL, { query, signal }); + return convertAllCasesToCamel(decodeCasesFindResponse(res)); +}; + +export const getCasesStatus = async ({ + http, + signal, + query, +}: HTTPService & { query: CasesStatusRequest }): Promise => { + const response = await http.get(CASE_STATUS_URL, { + signal, + query, + }); + + return convertToCamelCase(decodeCasesStatusResponse(response)); +}; diff --git a/x-pack/plugins/cases/public/api/utils.test.ts b/x-pack/plugins/cases/public/api/utils.test.ts new file mode 100644 index 0000000000000..f46ada35ffca1 --- /dev/null +++ b/x-pack/plugins/cases/public/api/utils.test.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { allCases, allCasesSnake } from '../containers/mock'; +import { convertAllCasesToCamel, convertArrayToCamelCase, convertToCamelCase } from './utils'; + +describe('utils', () => { + describe('convertArrayToCamelCase', () => { + it('converts an array of items to camel case correctly', () => { + const items = [ + { foo_bar: [{ bar_foo: '1' }], test_bar: '2', obj_pros: { is_valid: true } }, + { bar_test: [{ baz_foo: '1' }], test_bar: '2', obj_pros: { is_valid: true } }, + ]; + expect(convertArrayToCamelCase(items)).toEqual([ + { fooBar: [{ barFoo: '1' }], testBar: '2', objPros: { isValid: true } }, + { barTest: [{ bazFoo: '1' }], testBar: '2', objPros: { isValid: true } }, + ]); + }); + }); + + describe('convertToCamelCase', () => { + it('converts an object to camel case correctly', () => { + const obj = { bar_test: [{ baz_foo: '1' }], test_bar: '2', obj_pros: { is_valid: true } }; + + expect(convertToCamelCase(obj)).toEqual({ + barTest: [{ bazFoo: '1' }], + testBar: '2', + objPros: { isValid: true }, + }); + }); + }); + + describe('convertAllCasesToCamel', () => { + it('converts the find response to camel case', () => { + expect(convertAllCasesToCamel(allCasesSnake)).toEqual(allCases); + }); + }); +}); diff --git a/x-pack/plugins/cases/public/api/utils.ts b/x-pack/plugins/cases/public/api/utils.ts new file mode 100644 index 0000000000000..19cb800de921b --- /dev/null +++ b/x-pack/plugins/cases/public/api/utils.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isArray, set, camelCase, isObject } from 'lodash'; +import { CasesFindResponse, CaseResponse } from '../../common/api'; +import { Cases, Case } from '../containers/types'; + +export const convertArrayToCamelCase = (arrayOfSnakes: unknown[]): unknown[] => + arrayOfSnakes.reduce((acc: unknown[], value) => { + if (isArray(value)) { + return [...acc, convertArrayToCamelCase(value)]; + } else if (isObject(value)) { + return [...acc, convertToCamelCase(value)]; + } else { + return [...acc, value]; + } + }, []); + +export const convertToCamelCase = (obj: T): U => + Object.entries(obj).reduce((acc, [key, value]) => { + if (isArray(value)) { + set(acc, camelCase(key), convertArrayToCamelCase(value)); + } else if (isObject(value)) { + set(acc, camelCase(key), convertToCamelCase(value)); + } else { + set(acc, camelCase(key), value); + } + return acc; + }, {} as U); + +export const convertAllCasesToCamel = (snakeCases: CasesFindResponse): Cases => ({ + cases: snakeCases.cases.map((theCase) => convertToCamelCase(theCase)), + countOpenCases: snakeCases.count_open_cases, + countInProgressCases: snakeCases.count_in_progress_cases, + countClosedCases: snakeCases.count_closed_cases, + page: snakeCases.page, + perPage: snakeCases.per_page, + total: snakeCases.total, +}); diff --git a/x-pack/plugins/cases/public/client/api/index.test.ts b/x-pack/plugins/cases/public/client/api/index.test.ts index 8bf4ca682fe3b..dcefecf87c476 100644 --- a/x-pack/plugins/cases/public/client/api/index.test.ts +++ b/x-pack/plugins/cases/public/client/api/index.test.ts @@ -7,7 +7,7 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; import { createClientAPI } from '.'; -import { allCases, casesStatus } from '../../containers/mock'; +import { allCases, casesStatus, allCasesSnake } from '../../containers/mock'; describe('createClientAPI', () => { beforeEach(() => { @@ -48,7 +48,7 @@ describe('createClientAPI', () => { describe('find', () => { const http = httpServiceMock.createStartContract({ basePath: '' }); const api = createClientAPI({ http }); - http.get.mockResolvedValue(allCases); + http.get.mockResolvedValue(allCasesSnake); it('should return the correct response', async () => { expect(await api.cases.find({ from: 'now-1d' })).toEqual(allCases); diff --git a/x-pack/plugins/cases/public/client/api/index.ts b/x-pack/plugins/cases/public/client/api/index.ts index 8f55f7a4f0739..a4a16489d4dc9 100644 --- a/x-pack/plugins/cases/public/client/api/index.ts +++ b/x-pack/plugins/cases/public/client/api/index.ts @@ -11,11 +11,12 @@ import { CasesByAlertIDRequest, CasesFindRequest, getCasesFromAlertsUrl, - CasesResponse, CasesStatusRequest, CasesStatusResponse, } from '../../../common/api'; -import { CASE_FIND_URL, CASE_STATUS_URL } from '../../../common/constants'; +import { CASE_STATUS_URL } from '../../../common/constants'; +import { Cases, CasesStatus } from '../../../common/ui'; +import { getCases, getCasesStatus } from '../../api'; import { CasesUiStart } from '../../types'; export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['api'] => { @@ -26,10 +27,12 @@ export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['ap ): Promise => http.get(getCasesFromAlertsUrl(alertId), { query }), cases: { - find: (query: CasesFindRequest): Promise => - http.get(CASE_FIND_URL, { query }), + find: (query: CasesFindRequest, signal?: AbortSignal): Promise => + getCases({ http, query, signal }), getAllCasesMetrics: (query: CasesStatusRequest): Promise => http.get(CASE_STATUS_URL, { query }), + getCasesStatus: (query: CasesStatusRequest, signal?: AbortSignal): Promise => + getCasesStatus({ http, query, signal }), }, }; }; diff --git a/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts b/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts index 02a099f9c6a1f..a53a1e9ea452f 100644 --- a/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts +++ b/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts @@ -12,12 +12,12 @@ import { i18n } from '@kbn/i18n'; import { AuthenticatedUser } from '@kbn/security-plugin/common/model'; import { NavigateToAppOptions } from '@kbn/core/public'; +import { convertToCamelCase } from '../../../api/utils'; import { FEATURE_ID, DEFAULT_DATE_FORMAT, DEFAULT_DATE_FORMAT_TZ, } from '../../../../common/constants'; -import { convertToCamelCase } from '../../../containers/utils'; import { StartServices } from '../../../types'; import { useUiSetting, useKibana } from './kibana_react'; diff --git a/x-pack/plugins/cases/public/components/all_cases/table.tsx b/x-pack/plugins/cases/public/components/all_cases/table.tsx index 8190acce9e784..ce3442e734b43 100644 --- a/x-pack/plugins/cases/public/components/all_cases/table.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/table.tsx @@ -19,13 +19,13 @@ import styled from 'styled-components'; import { CasesTableUtilityBar } from './utility_bar'; import { LinkButton } from '../links'; -import { AllCases, Case, FilterOptions } from '../../../common/ui/types'; +import { Cases, Case, FilterOptions } from '../../../common/ui/types'; import * as i18n from './translations'; import { useCreateCaseNavigation } from '../../common/navigation'; interface CasesTableProps { columns: EuiBasicTableProps['columns']; - data: AllCases; + data: Cases; filterOptions: FilterOptions; goToCreateCase?: () => void; handleIsLoading: (a: boolean) => void; diff --git a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx index 64e22d7aa4e9c..a6247cedd3fac 100644 --- a/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/utility_bar.tsx @@ -15,14 +15,14 @@ import { UtilityBarText, } from '../utility_bar'; import * as i18n from './translations'; -import { AllCases, Case, DeleteCase, FilterOptions } from '../../../common/ui/types'; +import { Cases, Case, DeleteCase, FilterOptions } from '../../../common/ui/types'; import { getBulkItems } from '../bulk_actions'; import { useDeleteCases } from '../../containers/use_delete_cases'; import { ConfirmDeleteCaseModal } from '../confirm_delete_case'; import { useUpdateCases } from '../../containers/use_bulk_update_case'; interface OwnProps { - data: AllCases; + data: Cases; enableBulkActions: boolean; filterOptions: FilterOptions; handleIsLoading: (a: boolean) => void; diff --git a/x-pack/plugins/cases/public/containers/__mocks__/api.ts b/x-pack/plugins/cases/public/containers/__mocks__/api.ts index 3906997349357..4b2029a83d6dd 100644 --- a/x-pack/plugins/cases/public/containers/__mocks__/api.ts +++ b/x-pack/plugins/cases/public/containers/__mocks__/api.ts @@ -7,7 +7,7 @@ import { ActionLicense, - AllCases, + Cases, BulkUpdateStatus, Case, CasesStatus, @@ -84,7 +84,7 @@ export const getCases = async ({ sortOrder: 'desc', }, signal, -}: FetchCasesProps): Promise => Promise.resolve(allCases); +}: FetchCasesProps): Promise => Promise.resolve(allCases); export const postCase = async (newCase: CasePostRequest, signal: AbortSignal): Promise => Promise.resolve(basicCasePost); diff --git a/x-pack/plugins/cases/public/containers/api.test.tsx b/x-pack/plugins/cases/public/containers/api.test.tsx index 6b8bd6f65bc6d..0b996ec1c7a07 100644 --- a/x-pack/plugins/cases/public/containers/api.test.tsx +++ b/x-pack/plugins/cases/public/containers/api.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { httpServiceMock } from '@kbn/core/public/mocks'; import { KibanaServices } from '../common/lib/kibana'; import { ConnectorTypes, CommentType, CaseStatuses } from '../../common/api'; @@ -20,7 +21,6 @@ import { getActionLicense, getCase, getCases, - getCasesStatus, getCaseUserActions, getReporters, getTags, @@ -54,6 +54,7 @@ import { } from './mock'; import { DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS } from './use_get_cases'; +import { getCasesStatus } from '../api'; const abortCtrl = new AbortController(); const mockKibanaServices = KibanaServices.get as jest.Mock; @@ -246,21 +247,33 @@ describe('Case Configuration API', () => { }); describe('getCasesStatus', () => { + const http = httpServiceMock.createStartContract({ basePath: '' }); + http.get.mockResolvedValue(casesStatusSnake); + beforeEach(() => { fetchMock.mockClear(); - fetchMock.mockResolvedValue(casesStatusSnake); }); + test('should be called with correct check url, method, signal', async () => { - await getCasesStatus(abortCtrl.signal, [SECURITY_SOLUTION_OWNER]); - expect(fetchMock).toHaveBeenCalledWith(`${CASES_URL}/status`, { - method: 'GET', + await getCasesStatus({ + http, + signal: abortCtrl.signal, + query: { owner: [SECURITY_SOLUTION_OWNER] }, + }); + + expect(http.get).toHaveBeenCalledWith(`${CASES_URL}/status`, { signal: abortCtrl.signal, query: { owner: [SECURITY_SOLUTION_OWNER] }, }); }); test('should return correct response', async () => { - const resp = await getCasesStatus(abortCtrl.signal, [SECURITY_SOLUTION_OWNER]); + const resp = await getCasesStatus({ + http, + signal: abortCtrl.signal, + query: { owner: SECURITY_SOLUTION_OWNER }, + }); + expect(resp).toEqual(casesStatus); }); }); diff --git a/x-pack/plugins/cases/public/containers/api.ts b/x-pack/plugins/cases/public/containers/api.ts index a33f0e2501ac0..63a2ea794e065 100644 --- a/x-pack/plugins/cases/public/containers/api.ts +++ b/x-pack/plugins/cases/public/containers/api.ts @@ -6,17 +6,20 @@ */ import { omit } from 'lodash'; - -import { StatusAll, ResolvedCase } from '../../common/ui/types'; +import { + Cases, + FetchCasesProps, + ResolvedCase, + SortFieldCase, + StatusAll, +} from '../../common/ui/types'; import { BulkCreateCommentRequest, CasePatchRequest, CasePostRequest, CaseResponse, CaseResolveResponse, - CasesFindResponse, CasesResponse, - CasesStatusResponse, CaseUserActionsResponse, CommentRequest, CommentType, @@ -28,10 +31,10 @@ import { User, getCaseCommentDeleteUrl, SingleCaseMetricsResponse, + CasesFindResponse, } from '../../common/api'; import { CASE_REPORTERS_URL, - CASE_STATUS_URL, CASE_TAGS_URL, CASES_URL, INTERNAL_BULK_CREATE_ATTACHMENTS_URL, @@ -40,31 +43,25 @@ import { getAllConnectorTypesUrl } from '../../common/utils/connectors_api'; import { KibanaServices } from '../common/lib/kibana'; +import { convertAllCasesToCamel, convertToCamelCase, convertArrayToCamelCase } from '../api/utils'; + import { ActionLicense, - AllCases, BulkUpdateStatus, Case, SingleCaseMetrics, SingleCaseMetricsFeature, - CasesStatus, - FetchCasesProps, - SortFieldCase, CaseUserActions, } from './types'; import { - convertToCamelCase, - convertAllCasesToCamel, - convertArrayToCamelCase, decodeCaseResponse, decodeCasesResponse, - decodeCasesFindResponse, - decodeCasesStatusResponse, decodeCaseUserActionsResponse, decodeCaseResolveResponse, decodeSingleCaseMetricsResponse, } from './utils'; +import { decodeCasesFindResponse } from '../api/decoders'; export const getCase = async ( caseId: string, @@ -99,18 +96,6 @@ export const resolveCase = async ( return convertToCamelCase(decodeCaseResolveResponse(response)); }; -export const getCasesStatus = async ( - signal: AbortSignal, - owner: string[] -): Promise => { - const response = await KibanaServices.get().http.fetch(CASE_STATUS_URL, { - method: 'GET', - signal, - query: { ...(owner.length > 0 ? { owner } : {}) }, - }); - return convertToCamelCase(decodeCasesStatusResponse(response)); -}; - export const getTags = async (signal: AbortSignal, owner: string[]): Promise => { const response = await KibanaServices.get().http.fetch(CASE_TAGS_URL, { method: 'GET', @@ -176,7 +161,7 @@ export const getCases = async ({ sortOrder: 'desc', }, signal, -}: FetchCasesProps): Promise => { +}: FetchCasesProps): Promise => { const query = { reporters: filterOptions.reporters.map((r) => r.username ?? '').filter((r) => r !== ''), tags: filterOptions.tags, @@ -185,11 +170,13 @@ export const getCases = async ({ ...(filterOptions.owner.length > 0 ? { owner: filterOptions.owner } : {}), ...queryParams, }; + const response = await KibanaServices.get().http.fetch(`${CASES_URL}/_find`, { method: 'GET', query: query.status === StatusAll ? omit(query, ['status']) : query, signal, }); + return convertAllCasesToCamel(decodeCasesFindResponse(response)); }; diff --git a/x-pack/plugins/cases/public/containers/configure/api.ts b/x-pack/plugins/cases/public/containers/configure/api.ts index 32202afc34881..53e045882cb7c 100644 --- a/x-pack/plugins/cases/public/containers/configure/api.ts +++ b/x-pack/plugins/cases/public/containers/configure/api.ts @@ -18,14 +18,9 @@ import { } from '../../../common/api'; import { CASE_CONFIGURE_CONNECTORS_URL, CASE_CONFIGURE_URL } from '../../../common/constants'; import { KibanaServices } from '../../common/lib/kibana'; - +import { convertToCamelCase, convertArrayToCamelCase } from '../../api/utils'; import { ApiProps } from '../types'; -import { - convertArrayToCamelCase, - convertToCamelCase, - decodeCaseConfigurationsResponse, - decodeCaseConfigureResponse, -} from '../utils'; +import { decodeCaseConfigurationsResponse, decodeCaseConfigureResponse } from '../utils'; import { CaseConfigure } from './types'; export const fetchConnectors = async ({ signal }: ApiProps): Promise => { diff --git a/x-pack/plugins/cases/public/containers/mock.ts b/x-pack/plugins/cases/public/containers/mock.ts index 8c45fd5b083e0..8a31d8cac2b1e 100644 --- a/x-pack/plugins/cases/public/containers/mock.ts +++ b/x-pack/plugins/cases/public/containers/mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ActionLicense, AllCases, Case, CasesStatus, CaseUserActions, Comment } from './types'; +import { ActionLicense, Cases, Case, CasesStatus, CaseUserActions, Comment } from './types'; import type { ResolvedCase, @@ -330,7 +330,7 @@ export const cases: Case[] = [ caseWithAlertsSyncOff, ]; -export const allCases: AllCases = { +export const allCases: Cases = { cases, page: 1, perPage: 5, diff --git a/x-pack/plugins/cases/public/containers/use_get_cases.tsx b/x-pack/plugins/cases/public/containers/use_get_cases.tsx index 283cdfdf39aa4..d817dc9d9ac0f 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases.tsx @@ -8,7 +8,7 @@ import { useCallback, useEffect, useReducer, useRef } from 'react'; import { DEFAULT_TABLE_ACTIVE_PAGE, DEFAULT_TABLE_LIMIT } from './constants'; import { - AllCases, + Cases, Case, FilterOptions, QueryParams, @@ -21,7 +21,7 @@ import * as i18n from './translations'; import { getCases, patchCase } from './api'; export interface UseGetCasesState { - data: AllCases; + data: Cases; filterOptions: FilterOptions; isError: boolean; loading: string[]; @@ -39,7 +39,7 @@ export type Action = | { type: 'FETCH_INIT'; payload: string } | { type: 'FETCH_CASES_SUCCESS'; - payload: AllCases; + payload: Cases; } | { type: 'FETCH_FAILURE'; payload: string } | { type: 'FETCH_UPDATE_CASE_SUCCESS' } @@ -114,11 +114,11 @@ export const DEFAULT_QUERY_PARAMS: QueryParams = { sortOrder: 'desc', }; -export const initialData: AllCases = { +export const initialData: Cases = { cases: [], - countClosedCases: null, - countInProgressCases: null, - countOpenCases: null, + countClosedCases: 0, + countInProgressCases: 0, + countOpenCases: 0, page: 0, perPage: 0, total: 0, diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx index 2e3e42255145d..3978e944db949 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_status.test.tsx @@ -9,11 +9,11 @@ import React from 'react'; import { renderHook, act } from '@testing-library/react-hooks'; import { useGetCasesStatus, UseGetCasesStatus } from './use_get_cases_status'; import { casesStatus } from './mock'; -import * as api from './api'; +import * as api from '../api'; import { TestProviders } from '../common/mock'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; -jest.mock('./api'); +jest.mock('../api'); jest.mock('../common/lib/kibana'); describe('useGetCasesStatus', () => { @@ -30,9 +30,9 @@ describe('useGetCasesStatus', () => { await act(async () => { expect(result.current).toEqual({ - countClosedCases: null, - countOpenCases: null, - countInProgressCases: null, + countClosedCases: 0, + countOpenCases: 0, + countInProgressCases: 0, isLoading: true, isError: false, fetchCasesStatus: result.current.fetchCasesStatus, @@ -49,12 +49,17 @@ describe('useGetCasesStatus', () => { wrapper: ({ children }) => {children}, } ); + await waitForNextUpdate(); - expect(spyOnGetCasesStatus).toBeCalledWith(abortCtrl.signal, [SECURITY_SOLUTION_OWNER]); + expect(spyOnGetCasesStatus).toBeCalledWith({ + http: expect.anything(), + signal: abortCtrl.signal, + query: { owner: [SECURITY_SOLUTION_OWNER] }, + }); }); }); - it('fetch reporters', async () => { + it('fetch statuses', async () => { await act(async () => { const { result, waitForNextUpdate } = renderHook( () => useGetCasesStatus(), @@ -62,6 +67,7 @@ describe('useGetCasesStatus', () => { wrapper: ({ children }) => {children}, } ); + await waitForNextUpdate(); expect(result.current).toEqual({ countClosedCases: casesStatus.countClosedCases, diff --git a/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx b/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx index 5e21c339856fb..6530236a2fee6 100644 --- a/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx +++ b/x-pack/plugins/cases/public/containers/use_get_cases_status.tsx @@ -8,10 +8,10 @@ import { useCallback, useEffect, useState, useRef } from 'react'; import { useCasesContext } from '../components/cases_context/use_cases_context'; -import { getCasesStatus } from './api'; import * as i18n from './translations'; import { CasesStatus } from './types'; -import { useToasts } from '../common/lib/kibana'; +import { useHttp, useToasts } from '../common/lib/kibana'; +import { getCasesStatus } from '../api'; interface CasesStatusState extends CasesStatus { isLoading: boolean; @@ -19,9 +19,9 @@ interface CasesStatusState extends CasesStatus { } const initialData: CasesStatusState = { - countClosedCases: null, - countInProgressCases: null, - countOpenCases: null, + countClosedCases: 0, + countInProgressCases: 0, + countOpenCases: 0, isLoading: true, isError: false, }; @@ -31,6 +31,7 @@ export interface UseGetCasesStatus extends CasesStatusState { } export const useGetCasesStatus = (): UseGetCasesStatus => { + const http = useHttp(); const { owner } = useCasesContext(); const [casesStatusState, setCasesStatusState] = useState(initialData); const toasts = useToasts(); @@ -47,7 +48,11 @@ export const useGetCasesStatus = (): UseGetCasesStatus => { isLoading: true, }); - const response = await getCasesStatus(abortCtrlRef.current.signal, owner); + const response = await getCasesStatus({ + http, + signal: abortCtrlRef.current.signal, + query: { owner }, + }); if (!isCancelledRef.current) { setCasesStatusState({ diff --git a/x-pack/plugins/cases/public/containers/utils.ts b/x-pack/plugins/cases/public/containers/utils.ts index deafcda2d24ea..a9a0eff53c07c 100644 --- a/x-pack/plugins/cases/public/containers/utils.ts +++ b/x-pack/plugins/cases/public/containers/utils.ts @@ -5,22 +5,17 @@ * 2.0. */ -import { set } from '@elastic/safer-lodash-set'; -import { camelCase, isArray, isObject, transform, snakeCase } from 'lodash'; +import { isObject, transform, snakeCase } from 'lodash'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import { ToastInputFields } from '@kbn/core/public'; import { - CasesFindResponse, - CasesFindResponseRt, CaseResponse, CaseResponseRt, CasesResponse, CasesResponseRt, - CasesStatusResponseRt, - CasesStatusResponse, throwErrors, CasesConfigurationsResponse, CaseConfigurationsResponseRt, @@ -35,7 +30,7 @@ import { SingleCaseMetricsResponse, SingleCaseMetricsResponseRt, } from '../../common/api'; -import { AllCases, Case, UpdateByKey } from './types'; +import { Case, UpdateByKey } from './types'; import * as i18n from './translations'; export const getTypedPayload = (a: unknown): T => a as T; @@ -46,45 +41,6 @@ export const covertToSnakeCase = (obj: Record) => acc[camelKey] = isObject(value) ? covertToSnakeCase(value as Record) : value; }); -export const convertArrayToCamelCase = (arrayOfSnakes: unknown[]): unknown[] => - arrayOfSnakes.reduce((acc: unknown[], value) => { - if (isArray(value)) { - return [...acc, convertArrayToCamelCase(value)]; - } else if (isObject(value)) { - return [...acc, convertToCamelCase(value)]; - } else { - return [...acc, value]; - } - }, []); - -export const convertToCamelCase = (obj: T): U => - Object.entries(obj).reduce((acc, [key, value]) => { - if (isArray(value)) { - set(acc, camelCase(key), convertArrayToCamelCase(value)); - } else if (isObject(value)) { - set(acc, camelCase(key), convertToCamelCase(value)); - } else { - set(acc, camelCase(key), value); - } - return acc; - }, {} as U); - -export const convertAllCasesToCamel = (snakeCases: CasesFindResponse): AllCases => ({ - cases: snakeCases.cases.map((theCase) => convertToCamelCase(theCase)), - countOpenCases: snakeCases.count_open_cases, - countInProgressCases: snakeCases.count_in_progress_cases, - countClosedCases: snakeCases.count_closed_cases, - page: snakeCases.page, - perPage: snakeCases.per_page, - total: snakeCases.total, -}); - -export const decodeCasesStatusResponse = (respCase?: CasesStatusResponse) => - pipe( - CasesStatusResponseRt.decode(respCase), - fold(throwErrors(createToasterPlainError), identity) - ); - export const createToasterPlainError = (message: string) => new ToasterError([message]); export const decodeCaseResponse = (respCase?: CaseResponse) => @@ -105,9 +61,6 @@ export const decodeSingleCaseMetricsResponse = (respCase?: SingleCaseMetricsResp export const decodeCasesResponse = (respCase?: CasesResponse) => pipe(CasesResponseRt.decode(respCase), fold(throwErrors(createToasterPlainError), identity)); -export const decodeCasesFindResponse = (respCases?: CasesFindResponse) => - pipe(CasesFindResponseRt.decode(respCases), fold(throwErrors(createToasterPlainError), identity)); - export const decodeCaseConfigurationsResponse = (respCase?: CasesConfigurationsResponse) => { return pipe( CaseConfigurationsResponseRt.decode(respCase), diff --git a/x-pack/plugins/cases/public/mocks.ts b/x-pack/plugins/cases/public/mocks.ts index f8c0eaaaef7de..ffaf7de51d05f 100644 --- a/x-pack/plugins/cases/public/mocks.ts +++ b/x-pack/plugins/cases/public/mocks.ts @@ -10,7 +10,7 @@ import { CasesUiStart } from './types'; const apiMock: jest.Mocked = { getRelatedCases: jest.fn(), - cases: { find: jest.fn(), getAllCasesMetrics: jest.fn() }, + cases: { find: jest.fn(), getAllCasesMetrics: jest.fn(), getCasesStatus: jest.fn() }, }; const uiMock: jest.Mocked = { diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts index 65cc1de25d345..b8b8199329c95 100644 --- a/x-pack/plugins/cases/public/types.ts +++ b/x-pack/plugins/cases/public/types.ts @@ -21,7 +21,6 @@ import { CasesByAlertId, CasesByAlertIDRequest, CasesFindRequest, - CasesResponse, CasesStatusRequest, CasesStatusResponse, CommentRequestAlertType, @@ -36,6 +35,7 @@ import type { GetCasesProps } from './client/ui/get_cases'; import { GetAllCasesSelectorModalProps } from './client/ui/get_all_cases_selector_modal'; import { GetCreateCaseFlyoutProps } from './client/ui/get_create_case_flyout'; import { GetRecentCasesProps } from './client/ui/get_recent_cases'; +import { Cases, CasesStatus } from '../common/ui'; export interface CasesPluginSetup { security: SecurityPluginSetup; @@ -76,8 +76,9 @@ export interface CasesUiStart { api: { getRelatedCases: (alertId: string, query: CasesByAlertIDRequest) => Promise; cases: { - find: (query: CasesFindRequest) => Promise; + find: (query: CasesFindRequest, signal?: AbortSignal) => Promise; getAllCasesMetrics: (query: CasesStatusRequest) => Promise; + getCasesStatus: (query: CasesStatusRequest, signal?: AbortSignal) => Promise; }; }; ui: { diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx index eb5daeeb374c2..37c48487912e0 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.test.tsx @@ -28,16 +28,17 @@ jest.mock('../../../../common/containers/use_global_time', () => { }); jest.mock('../../../../common/lib/kibana'); -const mockGetAllCasesMetrics = jest.fn(); -mockGetAllCasesMetrics.mockResolvedValue({ - count_open_cases: 1, - count_in_progress_cases: 2, - count_closed_cases: 3, +const mockGetCasesStatus = jest.fn(); +mockGetCasesStatus.mockResolvedValue({ + countOpenCases: 1, + countInProgressCases: 2, + countClosedCases: 3, }); -mockGetAllCasesMetrics.mockResolvedValueOnce({ - count_open_cases: 0, - count_in_progress_cases: 0, - count_closed_cases: 0, + +mockGetCasesStatus.mockResolvedValueOnce({ + countOpenCases: 0, + countInProgressCases: 0, + countClosedCases: 0, }); const mockUseKibana = { @@ -46,7 +47,7 @@ const mockUseKibana = { ...mockCasesContract(), api: { cases: { - getAllCasesMetrics: mockGetAllCasesMetrics, + getCasesStatus: mockGetCasesStatus, }, }, }, diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.tsx index 813fcaa848115..580f91dea6d7d 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/use_cases_by_status.tsx @@ -5,17 +5,12 @@ * 2.0. */ +import { CasesStatus } from '@kbn/cases-plugin/common/ui'; import { useState, useEffect } from 'react'; import { APP_ID } from '../../../../../common/constants'; import { useGlobalTime } from '../../../../common/containers/use_global_time'; import { useKibana } from '../../../../common/lib/kibana'; -export interface CasesCounts { - count_open_cases?: number; - count_in_progress_cases?: number; - count_closed_cases?: number; -} - export interface UseCasesByStatusProps { skip?: boolean; } @@ -37,24 +32,28 @@ export const useCasesByStatus = ({ skip = false }) => { const [updatedAt, setUpdatedAt] = useState(Date.now()); const [isLoading, setIsLoading] = useState(true); - const [casesCounts, setCasesCounts] = useState(null); + const [casesCounts, setCasesCounts] = useState(null); useEffect(() => { let isSubscribed = true; const abortCtrl = new AbortController(); const fetchCases = async () => { try { - const casesResponse = await cases.api.cases.getAllCasesMetrics({ - from, - to, - owner: APP_ID, - }); + const casesResponse = await cases.api.cases.getCasesStatus( + { + from, + to, + owner: APP_ID, + }, + abortCtrl.signal + ); + if (isSubscribed) { setCasesCounts(casesResponse); } } catch (error) { if (isSubscribed) { - setCasesCounts({}); + setCasesCounts(null); } } if (isSubscribed) { @@ -80,14 +79,14 @@ export const useCasesByStatus = ({ skip = false }) => { }, [cases.api.cases, from, skip, to]); return { - closed: casesCounts?.count_closed_cases ?? 0, - inProgress: casesCounts?.count_in_progress_cases ?? 0, + closed: casesCounts?.countClosedCases ?? 0, + inProgress: casesCounts?.countInProgressCases ?? 0, isLoading, - open: casesCounts?.count_open_cases ?? 0, + open: casesCounts?.countOpenCases ?? 0, totalCounts: - (casesCounts?.count_closed_cases ?? 0) + - (casesCounts?.count_in_progress_cases ?? 0) + - (casesCounts?.count_open_cases ?? 0), + (casesCounts?.countClosedCases ?? 0) + + (casesCounts?.countInProgressCases ?? 0) + + (casesCounts?.countOpenCases ?? 0), updatedAt, }; }; From 78d6acef2468d3f5e3187c21bab509f8b98b3885 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Wed, 4 May 2022 11:19:49 +0200 Subject: [PATCH 12/68] Create Manage landing page (#131245) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../security_solution/common/constants.ts | 2 + .../components/landing_links_icons.test.tsx | 70 +++++++ .../components/landing_links_icons.tsx | 82 ++++++++ .../components/landing_links_images.test.tsx | 9 +- .../components/landing_links_images.tsx | 19 +- .../landing_pages/components/translations.ts | 14 -- .../public/landing_pages/icons/blocklist.tsx | 38 ++++ .../landing_pages/icons/endpoint_policies.tsx | 24 +++ .../public/landing_pages/icons/endpoints.tsx | 36 ++++ .../landing_pages/icons/event_filters.tsx | 27 +++ .../landing_pages/icons/exception_lists.tsx | 37 ++++ .../landing_pages/icons/host_isolation.tsx | 39 ++++ .../public/landing_pages/icons/siem_rules.tsx | 58 ++++++ .../icons/trusted_applications.tsx | 44 +++++ .../landing_pages/pages/manage.test.tsx | 78 ++++++++ .../public/landing_pages/pages/manage.tsx | 179 ++++++++++++++++++ .../landing_pages/pages/translations.ts | 4 + .../public/landing_pages/routes.tsx | 13 +- 18 files changed, 746 insertions(+), 27 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx delete mode 100644 x-pack/plugins/security_solution/public/landing_pages/components/translations.ts create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/blocklist.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/endpoint_policies.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/endpoints.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/event_filters.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/exception_lists.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/host_isolation.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/siem_rules.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/icons/trusted_applications.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx create mode 100644 x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index ea2f83a32182e..1d898901455e7 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -121,10 +121,12 @@ export enum SecurityPageName { usersExternalAlerts = 'users-external_alerts', threatHuntingLanding = 'threat-hunting', dashboardsLanding = 'dashboards', + manageLanding = 'manage', } export const THREAT_HUNTING_PATH = '/threat_hunting' as const; export const DASHBOARDS_PATH = '/dashboards' as const; +export const MANAGE_PATH = '/manage' as const; export const TIMELINES_PATH = '/timelines' as const; export const CASES_PATH = '/cases' as const; export const OVERVIEW_PATH = '/overview' as const; diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx new file mode 100644 index 0000000000000..3553f44cc621f --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.test.tsx @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { fireEvent, render } from '@testing-library/react'; +import React from 'react'; +import { SecurityPageName } from '../../app/types'; +import { TestProviders } from '../../common/mock'; +import { LandingLinksIcons, NavItem } from './landing_links_icons'; + +const DEFAULT_NAV_ITEM: NavItem = { + id: SecurityPageName.overview, + label: 'TEST LABEL', + description: 'TEST DESCRIPTION', + icon: 'myTestIcon', +}; + +const mockNavigateTo = jest.fn(); +jest.mock('../../common/lib/kibana', () => { + const originalModule = jest.requireActual('../../common/lib/kibana'); + return { + ...originalModule, + useNavigation: () => ({ + navigateTo: mockNavigateTo, + }), + }; +}); + +jest.mock('../../common/components/link_to', () => { + const originalModule = jest.requireActual('../../common/components/link_to'); + return { + ...originalModule, + useFormatUrl: (id: string) => ({ + formatUrl: jest.fn().mockImplementation((path: string) => `/${id}`), + search: '', + }), + }; +}); + +describe('LandingLinksIcons', () => { + it('renders', () => { + const label = 'test label'; + + const { queryByText } = render( + + + + ); + + expect(queryByText(label)).toBeInTheDocument(); + }); + + it('renders navigation link', () => { + const id = SecurityPageName.administration; + const label = 'myTestLable'; + + const { getByText } = render( + + + + ); + + fireEvent.click(getByText(label)); + + expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/administration' }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx new file mode 100644 index 0000000000000..82a0d2148f683 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_icons.tsx @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + EuiFlexGrid, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiText, + EuiTitle, + IconType, +} from '@elastic/eui'; +import React from 'react'; +import styled from 'styled-components'; +import { SecurityPageName } from '../../app/types'; +import { + SecuritySolutionLinkAnchor, + withSecuritySolutionLink, +} from '../../common/components/links'; + +interface LandingLinksImagesProps { + items: NavItem[]; +} + +export interface NavItem { + id: SecurityPageName; + label: string; + icon: IconType; + description: string; + path?: string; +} + +const Link = styled.a` + color: inherit; +`; + +const SecuritySolutionLink = withSecuritySolutionLink(Link); + +const Description = styled(EuiFlexItem)` + max-width: 22em; +`; + +const StyledEuiTitle = styled(EuiTitle)` + margin-top: ${({ theme }) => theme.eui.paddingSizes.m}; + margin-bottom: ${({ theme }) => theme.eui.paddingSizes.xs}; +`; + +export const LandingLinksIcons: React.FC = ({ items }) => ( + + {items.map(({ label, description, path, id, icon }) => ( + + + + + + + + + +

{label}

+
+
+
+ + + {description} + + +
+
+ ))} +
+); diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx index d326fff1a9262..479de5e13f432 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.test.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { SecurityPageName } from '../../app/types'; import { TestProviders } from '../../common/mock'; import { LandingLinksImages, NavItem } from './landing_links_images'; -import { SCREENSHOT_IMAGE_ALT } from './translations'; const DEFAULT_NAV_ITEM: NavItem = { id: SecurityPageName.overview, @@ -32,7 +31,7 @@ jest.mock('../../common/lib/kibana/kibana_react', () => { }); describe('LandingLinksImages', () => { - test('renders', () => { + it('renders', () => { const label = 'test label'; const { queryByText } = render( @@ -44,16 +43,16 @@ describe('LandingLinksImages', () => { expect(queryByText(label)).toBeInTheDocument(); }); - test('renders image', () => { + it('renders image', () => { const image = 'test_image.jpeg'; const label = 'TEST_LABEL'; - const { getByAltText } = render( + const { getByTestId } = render( ); - expect(getByAltText(SCREENSHOT_IMAGE_ALT(label))).toHaveAttribute('src', image); + expect(getByTestId('LandingLinksImage')).toHaveAttribute('src', image); }); }); diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx index 93366b413e0bc..b6a16da8cdc82 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/components/landing_links_images.tsx @@ -9,7 +9,6 @@ import React from 'react'; import styled from 'styled-components'; import { SecurityPageName } from '../../app/types'; import { withSecuritySolutionLink } from '../../common/components/links'; -import * as i18n from './translations'; interface LandingLinksImagesProps { items: NavItem[]; @@ -23,7 +22,7 @@ export interface NavItem { path?: string; } -const PrimatyEuiTitle = styled(EuiTitle)` +const PrimaryEuiTitle = styled(EuiTitle)` color: ${(props) => props.theme.eui.euiColorPrimary}; `; @@ -49,18 +48,24 @@ const Content = styled(EuiFlexItem)` export const LandingLinksImages: React.FC = ({ items }) => ( {items.map(({ label, description, path, image, id }) => ( - - + + {/* Empty onClick is to force hover style on `EuiPanel` */} {}}> - + - +

{label}

-
+ {description} diff --git a/x-pack/plugins/security_solution/public/landing_pages/components/translations.ts b/x-pack/plugins/security_solution/public/landing_pages/components/translations.ts deleted file mode 100644 index 6f27c3e58cbbc..0000000000000 --- a/x-pack/plugins/security_solution/public/landing_pages/components/translations.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const SCREENSHOT_IMAGE_ALT = (pageName: string) => - i18n.translate('xpack.securitySolution.landing.threatHunting.pageImageAlt', { - values: { pageName }, - defaultMessage: '{pageName} page screenshot', - }); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/blocklist.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/blocklist.tsx new file mode 100644 index 0000000000000..75d272034d668 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/blocklist.tsx @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconBlocklist: React.FC> = ({ ...props }) => ( + + + + + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/endpoint_policies.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/endpoint_policies.tsx new file mode 100644 index 0000000000000..7563ac17045a2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/endpoint_policies.tsx @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconEndpointPolicies: React.FC> = ({ ...props }) => ( + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/endpoints.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/endpoints.tsx new file mode 100644 index 0000000000000..a8254d3996c72 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/endpoints.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconEndpoints: React.FC> = ({ ...props }) => ( + + + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/event_filters.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/event_filters.tsx new file mode 100644 index 0000000000000..78628b7904e8a --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/event_filters.tsx @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconEventFilters: React.FC> = ({ ...props }) => ( + + + + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/exception_lists.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/exception_lists.tsx new file mode 100644 index 0000000000000..a4cc7a25a9785 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/exception_lists.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconExceptionLists: React.FC> = ({ ...props }) => ( + + + + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/host_isolation.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/host_isolation.tsx new file mode 100644 index 0000000000000..c0df14075c958 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/host_isolation.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconHostIsolation: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/siem_rules.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/siem_rules.tsx new file mode 100644 index 0000000000000..fe89c8fb22581 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/siem_rules.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconSiemRules: React.FC> = ({ ...props }) => ( + + + + + + + + + + + + + + + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/icons/trusted_applications.tsx b/x-pack/plugins/security_solution/public/landing_pages/icons/trusted_applications.tsx new file mode 100644 index 0000000000000..7b9f980b7f231 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/icons/trusted_applications.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { SVGProps } from 'react'; +export const IconTrustedApplications: React.FC> = ({ ...props }) => ( + + + + + + + + +); diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx new file mode 100644 index 0000000000000..efb1bcf35c39e --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.test.tsx @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render } from '@testing-library/react'; +import React from 'react'; +import { SecurityPageName } from '../../app/types'; +import { TestProviders } from '../../common/mock'; +import { LandingCategories, NavConfigType } from './manage'; + +const RULES_ITEM_LABEL = 'elastic rules!'; +const EXCEPTIONS_ITEM_LABEL = 'exceptional!'; + +const testConfig: NavConfigType = { + categories: [ + { + label: 'first tests category', + itemIds: [SecurityPageName.rules], + }, + { + label: 'second tests category', + itemIds: [SecurityPageName.exceptions], + }, + ], + items: [ + { + id: SecurityPageName.rules, + label: RULES_ITEM_LABEL, + description: '', + icon: 'testIcon1', + }, + { + id: SecurityPageName.exceptions, + label: EXCEPTIONS_ITEM_LABEL, + description: '', + icon: 'testIcon2', + }, + ], +}; + +describe('LandingCategories', () => { + it('renders items', () => { + const { queryByText } = render( + + + + ); + + expect(queryByText(RULES_ITEM_LABEL)).toBeInTheDocument(); + expect(queryByText(EXCEPTIONS_ITEM_LABEL)).toBeInTheDocument(); + }); + + it('renders items in the same order as defined', () => { + const { queryAllByTestId } = render( + + + + ); + + const renderedItems = queryAllByTestId('LandingItem'); + + expect(renderedItems[0]).toHaveTextContent(EXCEPTIONS_ITEM_LABEL); + expect(renderedItems[1]).toHaveTextContent(RULES_ITEM_LABEL); + }); +}); diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx new file mode 100644 index 0000000000000..da4d25f621305 --- /dev/null +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/manage.tsx @@ -0,0 +1,179 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { EuiHorizontalRule, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { compact } from 'lodash/fp'; +import React from 'react'; +import styled from 'styled-components'; +import { + BLOCKLIST, + ENDPOINTS, + EVENT_FILTERS, + EXCEPTIONS, + TRUSTED_APPLICATIONS, +} from '../../app/translations'; +import { SecurityPageName } from '../../app/types'; +import { HeaderPage } from '../../common/components/header_page'; +import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; +import { SpyRoute } from '../../common/utils/route/spy_routes'; +import { LandingLinksIcons, NavItem } from '../components/landing_links_icons'; +import { IconBlocklist } from '../icons/blocklist'; +import { IconEndpoints } from '../icons/endpoints'; +import { IconEndpointPolicies } from '../icons/endpoint_policies'; +import { IconEventFilters } from '../icons/event_filters'; +import { IconExceptionLists } from '../icons/exception_lists'; +import { IconHostIsolation } from '../icons/host_isolation'; +import { IconSiemRules } from '../icons/siem_rules'; +import { IconTrustedApplications } from '../icons/trusted_applications'; +import { MANAGE_PAGE_TITLE } from './translations'; + +// TODO +const FIX_ME_TEMPORARY_DESCRIPTION = 'Description here'; + +export interface NavConfigType { + items: NavItem[]; + categories: Array<{ label: string; itemIds: SecurityPageName[] }>; +} + +const config: NavConfigType = { + categories: [ + { + label: i18n.translate('xpack.securitySolution.landing.threatHunting.siemTitle', { + defaultMessage: 'SIEM', + }), + itemIds: [SecurityPageName.rules, SecurityPageName.exceptions], + }, + { + label: i18n.translate('xpack.securitySolution.landing.threatHunting.endpointsTitle', { + defaultMessage: 'ENDPOINTS', + }), + itemIds: [ + SecurityPageName.endpoints, + SecurityPageName.policies, + SecurityPageName.trustedApps, + SecurityPageName.eventFilters, + SecurityPageName.blocklist, + SecurityPageName.hostIsolationExceptions, + ], + }, + ], + items: [ + { + id: SecurityPageName.rules, + label: i18n.translate('xpack.securitySolution.landing.manage.rulesLabel', { + defaultMessage: 'SIEM rules', + }), + description: FIX_ME_TEMPORARY_DESCRIPTION, + icon: IconSiemRules, + }, + { + id: SecurityPageName.exceptions, + label: EXCEPTIONS, + description: FIX_ME_TEMPORARY_DESCRIPTION, + icon: IconExceptionLists, + }, + { + id: SecurityPageName.endpoints, + label: ENDPOINTS, + description: i18n.translate('xpack.securitySolution.landing.manage.endpointsDescription', { + defaultMessage: 'Hosts running endpoint security', + }), + icon: IconEndpoints, + }, + { + id: SecurityPageName.policies, + label: i18n.translate('xpack.securitySolution.landing.manage.endpointPoliceLabel', { + defaultMessage: 'Endpoint policies', + }), + description: FIX_ME_TEMPORARY_DESCRIPTION, + icon: IconEndpointPolicies, + }, + { + id: SecurityPageName.trustedApps, + label: TRUSTED_APPLICATIONS, + description: i18n.translate( + 'xpack.securitySolution.landing.manage.trustedApplicationsDescription', + { + defaultMessage: + 'Improve performance or alleviate conflicts with other applications running on your hosts', + } + ), + icon: IconTrustedApplications, + }, + { + id: SecurityPageName.eventFilters, + label: EVENT_FILTERS, + description: i18n.translate('xpack.securitySolution.landing.manage.eventFiltersDescription', { + defaultMessage: 'Exclude unwanted applications from running on your hosts', + }), + icon: IconEventFilters, + }, + { + id: SecurityPageName.blocklist, + label: BLOCKLIST, + description: FIX_ME_TEMPORARY_DESCRIPTION, + icon: IconBlocklist, + }, + { + id: SecurityPageName.hostIsolationExceptions, + label: i18n.translate('xpack.securitySolution.landing.manage.hostIsolationLabel', { + defaultMessage: 'Host isolation IP exceptions', + }), + description: i18n.translate( + 'xpack.securitySolution.landing.manage.hostIsolationDescription', + { + defaultMessage: 'Allow isolated hosts to communicate with specific IPs', + } + ), + + icon: IconHostIsolation, + }, + ], +}; + +export const ManageLandingPage = () => ( + + + + + +); + +const StyledEuiHorizontalRule = styled(EuiHorizontalRule)` + margin-top: ${({ theme }) => theme.eui.paddingSizes.m}; + margin-bottom: ${({ theme }) => theme.eui.paddingSizes.l}; +`; + +const getNavItembyId = (navConfig: NavConfigType) => (itemId: string) => + navConfig.items.find(({ id }: NavItem) => id === itemId); + +const navItemsFromIds = (itemIds: SecurityPageName[], navConfig: NavConfigType) => + compact(itemIds.map(getNavItembyId(navConfig))); + +export const LandingCategories = React.memo(({ navConfig }: { navConfig: NavConfigType }) => { + return ( + <> + {navConfig.categories.map(({ label, itemIds }, index) => ( +
+ {index > 0 && ( + <> + + + + )} + +

{label}

+
+ + +
+ ))} + + ); +}); + +LandingCategories.displayName = 'LandingCategories'; diff --git a/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts b/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts index 398bc3fc89fd8..13a2396201cc5 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts +++ b/x-pack/plugins/security_solution/public/landing_pages/pages/translations.ts @@ -20,3 +20,7 @@ export const DASHBOARDS_PAGE_TITLE = i18n.translate( defaultMessage: 'Dashboards', } ); + +export const MANAGE_PAGE_TITLE = i18n.translate('xpack.securitySolution.landing.manage.pageTitle', { + defaultMessage: 'Manage', +}); diff --git a/x-pack/plugins/security_solution/public/landing_pages/routes.tsx b/x-pack/plugins/security_solution/public/landing_pages/routes.tsx index d849b4c22cf7e..af8ce9dbdaf2a 100644 --- a/x-pack/plugins/security_solution/public/landing_pages/routes.tsx +++ b/x-pack/plugins/security_solution/public/landing_pages/routes.tsx @@ -9,9 +9,10 @@ import React from 'react'; import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; import { SecurityPageName, SecuritySubPluginRoutes } from '../app/types'; -import { DASHBOARDS_PATH, THREAT_HUNTING_PATH } from '../../common/constants'; +import { DASHBOARDS_PATH, MANAGE_PATH, THREAT_HUNTING_PATH } from '../../common/constants'; import { ThreatHuntingLandingPage } from './pages/threat_hunting'; import { DashboardsLandingPage } from './pages/dashboards'; +import { ManageLandingPage } from './pages/manage'; export const ThreatHuntingRoutes = () => ( @@ -25,6 +26,12 @@ export const DashboardRoutes = () => ( ); +export const ManageRoutes = () => ( + + + +); + export const routes: SecuritySubPluginRoutes = [ { path: THREAT_HUNTING_PATH, @@ -34,4 +41,8 @@ export const routes: SecuritySubPluginRoutes = [ path: DASHBOARDS_PATH, render: DashboardRoutes, }, + { + path: MANAGE_PATH, + render: ManageRoutes, + }, ]; From 5793d1949fb92405569237bb7e40fd1ebcb461b1 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Wed, 4 May 2022 11:30:39 +0200 Subject: [PATCH 13/68] [Discover] Add project tree to README.md (#131480) --- src/plugins/discover/README.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/plugins/discover/README.md b/src/plugins/discover/README.md index a914d651eef35..6537a830c46a9 100644 --- a/src/plugins/discover/README.md +++ b/src/plugins/discover/README.md @@ -1 +1,32 @@ -Contains the Discover application and the saved search embeddable. \ No newline at end of file +# Discover + +Contains the Discover application and the saved search embeddable. + +## Project tree + +### [src/plugins/discover/public](./public) + +Contains all the client-only code. When you initially load Discover, [public/application/main](./public/application/main) is executed and displayed. + +* **[/application](./public/application)** \ +One folder for every "route", each folder contains files and folders related only to this route. + * **[/context](./public/application/context)** (Also known as "Surrounding documents" - historically this has been a separate plugin) + * **[/doc](./public/application/doc)** (Also known as "Single document" - historically this has been a separate plugin) + * **[/main](./public/application/main)** (Main part of Discover containing the document table) + * **[/not_found](./public/application/not_found)** (Rendered when a route can't be found) + * **[/view_alert](./public/application/view_alert)** (Forwarding links in alert notifications) +* **[/components](./public/components)** (All React components used in more than just one app) +* **[/embeddable](./public/embeddable)** (Code related to the saved search embeddable, rendered on dashboards) +* **[/services](./public/services)** (Services either for external or internal use) +* **[/utils](./public/utils)** (All utility functions used across more than one application) + +### [src/plugins/discover/server](./server) + +Contains all the server-only code. + +### [src/plugins/discover/common](./common)) + +Contains all code shared by client and server. + + + From c9d84e32f27c4f5b9ff48d06165389f6a9fb707d Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Wed, 4 May 2022 11:47:56 +0200 Subject: [PATCH 14/68] [Discover] Migrate legacy searchSource fetch() to fetch$() (#129104) --- .../application/context/services/_stubs.ts | 42 ++++++++++++------- .../context/services/anchor.test.ts | 11 +++-- .../application/context/services/anchor.ts | 7 ++-- .../services/context.predecessors.test.ts | 4 +- .../services/context.successors.test.ts | 4 +- .../context/utils/fetch_hits_in_interval.ts | 10 +++-- 6 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/plugins/discover/public/application/context/services/_stubs.ts b/src/plugins/discover/public/application/context/services/_stubs.ts index df53523c367ae..b37c1ecf4efbf 100644 --- a/src/plugins/discover/public/application/context/services/_stubs.ts +++ b/src/plugins/discover/public/application/context/services/_stubs.ts @@ -8,7 +8,9 @@ import sinon from 'sinon'; import moment from 'moment'; - +import { of } from 'rxjs'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { IKibanaSearchResponse } from '@kbn/data-plugin/common'; import { EsHitRecordList } from '../../types'; type SortHit = { @@ -21,6 +23,23 @@ type SortHit = { * A stubbed search source with a `fetch` method that returns all of `_stubHits`. */ export function createSearchSourceStub(hits: EsHitRecordList, timeField?: string) { + const requestResult = { + id: 'Fjk5bndxTHJWU2FldVRVQ0tYR0VqOFEcRWtWNDhOdG5SUzJYcFhONVVZVTBJQToxMDMwOQ==', + rawResponse: { + took: 2, + timed_out: false, + _shards: { total: 1, successful: 1, skipped: 0, failed: 0 }, + hits: { + hits, + total: hits.length, + }, + }, + isPartial: false, + isRunning: false, + total: 1, + loaded: 1, + isRestored: false, + } as unknown as IKibanaSearchResponse>; // eslint-disable-next-line @typescript-eslint/no-explicit-any const searchSourceStub: any = { _stubHits: hits, @@ -36,14 +55,7 @@ export function createSearchSourceStub(hits: EsHitRecordList, timeField?: string const previousSetCall = searchSourceStub.setField.withArgs(key).lastCall; return previousSetCall ? previousSetCall.args[1] : null; }), - fetch: sinon.spy(() => - Promise.resolve({ - hits: { - hits: searchSourceStub._stubHits, - total: searchSourceStub._stubHits.length, - }, - }) - ), + fetch$: sinon.spy(() => of(requestResult)), }; return searchSourceStub; } @@ -54,7 +66,7 @@ export function createSearchSourceStub(hits: EsHitRecordList, timeField?: string export function createContextSearchSourceStub(timeFieldName: string) { const searchSourceStub = createSearchSourceStub([], timeFieldName); - searchSourceStub.fetch = sinon.spy(() => { + searchSourceStub.fetch$ = sinon.spy(() => { const timeField: keyof SortHit = searchSourceStub._stubTimeField; const lastQuery = searchSourceStub.setField.withArgs('query').lastCall.args[1]; const timeRange = lastQuery.query.bool.must.constant_score.filter.range[timeField]; @@ -72,10 +84,12 @@ export function createContextSearchSourceStub(timeFieldName: string) { ) .sort(sortFunction); - return Promise.resolve({ - hits: { - hits: filteredHits, - total: filteredHits.length, + return of({ + rawResponse: { + hits: { + hits: filteredHits, + total: filteredHits.length, + }, }, }); }); diff --git a/src/plugins/discover/public/application/context/services/anchor.test.ts b/src/plugins/discover/public/application/context/services/anchor.test.ts index 30ff0b039d3e7..ab613fb71cc6d 100644 --- a/src/plugins/discover/public/application/context/services/anchor.test.ts +++ b/src/plugins/discover/public/application/context/services/anchor.test.ts @@ -27,12 +27,12 @@ describe('context app', function () { searchSourceStub = createSearchSourceStub([{ _id: 'hit1' }] as unknown as EsHitRecordList); }); - it('should use the `fetch` method of the SearchSource', function () { + it('should use the `fetch$` method of the SearchSource', function () { return fetchAnchor('id', indexPattern, searchSourceStub, [ { '@timestamp': SortDirection.desc }, { _doc: SortDirection.desc }, ]).then(() => { - expect(searchSourceStub.fetch.calledOnce).toBe(true); + expect(searchSourceStub.fetch$.calledOnce).toBe(true); }); }); @@ -142,7 +142,7 @@ describe('context app', function () { }); it('should reject with an error when no hits were found', function () { - searchSourceStub._stubHits = []; + searchSourceStub = createSearchSourceStub([] as unknown as EsHitRecordList); return fetchAnchor('id', indexPattern, searchSourceStub, [ { '@timestamp': SortDirection.desc }, @@ -158,7 +158,10 @@ describe('context app', function () { }); it('should return the first hit after adding an anchor marker', function () { - searchSourceStub._stubHits = [{ property1: 'value1' }, { property2: 'value2' }]; + searchSourceStub = createSearchSourceStub([ + { property1: 'value1' }, + { property2: 'value2' }, + ] as unknown as EsHitRecordList); return fetchAnchor('id', indexPattern, searchSourceStub, [ { '@timestamp': SortDirection.desc }, diff --git a/src/plugins/discover/public/application/context/services/anchor.ts b/src/plugins/discover/public/application/context/services/anchor.ts index a55ed2506537f..28d2298513aa7 100644 --- a/src/plugins/discover/public/application/context/services/anchor.ts +++ b/src/plugins/discover/public/application/context/services/anchor.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - +import { lastValueFrom } from 'rxjs'; import { i18n } from '@kbn/i18n'; import { ISearchSource, EsQuerySortValue } from '@kbn/data-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; @@ -19,9 +19,8 @@ export async function fetchAnchor( useNewFieldsApi: boolean = false ): Promise { updateSearchSource(searchSource, anchorId, sort, useNewFieldsApi, indexPattern); - - const response = await searchSource.fetch(); - const doc = response.hits?.hits?.[0]; + const { rawResponse } = await lastValueFrom(await searchSource.fetch$()); + const doc = rawResponse.hits?.hits?.[0]; if (!doc) { throw new Error( diff --git a/src/plugins/discover/public/application/context/services/context.predecessors.test.ts b/src/plugins/discover/public/application/context/services/context.predecessors.test.ts index 90fe6bfd7e26b..3b04e7801da4d 100644 --- a/src/plugins/discover/public/application/context/services/context.predecessors.test.ts +++ b/src/plugins/discover/public/application/context/services/context.predecessors.test.ts @@ -89,7 +89,7 @@ describe('context predecessors', function () { return fetchPredecessors(ANCHOR_TIMESTAMP_3000, MS_PER_DAY * 3000, '_doc', 0, 3).then( (hits: EsHitRecordList) => { - expect(mockSearchSource.fetch.calledOnce).toBe(true); + expect(mockSearchSource.fetch$.calledOnce).toBe(true); expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 3)); } ); @@ -234,7 +234,7 @@ describe('context predecessors', function () { (hits: EsHitRecordList) => { const setFieldsSpy = mockSearchSource.setField.withArgs('fields'); const removeFieldsSpy = mockSearchSource.removeField.withArgs('fieldsFromSource'); - expect(mockSearchSource.fetch.calledOnce).toBe(true); + expect(mockSearchSource.fetch$.calledOnce).toBe(true); expect(removeFieldsSpy.calledOnce).toBe(true); expect(setFieldsSpy.calledOnce).toBe(true); expect(hits).toEqual(mockSearchSource._stubHits.slice(0, 3)); diff --git a/src/plugins/discover/public/application/context/services/context.successors.test.ts b/src/plugins/discover/public/application/context/services/context.successors.test.ts index 0c32c3b7ed213..08e5013f1ed80 100644 --- a/src/plugins/discover/public/application/context/services/context.successors.test.ts +++ b/src/plugins/discover/public/application/context/services/context.successors.test.ts @@ -88,7 +88,7 @@ describe('context successors', function () { return fetchSuccessors(ANCHOR_TIMESTAMP_3000, MS_PER_DAY * 3000, '_doc', 0, 3).then( (hits) => { - expect(mockSearchSource.fetch.calledOnce).toBe(true); + expect(mockSearchSource.fetch$.calledOnce).toBe(true); expect(hits).toEqual(mockSearchSource._stubHits.slice(-3)); } ); @@ -225,7 +225,7 @@ describe('context successors', function () { return fetchSuccessors(ANCHOR_TIMESTAMP_3000, MS_PER_DAY * 3000, '_doc', 0, 3).then( (hits) => { - expect(mockSearchSource.fetch.calledOnce).toBe(true); + expect(mockSearchSource.fetch$.calledOnce).toBe(true); expect(hits).toEqual(mockSearchSource._stubHits.slice(-3)); const setFieldsSpy = mockSearchSource.setField.withArgs('fields'); const removeFieldsSpy = mockSearchSource.removeField.withArgs('fieldsFromSource'); diff --git a/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts b/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts index 1d990f4ae8359..3547127c1ab8c 100644 --- a/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts +++ b/src/plugins/discover/public/application/context/utils/fetch_hits_in_interval.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - +import { lastValueFrom } from 'rxjs'; import { ISearchSource, EsQuerySortValue, SortDirection } from '@kbn/data-plugin/public'; import { convertTimeValueToIso } from './date_conversion'; import { IntervalValue } from './generate_intervals'; @@ -48,7 +48,7 @@ export async function fetchHitsInInterval( if (stop) { range[sortDir === SortDirection.asc ? 'lte' : 'gte'] = convertTimeValueToIso(stop, nanosValue); } - const response = await searchSource + const fetch$ = searchSource .setField('size', maxCount) .setField('query', { query: { @@ -74,8 +74,10 @@ export async function fetchHitsInInterval( .setField('searchAfter', searchAfter) .setField('sort', sort) .setField('version', true) - .fetch(); + .fetch$(); + + const { rawResponse } = await lastValueFrom(fetch$); // TODO: There's a difference in the definition of SearchResponse and EsHitRecord - return (response.hits?.hits as unknown as EsHitRecord[]) || []; + return (rawResponse.hits?.hits as unknown as EsHitRecord[]) || []; } From 9aeb1fb44616e1bb4b0033456f06e30618a4377f Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Wed, 4 May 2022 11:58:01 +0200 Subject: [PATCH 15/68] Update search session config docs (#131411) --- docs/settings/search-sessions-settings.asciidoc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/settings/search-sessions-settings.asciidoc b/docs/settings/search-sessions-settings.asciidoc index 7b03cd23a9023..7628ecfb397e1 100644 --- a/docs/settings/search-sessions-settings.asciidoc +++ b/docs/settings/search-sessions-settings.asciidoc @@ -7,26 +7,26 @@ Configure the search session settings in your `kibana.yml` configuration file. -`xpack.data_enhanced.search.sessions.enabled` {ess-icon}:: +`data.search.sessions.enabled` {ess-icon}:: Set to `true` (default) to enable search sessions. -`xpack.data_enhanced.search.sessions.trackingInterval` {ess-icon}:: +`data.search.sessions.trackingInterval` {ess-icon}:: The frequency for updating the state of a search session. The default is `10s`. -`xpack.data_enhanced.search.sessions.pageSize` {ess-icon}:: +`data.search.sessions.pageSize` {ess-icon}:: How many search sessions {kib} processes at once while monitoring session progress. The default is `100`. -`xpack.data_enhanced.search.sessions.notTouchedTimeout` {ess-icon}:: +`data.search.sessions.notTouchedTimeout` {ess-icon}:: How long {kib} stores search results from unsaved sessions, after the last search in the session completes. The default is `5m`. -`xpack.data_enhanced.search.sessions.notTouchedInProgressTimeout` {ess-icon}:: +`data.search.sessions.notTouchedInProgressTimeout` {ess-icon}:: How long a search session can run after a user navigates away without saving a session. The default is `1m`. -`xpack.data_enhanced.search.sessions.maxUpdateRetries` {ess-icon}:: +`data.search.sessions.maxUpdateRetries` {ess-icon}:: How many retries {kib} can perform while attempting to save a search session. The default is `3`. -`xpack.data_enhanced.search.sessions.defaultExpiration` {ess-icon}:: +`data.search.sessions.defaultExpiration` {ess-icon}:: How long search session results are stored before they are deleted. Extending a search session resets the expiration by the same value. The default is `7d`. From c9b424c8a2d01727e633f4b949d09c02d7017b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Wed, 4 May 2022 12:32:18 +0200 Subject: [PATCH 16/68] [EBT] Fix flaky test (#131494) --- .../analytics_client/analytics_client.test.ts | 770 +++++++++--------- 1 file changed, 397 insertions(+), 373 deletions(-) diff --git a/packages/analytics/client/src/analytics_client/analytics_client.test.ts b/packages/analytics/client/src/analytics_client/analytics_client.test.ts index 1e8d5aa5445c0..cbb1b4131b4a4 100644 --- a/packages/analytics/client/src/analytics_client/analytics_client.test.ts +++ b/packages/analytics/client/src/analytics_client/analytics_client.test.ts @@ -9,6 +9,7 @@ // eslint-disable-next-line max-classes-per-file import type { Observable } from 'rxjs'; import { BehaviorSubject, firstValueFrom, lastValueFrom, Subject } from 'rxjs'; +import { fakeSchedulers } from 'rxjs-marbles/jest'; import type { MockedLogger } from '@kbn/logging-mocks'; import { loggerMock } from '@kbn/logging-mocks'; import { AnalyticsClient } from './analytics_client'; @@ -17,14 +18,12 @@ import { shippersMock } from '../shippers/mocks'; import type { EventContext, TelemetryCounter } from '../events'; import { TelemetryCounterType } from '../events'; -const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - -// FLAKY: https://github.com/elastic/kibana/issues/131369 -describe.skip('AnalyticsClient', () => { +describe('AnalyticsClient', () => { let analyticsClient: AnalyticsClient; let logger: MockedLogger; beforeEach(() => { + jest.useFakeTimers(); logger = loggerMock.create(); analyticsClient = new AnalyticsClient({ logger, @@ -33,6 +32,10 @@ describe.skip('AnalyticsClient', () => { }); }); + afterEach(() => { + jest.useRealTimers(); + }); + describe('registerEventType', () => { test('successfully registers a event type', () => { analyticsClient.registerEventType({ @@ -311,54 +314,63 @@ describe.skip('AnalyticsClient', () => { expect(optIn).toHaveBeenCalledWith(true); }); - test('Spreads the context updates to the shipper (only after opt-in)', async () => { - const extendContextMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper, { extendContextMock }); - expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in - analyticsClient.optIn({ global: { enabled: true } }); - await delay(10); - expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context - - const context$ = new Subject<{ a_field: boolean }>(); - analyticsClient.registerContextProvider({ - name: 'contextProviderA', - schema: { - a_field: { - type: 'boolean', - _meta: { - description: 'a_field description', + test( + 'Spreads the context updates to the shipper (only after opt-in)', + fakeSchedulers(async (advance) => { + const extendContextMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper, { extendContextMock }); + expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in + analyticsClient.optIn({ global: { enabled: true } }); + advance(10); + expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context + + const context$ = new Subject<{ a_field: boolean }>(); + analyticsClient.registerContextProvider({ + name: 'contextProviderA', + schema: { + a_field: { + type: 'boolean', + _meta: { + description: 'a_field description', + }, }, }, - }, - context$, - }); - - context$.next({ a_field: true }); - expect(extendContextMock).toHaveBeenCalledWith({ a_field: true }); // After update - }); - - test('Does not spread the context if opt-in === false', async () => { - const extendContextMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper, { extendContextMock }); - expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in - analyticsClient.optIn({ global: { enabled: false } }); - await delay(10); - expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in - }); + context$, + }); - test('Handles errors in the shipper', async () => { - const extendContextMock = jest.fn().mockImplementation(() => { - throw new Error('Something went terribly wrong'); - }); - analyticsClient.registerShipper(MockedShipper, { extendContextMock }); - analyticsClient.optIn({ global: { enabled: true } }); - await delay(10); - expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context - expect(logger.warn).toHaveBeenCalledWith( - `Shipper "${MockedShipper.shipperName}" failed to extend the context`, - expect.any(Error) - ); - }); + context$.next({ a_field: true }); + expect(extendContextMock).toHaveBeenCalledWith({ a_field: true }); // After update + }) + ); + + test( + 'Does not spread the context if opt-in === false', + fakeSchedulers(async (advance) => { + const extendContextMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper, { extendContextMock }); + expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in + analyticsClient.optIn({ global: { enabled: false } }); + advance(10); + expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in + }) + ); + + test( + 'Handles errors in the shipper', + fakeSchedulers(async (advance) => { + const extendContextMock = jest.fn().mockImplementation(() => { + throw new Error('Something went terribly wrong'); + }); + analyticsClient.registerShipper(MockedShipper, { extendContextMock }); + analyticsClient.optIn({ global: { enabled: true } }); + advance(10); + expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context + expect(logger.warn).toHaveBeenCalledWith( + `Shipper "${MockedShipper.shipperName}" failed to extend the context`, + expect.any(Error) + ); + }) + ); }); describe('registerContextProvider', () => { @@ -819,86 +831,89 @@ describe.skip('AnalyticsClient', () => { ]); }); - test('Sends events from the internal queue when there are shippers and an opt-in response is true', async () => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - // As proven in the previous test, the events are still enqueued. - // Let's register a shipper and opt-in to test the dequeue logic. - const reportEventsMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); - analyticsClient.optIn({ global: { enabled: true } }); - await delay(10); - - expect(reportEventsMock).toHaveBeenCalledTimes(2); - expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'a' }, - timestamp: expect.any(String), - }, - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'b' }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock).toHaveBeenNthCalledWith(2, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - - // Expect 3 enqueued events, and 2 sent_to_shipper batched requests - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-a', - code: 'OK', - count: 2, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }); + test( + 'Sends events from the internal queue when there are shippers and an opt-in response is true', + fakeSchedulers(async (advance) => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + // As proven in the previous test, the events are still enqueued. + // Let's register a shipper and opt-in to test the dequeue logic. + const reportEventsMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); + analyticsClient.optIn({ global: { enabled: true } }); + advance(10); + + expect(reportEventsMock).toHaveBeenCalledTimes(2); + expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'a' }, + timestamp: expect.any(String), + }, + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'b' }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock).toHaveBeenNthCalledWith(2, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + + // Expect 3 enqueued events, and 2 sent_to_shipper batched requests + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-a', + code: 'OK', + count: 2, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }) + ); test('Discards events from the internal queue when there are shippers and an opt-in response is false', async () => { const telemetryCounterPromise = lastValueFrom( @@ -942,250 +957,259 @@ describe.skip('AnalyticsClient', () => { ]); }); - test('Discards only one type of the enqueued events based on event_type config', async () => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 1), toArray()) // Waiting for 3 enqueued + 1 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - const reportEventsMock = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); - analyticsClient.optIn({ - global: { enabled: true }, - event_types: { ['event-type-a']: { enabled: false } }, - }); - await delay(10); - - expect(reportEventsMock).toHaveBeenCalledTimes(1); - expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - - // Expect 3 enqueued events, and 1 sent_to_shipper batched request - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }); - - test('Discards the event at the shipper level (for a specific event)', async () => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - // Register 2 shippers and set 1 of them as disabled for event-type-a - const reportEventsMock1 = jest.fn(); - const reportEventsMock2 = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); - analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); - analyticsClient.optIn({ - global: { enabled: true }, - event_types: { - ['event-type-a']: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, - }, - }); - await delay(10); - - expect(reportEventsMock1).toHaveBeenCalledTimes(2); - expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'a' }, - timestamp: expect.any(String), - }, - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'b' }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock2).toHaveBeenCalledTimes(1); - expect(reportEventsMock2).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - - // Expect 3 enqueued events, and 2 sent_to_shipper batched requests - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-a', - code: 'OK', - count: 2, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }); - - test('Discards all the events at the shipper level (globally disabled)', async () => { - const telemetryCounterPromise = lastValueFrom( - analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events - ); - - // Send multiple events of 1 type to test the grouping logic as well - analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); - analyticsClient.reportEvent('event-type-b', { b_field: 100 }); - analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); - - // Register 2 shippers and set 1 of them as globally disabled - const reportEventsMock1 = jest.fn(); - const reportEventsMock2 = jest.fn(); - analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); - analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); - analyticsClient.optIn({ - global: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, - event_types: { - ['event-type-a']: { enabled: true }, - }, - }); - await delay(10); - - expect(reportEventsMock1).toHaveBeenCalledTimes(2); - expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'a' }, - timestamp: expect.any(String), - }, - { - context: {}, - event_type: 'event-type-a', - properties: { a_field: 'b' }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ - { - context: {}, - event_type: 'event-type-b', - properties: { b_field: 100 }, - timestamp: expect.any(String), - }, - ]); - expect(reportEventsMock2).toHaveBeenCalledTimes(0); - - // Expect 3 enqueued events, and 2 sent_to_shipper batched requests - await expect(telemetryCounterPromise).resolves.toEqual([ - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-b', - code: 'enqueued', - count: 1, - }, - { - type: 'enqueued', - source: 'client', - event_type: 'event-type-a', - code: 'enqueued', - count: 1, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-a', - code: 'OK', - count: 2, - }, - { - type: 'sent_to_shipper', - source: 'client', - event_type: 'event-type-b', - code: 'OK', - count: 1, - }, - ]); - }); + test( + 'Discards only one type of the enqueued events based on event_type config', + fakeSchedulers(async (advance) => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 1), toArray()) // Waiting for 3 enqueued + 1 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + const reportEventsMock = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock }); + analyticsClient.optIn({ + global: { enabled: true }, + event_types: { ['event-type-a']: { enabled: false } }, + }); + advance(10); + + expect(reportEventsMock).toHaveBeenCalledTimes(1); + expect(reportEventsMock).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + + // Expect 3 enqueued events, and 1 sent_to_shipper batched request + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }) + ); + + test( + 'Discards the event at the shipper level (for a specific event)', + fakeSchedulers(async (advance) => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + // Register 2 shippers and set 1 of them as disabled for event-type-a + const reportEventsMock1 = jest.fn(); + const reportEventsMock2 = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); + analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); + analyticsClient.optIn({ + global: { enabled: true }, + event_types: { + ['event-type-a']: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, + }, + }); + advance(10); + + expect(reportEventsMock1).toHaveBeenCalledTimes(2); + expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'a' }, + timestamp: expect.any(String), + }, + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'b' }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock2).toHaveBeenCalledTimes(1); + expect(reportEventsMock2).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + + // Expect 3 enqueued events, and 2 sent_to_shipper batched requests + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-a', + code: 'OK', + count: 2, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }) + ); + + test( + 'Discards all the events at the shipper level (globally disabled)', + fakeSchedulers(async (advance) => { + const telemetryCounterPromise = lastValueFrom( + analyticsClient.telemetryCounter$.pipe(take(3 + 2), toArray()) // Waiting for 3 enqueued + 2 batch-shipped events + ); + + // Send multiple events of 1 type to test the grouping logic as well + analyticsClient.reportEvent('event-type-a', { a_field: 'a' }); + analyticsClient.reportEvent('event-type-b', { b_field: 100 }); + analyticsClient.reportEvent('event-type-a', { a_field: 'b' }); + + // Register 2 shippers and set 1 of them as globally disabled + const reportEventsMock1 = jest.fn(); + const reportEventsMock2 = jest.fn(); + analyticsClient.registerShipper(MockedShipper1, { reportEventsMock: reportEventsMock1 }); + analyticsClient.registerShipper(MockedShipper2, { reportEventsMock: reportEventsMock2 }); + analyticsClient.optIn({ + global: { enabled: true, shippers: { [MockedShipper2.shipperName]: false } }, + event_types: { + ['event-type-a']: { enabled: true }, + }, + }); + advance(10); + + expect(reportEventsMock1).toHaveBeenCalledTimes(2); + expect(reportEventsMock1).toHaveBeenNthCalledWith(1, [ + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'a' }, + timestamp: expect.any(String), + }, + { + context: {}, + event_type: 'event-type-a', + properties: { a_field: 'b' }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock1).toHaveBeenNthCalledWith(2, [ + { + context: {}, + event_type: 'event-type-b', + properties: { b_field: 100 }, + timestamp: expect.any(String), + }, + ]); + expect(reportEventsMock2).toHaveBeenCalledTimes(0); + + // Expect 3 enqueued events, and 2 sent_to_shipper batched requests + await expect(telemetryCounterPromise).resolves.toEqual([ + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-b', + code: 'enqueued', + count: 1, + }, + { + type: 'enqueued', + source: 'client', + event_type: 'event-type-a', + code: 'enqueued', + count: 1, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-a', + code: 'OK', + count: 2, + }, + { + type: 'sent_to_shipper', + source: 'client', + event_type: 'event-type-b', + code: 'OK', + count: 1, + }, + ]); + }) + ); test('Discards incoming events when opt-in response is false', async () => { // Set OptIn and shipper first to test the "once-set up" scenario From df225b213b188c81888141cee2ec191424fc0649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Wed, 4 May 2022 12:41:00 +0200 Subject: [PATCH 17/68] [Security Solution] [Endpoint] Update blocklist flyout license banner copy (#130561) * Add missing period at the end of the sentence * Copy update due old pr comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../public/management/pages/blocklist/view/blocklist.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx b/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx index a48d770460ec9..759cc37ed902b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx @@ -71,7 +71,7 @@ const BLOCKLIST_PAGE_LABELS: ArtifactListPageProps['labels'] = { @@ -87,7 +87,7 @@ const BLOCKLIST_PAGE_LABELS: ArtifactListPageProps['labels'] = { }), emptyStateInfo: i18n.translate('xpack.securitySolution.blocklist.emptyStateInfo', { defaultMessage: - 'The blocklist prevents selected applications from running on your hosts by extending the list of processes the Endpoint considers malicious.', + 'The blocklist prevents specified applications from running on your hosts, extending the list of processes that Endpoint Security considers malicious.', }), emptyStatePrimaryButtonLabel: i18n.translate( 'xpack.securitySolution.blocklist.emptyStatePrimaryButtonLabel', From 13c928d4f34ba3f7249dd5bf08c8045c7069b615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Wed, 4 May 2022 13:08:25 +0200 Subject: [PATCH 18/68] [FullStory] Filter custom events by an allowlist (#131148) --- .../client/src/analytics_client/types.ts | 2 +- packages/analytics/client/src/events/types.ts | 5 +- .../analytics/client/src/shippers/types.ts | 2 +- .../analytics/shippers/fullstory/README.md | 4 ++ .../fullstory/src/fullstory_shipper.test.ts | 45 ++++++++++++++++- .../fullstory/src/fullstory_shipper.ts | 48 ++++++++++++++++--- .../shippers/fullstory/src/load_snippet.ts | 3 ++ .../test_suites/core_plugins/rendering.ts | 1 + x-pack/plugins/cloud/public/plugin.tsx | 4 +- x-pack/plugins/cloud/server/config.ts | 3 ++ 10 files changed, 106 insertions(+), 11 deletions(-) diff --git a/packages/analytics/client/src/analytics_client/types.ts b/packages/analytics/client/src/analytics_client/types.ts index 782d6b16fa594..7dd2be53991b0 100644 --- a/packages/analytics/client/src/analytics_client/types.ts +++ b/packages/analytics/client/src/analytics_client/types.ts @@ -176,7 +176,7 @@ export interface IAnalyticsClient { ) => void; /** * Registers the event type that will be emitted via the reportEvent API. - * @param eventTypeOps + * @param eventTypeOps The definition of the event type {@link EventTypeOpts}. */ registerEventType: (eventTypeOps: EventTypeOpts) => void; diff --git a/packages/analytics/client/src/events/types.ts b/packages/analytics/client/src/events/types.ts index bc193a2788db1..a63d2adeeb62a 100644 --- a/packages/analytics/client/src/events/types.ts +++ b/packages/analytics/client/src/events/types.ts @@ -36,7 +36,10 @@ export interface EventContext { * The current entity ID (dashboard ID, visualization ID, etc.). */ entityId?: string; - // TODO: Extend with known keys + + /** + * Additional keys are allowed. + */ [key: string]: unknown; } diff --git a/packages/analytics/client/src/shippers/types.ts b/packages/analytics/client/src/shippers/types.ts index 945ea08dae58a..15328507b4fe7 100644 --- a/packages/analytics/client/src/shippers/types.ts +++ b/packages/analytics/client/src/shippers/types.ts @@ -25,7 +25,7 @@ export interface IShipper { optIn: (isOptedIn: boolean) => void; /** * Perform any necessary calls to the persisting/analytics solution to set the event's context. - * @param newContext + * @param newContext The full new context to set {@link EventContext} */ extendContext?: (newContext: EventContext) => void; /** diff --git a/packages/analytics/shippers/fullstory/README.md b/packages/analytics/shippers/fullstory/README.md index 60c4b641e300b..5bcc8d3c7d040 100644 --- a/packages/analytics/shippers/fullstory/README.md +++ b/packages/analytics/shippers/fullstory/README.md @@ -21,3 +21,7 @@ analytics.registerShipper(FullStoryShipper, { fullStoryOrgId: '12345' }) | `scriptUrl` | The URL to load the FullStory client from. Falls back to `edge.fullstory.com/s/fs.js` if not specified. | | `debug` | Whether the debug logs should be printed to the console. Defaults to `false`. | | `namespace` | The name of the variable where the API is stored: `window[namespace]`. Defaults to `FS`. | + +## FullStory Custom Events Rate Limits + +FullStory limits the number of custom events that can be sent per second ([docs](https://help.fullstory.com/hc/en-us/articles/360020623234#custom-property-rate-limiting)). In order to comply with that limit, this shipper will only emit the event types registered in the allow-list defined in the constant [CUSTOM_EVENT_TYPES_ALLOWLIST](./src/fullstory_shipper.ts). We may change this behaviour in the future to a remotely-controlled list of events or rely on the opt-in _cherry-pick_ config mechanism of the Analytics Client. diff --git a/packages/analytics/shippers/fullstory/src/fullstory_shipper.test.ts b/packages/analytics/shippers/fullstory/src/fullstory_shipper.test.ts index 4b60ba661fe14..10f24ba5b5e14 100644 --- a/packages/analytics/shippers/fullstory/src/fullstory_shipper.test.ts +++ b/packages/analytics/shippers/fullstory/src/fullstory_shipper.test.ts @@ -119,7 +119,7 @@ describe('FullStoryShipper', () => { { event_type: 'test-event-2', timestamp: '2020-01-01T00:00:00.000Z', - properties: { test: 'test-2' }, + properties: { other_property: 'test-2' }, context: { pageName: 'test-page-1' }, }, ]); @@ -129,6 +129,49 @@ describe('FullStoryShipper', () => { test_str: 'test-1', }); expect(fullStoryApiMock.event).toHaveBeenCalledWith('test-event-2', { + other_property_str: 'test-2', + }); + }); + + test('filters the events by the allow-list', () => { + fullstoryShipper = new FullStoryShipper( + { + eventTypesAllowlist: ['valid-event-1', 'valid-event-2'], + debug: true, + fullStoryOrgId: 'test-org-id', + }, + { + logger: loggerMock.create(), + sendTo: 'staging', + isDev: true, + } + ); + fullstoryShipper.reportEvents([ + { + event_type: 'test-event-1', // Should be filtered out. + timestamp: '2020-01-01T00:00:00.000Z', + properties: { test: 'test-1' }, + context: { pageName: 'test-page-1' }, + }, + { + event_type: 'valid-event-1', + timestamp: '2020-01-01T00:00:00.000Z', + properties: { test: 'test-1' }, + context: { pageName: 'test-page-1' }, + }, + { + event_type: 'valid-event-2', + timestamp: '2020-01-01T00:00:00.000Z', + properties: { test: 'test-2' }, + context: { pageName: 'test-page-1' }, + }, + ]); + + expect(fullStoryApiMock.event).toHaveBeenCalledTimes(2); + expect(fullStoryApiMock.event).toHaveBeenCalledWith('valid-event-1', { + test_str: 'test-1', + }); + expect(fullStoryApiMock.event).toHaveBeenCalledWith('valid-event-2', { test_str: 'test-2', }); }); diff --git a/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts b/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts index ef9d5d662813d..ad970564c6845 100644 --- a/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts +++ b/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts @@ -18,20 +18,46 @@ import { getParsedVersion } from './get_parsed_version'; import { formatPayload } from './format_payload'; import { loadSnippet } from './load_snippet'; -export type FullStoryShipperConfig = FullStorySnippetConfig; +/** + * FullStory shipper configuration. + */ +export interface FullStoryShipperConfig extends FullStorySnippetConfig { + /** + * FullStory's custom events rate limit is very aggressive. + * If this setting is provided, it'll only send the event types specified in this list. + */ + eventTypesAllowlist?: string[]; +} +/** + * FullStory shipper. + */ export class FullStoryShipper implements IShipper { + /** Shipper's unique name */ public static shipperName = 'FullStory'; + private readonly fullStoryApi: FullStoryApi; private lastUserId: string | undefined; + private readonly eventTypesAllowlist?: string[]; + /** + * Creates a new instance of the FullStoryShipper. + * @param config {@link FullStoryShipperConfig} + * @param initContext {@link AnalyticsClientInitContext} + */ constructor( config: FullStoryShipperConfig, private readonly initContext: AnalyticsClientInitContext ) { - this.fullStoryApi = loadSnippet(config); + const { eventTypesAllowlist, ...snippetConfig } = config; + this.fullStoryApi = loadSnippet(snippetConfig); + this.eventTypesAllowlist = eventTypesAllowlist; } + /** + * {@inheritDoc IShipper.extendContext} + * @param newContext {@inheritDoc IShipper.extendContext.newContext} + */ public extendContext(newContext: EventContext): void { this.initContext.logger.debug(`Received context ${JSON.stringify(newContext)}`); @@ -70,6 +96,10 @@ export class FullStoryShipper implements IShipper { } } + /** + * {@inheritDoc IShipper.optIn} + * @param isOptedIn {@inheritDoc IShipper.optIn.isOptedIn} + */ public optIn(isOptedIn: boolean): void { this.initContext.logger.debug(`Setting FS to optIn ${isOptedIn}`); // FullStory uses 2 different opt-in methods: @@ -85,11 +115,17 @@ export class FullStoryShipper implements IShipper { } } + /** + * {@inheritDoc IShipper.reportEvents} + * @param events {@inheritDoc IShipper.reportEvents.events} + */ public reportEvents(events: Event[]): void { this.initContext.logger.debug(`Reporting ${events.length} events to FS`); - events.forEach((event) => { - // We only read event.properties and discard the rest because the context is already sent in the other APIs. - this.fullStoryApi.event(event.event_type, formatPayload(event.properties)); - }); + events + .filter((event) => this.eventTypesAllowlist?.includes(event.event_type) ?? true) + .forEach((event) => { + // We only read event.properties and discard the rest because the context is already sent in the other APIs. + this.fullStoryApi.event(event.event_type, formatPayload(event.properties)); + }); } } diff --git a/packages/analytics/shippers/fullstory/src/load_snippet.ts b/packages/analytics/shippers/fullstory/src/load_snippet.ts index 471152f033b5a..b06530111d672 100644 --- a/packages/analytics/shippers/fullstory/src/load_snippet.ts +++ b/packages/analytics/shippers/fullstory/src/load_snippet.ts @@ -8,6 +8,9 @@ import type { FullStoryApi } from './types'; +/** + * FullStory basic configuration. + */ export interface FullStorySnippetConfig { /** * The FullStory account id. diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 32fc3be58d39c..0e2484691e03b 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -165,6 +165,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.cloud.deployment_url (string)', 'xpack.cloud.full_story.enabled (boolean)', 'xpack.cloud.full_story.org_id (any)', + 'xpack.cloud.full_story.eventTypesAllowlist (array)', 'xpack.cloud.id (string)', 'xpack.cloud.organization_url (string)', 'xpack.cloud.profile_url (string)', diff --git a/x-pack/plugins/cloud/public/plugin.tsx b/x-pack/plugins/cloud/public/plugin.tsx index bffc1d9496422..4ee3098c709cf 100644 --- a/x-pack/plugins/cloud/public/plugin.tsx +++ b/x-pack/plugins/cloud/public/plugin.tsx @@ -49,6 +49,7 @@ export interface CloudConfigType { full_story: { enabled: boolean; org_id?: string; + eventTypesAllowlist?: string[]; }; /** Configuration to enable live chat in Cloud-enabled instances of Kibana. */ chat: { @@ -249,7 +250,7 @@ export class CloudPlugin implements Plugin { * @private */ private async setupFullStory({ analytics, basePath }: SetupFullStoryDeps) { - const { enabled, org_id: fullStoryOrgId } = this.config.full_story; + const { enabled, org_id: fullStoryOrgId, eventTypesAllowlist } = this.config.full_story; if (!enabled || !fullStoryOrgId) { return; // do not load any FullStory code in the browser if not enabled } @@ -257,6 +258,7 @@ export class CloudPlugin implements Plugin { // Keep this import async so that we do not load any FullStory code into the browser when it is disabled. const { FullStoryShipper } = await import('@kbn/analytics-shippers-fullstory'); analytics.registerShipper(FullStoryShipper, { + eventTypesAllowlist, fullStoryOrgId, // Load an Elastic-internally audited script. Ideally, it should be hosted on a CDN. scriptUrl: basePath.prepend( diff --git a/x-pack/plugins/cloud/server/config.ts b/x-pack/plugins/cloud/server/config.ts index bee83e23475b5..aebbc65e50f18 100644 --- a/x-pack/plugins/cloud/server/config.ts +++ b/x-pack/plugins/cloud/server/config.ts @@ -26,6 +26,9 @@ const fullStoryConfigSchema = schema.object({ schema.string({ minLength: 1 }), schema.maybe(schema.string()) ), + eventTypesAllowlist: schema.arrayOf(schema.string(), { + defaultValue: ['Loaded Kibana'], + }), }); const chatConfigSchema = schema.object({ From a1f8cd4ac08e4a32a7b628be3c87d2202f8e1cb3 Mon Sep 17 00:00:00 2001 From: Oren Zohar <85433724+oren-zohar@users.noreply.github.com> Date: Wed, 4 May 2022 14:13:34 +0300 Subject: [PATCH 19/68] updating managed agent manifest needed resources for cloudbeat (#130886) --- x-pack/plugins/fleet/common/constants/epm.ts | 1 + .../agent_enrollment_flyout/hooks.tsx | 8 +- .../server/services/elastic_agent_manifest.ts | 101 +++++++++++++++++- 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/fleet/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts index 888850b73b15e..5952208007232 100644 --- a/x-pack/plugins/fleet/common/constants/epm.ts +++ b/x-pack/plugins/fleet/common/constants/epm.ts @@ -16,6 +16,7 @@ export const FLEET_ENDPOINT_PACKAGE = 'endpoint'; export const FLEET_APM_PACKAGE = 'apm'; export const FLEET_SYNTHETICS_PACKAGE = 'synthetics'; export const FLEET_KUBERNETES_PACKAGE = 'kubernetes'; +export const FLEET_CLOUD_SECURITY_POSTURE_PACKAGE = 'cloud_security_posture'; export const FLEET_ELASTIC_AGENT_DETAILS_DASHBOARD_ID = 'elastic_agent-f47f18cc-9c7d-4278-b2ea-a6dee816d395'; diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx index 159de12ff578c..886ce736b3625 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/hooks.tsx @@ -9,11 +9,13 @@ import { i18n } from '@kbn/i18n'; import type { PackagePolicy, AgentPolicy } from '../../types'; import { sendGetOneAgentPolicy, useStartServices } from '../../hooks'; - -import { FLEET_KUBERNETES_PACKAGE } from '../../../common'; +import { FLEET_KUBERNETES_PACKAGE, FLEET_CLOUD_SECURITY_POSTURE_PACKAGE } from '../../../common'; import type { K8sMode } from './types'; +// Packages that requires custom elastic-agent manifest +const K8S_PACKAGES = new Set([FLEET_KUBERNETES_PACKAGE, FLEET_CLOUD_SECURITY_POSTURE_PACKAGE]); + export function useAgentPolicyWithPackagePolicies(policyId?: string) { const [agentPolicyWithPackagePolicies, setAgentPolicy] = useState(null); const core = useStartServices(); @@ -64,4 +66,4 @@ export function useIsK8sPolicy(agentPolicy?: AgentPolicy) { return { isK8s }; } -const isK8sPackage = (pkg: PackagePolicy) => pkg.package?.name === FLEET_KUBERNETES_PACKAGE; +const isK8sPackage = (pkg: PackagePolicy) => K8S_PACKAGES.has(pkg.package?.name as string); diff --git a/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts b/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts index 77fe33df4ca48..74cf93c1c6bcb 100644 --- a/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts +++ b/x-pack/plugins/fleet/server/services/elastic_agent_manifest.ts @@ -5,8 +5,7 @@ * 2.0. */ -export const elasticAgentStandaloneManifest = ` ---- +export const elasticAgentStandaloneManifest = `--- apiVersion: apps/v1 kind: DaemonSet metadata: @@ -66,6 +65,11 @@ spec: - name: proc mountPath: /hostfs/proc readOnly: true + - name: etc-kubernetes + mountPath: /hostfs/etc/kubernetes + - name: var-lib + mountPath: /hostfs/var/lib + readOnly: true - name: cgroup mountPath: /hostfs/sys/fs/cgroup readOnly: true @@ -75,6 +79,15 @@ spec: - name: varlog mountPath: /var/log readOnly: true + - name: passwd + mountPath: /hostfs/etc/passwd + readOnly: true + - name: group + mountPath: /hostfs/etc/group + readOnly: true + - name: systemd + mountPath: /hostfs/etc/systemd + readOnly: true volumes: - name: datastreams configMap: @@ -83,6 +96,18 @@ spec: - name: proc hostPath: path: /proc + - name: etc-kubernetes + hostPath: + path: /etc/kubernetes + - name: var-lib + hostPath: + path: /var/lib + - name: passwd + hostPath: + path: /etc/passwd + - name: group + hostPath: + path: /etc/group - name: cgroup hostPath: path: /sys/fs/cgroup @@ -92,6 +117,9 @@ spec: - name: varlog hostPath: path: /var/log + - name: systemd + hostPath: + path: /etc/systemd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -149,6 +177,7 @@ rules: - pods - services - configmaps + - serviceaccounts verbs: ["get", "list", "watch"] # Enable this rule only if planing to use kubernetes_secrets provider #- apiGroups: [""] @@ -181,6 +210,23 @@ rules: - "/metrics" verbs: - get + # required for cloudbeat + - apiGroups: ["rbac.authorization.k8s.io"] + resources: + - clusterrolebindings + - clusterroles + - rolebindings + - roles + verbs: ["get", "list", "watch"] + - apiGroups: ["networking.k8s.io"] + resources: + - ingressclasses + - ingresses + verbs: ["get", "list", "watch"] + - apiGroups: ["policy"] + resources: + - podsecuritypolicies + verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -222,7 +268,8 @@ metadata: --- `; -export const elasticAgentManagedManifest = `apiVersion: apps/v1 +export const elasticAgentManagedManifest = `--- +apiVersion: apps/v1 kind: DaemonSet metadata: name: elastic-agent @@ -285,6 +332,11 @@ spec: - name: proc mountPath: /hostfs/proc readOnly: true + - name: etc-kubernetes + mountPath: /hostfs/etc/kubernetes + - name: var-lib + mountPath: /hostfs/var/lib + readOnly: true - name: cgroup mountPath: /hostfs/sys/fs/cgroup readOnly: true @@ -294,10 +346,31 @@ spec: - name: varlog mountPath: /var/log readOnly: true + - name: passwd + mountPath: /hostfs/etc/passwd + readOnly: true + - name: group + mountPath: /hostfs/etc/group + readOnly: true + - name: systemd + mountPath: /hostfs/etc/systemd + readOnly: true volumes: - name: proc hostPath: path: /proc + - name: etc-kubernetes + hostPath: + path: /etc/kubernetes + - name: var-lib + hostPath: + path: /var/lib + - name: passwd + hostPath: + path: /etc/passwd + - name: group + hostPath: + path: /etc/group - name: cgroup hostPath: path: /sys/fs/cgroup @@ -307,6 +380,9 @@ spec: - name: varlog hostPath: path: /var/log + - name: systemd + hostPath: + path: /etc/systemd --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding @@ -364,6 +440,7 @@ rules: - pods - services - configmaps + - serviceaccounts verbs: ["get", "list", "watch"] # Enable this rule only if planing to use kubernetes_secrets provider #- apiGroups: [""] @@ -396,6 +473,23 @@ rules: - "/metrics" verbs: - get + # required for cloudbeat + - apiGroups: ["rbac.authorization.k8s.io"] + resources: + - clusterrolebindings + - clusterroles + - rolebindings + - roles + verbs: ["get", "list", "watch"] + - apiGroups: ["networking.k8s.io"] + resources: + - ingressclasses + - ingresses + verbs: ["get", "list", "watch"] + - apiGroups: ["policy"] + resources: + - podsecuritypolicies + verbs: ["get", "list", "watch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role @@ -435,5 +529,4 @@ metadata: labels: k8s-app: elastic-agent --- - `; From dbb4d3cf2c456c946fb80d99a9fb7d3dd96d2030 Mon Sep 17 00:00:00 2001 From: Katerina Patticha Date: Wed, 4 May 2022 13:22:04 +0200 Subject: [PATCH 20/68] [APM] Rename service groups template titles and links (#131381) * [APM] Update template title for service groups * [APM] Update link titles in global search * Fix translations Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/routing/apm_route_config.tsx | 11 +- .../templates/service_group_template.tsx | 2 +- x-pack/plugins/apm/public/plugin.ts | 16 +- .../translations/translations/fr-FR.json | 158 +++--------------- .../translations/translations/ja-JP.json | 5 - .../translations/translations/zh-CN.json | 5 - 6 files changed, 38 insertions(+), 159 deletions(-) diff --git a/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx index 0ff0b18818301..ad6947c736fe2 100644 --- a/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx +++ b/x-pack/plugins/apm/public/components/routing/apm_route_config.tsx @@ -21,13 +21,9 @@ import { ServiceGroupsList } from '../app/service_groups'; import { ServiceGroupsRedirect } from './service_groups_redirect'; import { offsetRt } from '../../../common/offset_rt'; -const ServiceGroupsBreadcrumnbLabel = i18n.translate( - 'xpack.apm.views.serviceGroups.breadcrumbLabel', - { defaultMessage: 'Services' } -); const ServiceGroupsTitle = i18n.translate( 'xpack.apm.views.serviceGroups.title', - { defaultMessage: 'Service groups' } + { defaultMessage: 'Services' } ); /** @@ -77,10 +73,7 @@ const apmRoutes = { // this route fails on navigation unless it's defined before home '/service-groups': { element: ( - + diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index 627196a9a4bdc..2ee87571cb719 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -93,6 +93,14 @@ export interface ApmPluginStartDeps { const servicesTitle = i18n.translate('xpack.apm.navigation.servicesTitle', { defaultMessage: 'Services', }); + +const allServicesTitle = i18n.translate( + 'xpack.apm.navigation.allServicesTitle', + { + defaultMessage: 'All services', + } +); + const tracesTitle = i18n.translate('xpack.apm.navigation.tracesTitle', { defaultMessage: 'Traces', }); @@ -270,12 +278,16 @@ export class ApmPlugin implements Plugin { ? [ { id: 'service-groups-list', - title: 'Service groups', + title: servicesTitle, path: '/service-groups', }, ] : []), - { id: 'services', title: servicesTitle, path: '/services' }, + { + id: 'services', + title: serviceGroupsEnabled ? allServicesTitle : servicesTitle, + path: '/services', + }, { id: 'traces', title: tracesTitle, path: '/traces' }, { id: 'service-map', title: serviceMapTitle, path: '/service-map' }, { id: 'backends', title: dependenciesTitle, path: '/backends' }, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index a3f72e12dd15a..c4d73013a4591 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2721,6 +2721,10 @@ "dataViews.unableWriteLabel": "Impossible d’écrire la vue de données ! Actualisez la page pour obtenir la dernière version de cette vue de données.", "devTools.badge.betaLabel": "Bêta", "devTools.badge.betaTooltipText": "Cette fonctionnalité pourra considérablement changer dans les futures versions", + "devTools.badge.readOnly.text": "Lecture seule", + "devTools.badge.readOnly.tooltip": "Enregistrement impossible", + "devTools.breadcrumb.homeLabel": "Outils de développement", + "devTools.devToolsTitle": "Outils de développement", "unifiedSearch.search.unableToGetSavedQueryToastTitle": "Impossible de charger la requête enregistrée {savedQueryId}", "unifiedSearch.noDataPopover.content": "Cette plage temporelle ne contient pas de données. Étendez ou ajustez la plage temporelle pour obtenir plus de champs et pouvoir créer des graphiques.", "unifiedSearch.noDataPopover.dismissAction": "Ne plus afficher", @@ -2836,10 +2840,22 @@ "unifiedSearch.filter.options.pinAllFiltersButtonLabel": "Tout épingler", "unifiedSearch.filter.options.unpinAllFiltersButtonLabel": "Tout désépingler", "unifiedSearch.filter.searchBar.changeAllFiltersTitle": "Changer tous les filtres", - "devTools.badge.readOnly.text": "Lecture seule", - "devTools.badge.readOnly.tooltip": "Enregistrement impossible", - "devTools.breadcrumb.homeLabel": "Outils de développement", - "devTools.devToolsTitle": "Outils de développement", + "unifiedSearch.kueryAutocomplete.andOperatorDescription": "Nécessite que {bothArguments} soient ''vrai''.", + "unifiedSearch.kueryAutocomplete.andOperatorDescription.bothArgumentsText": "les deux arguments", + "unifiedSearch.kueryAutocomplete.equalOperatorDescription": "{equals} une certaine valeur", + "unifiedSearch.kueryAutocomplete.equalOperatorDescription.equalsText": "égale", + "unifiedSearch.kueryAutocomplete.existOperatorDescription": "{exists} sous un certain format", + "unifiedSearch.kueryAutocomplete.existOperatorDescription.existsText": "existe", + "unifiedSearch.kueryAutocomplete.greaterThanOperatorDescription": "est {greaterThan} une certaine valeur", + "unifiedSearch.kueryAutocomplete.greaterThanOperatorDescription.greaterThanText": "supérieur à", + "unifiedSearch.kueryAutocomplete.greaterThanOrEqualOperatorDescription": "est {greaterThanOrEqualTo} une certaine valeur", + "unifiedSearch.kueryAutocomplete.greaterThanOrEqualOperatorDescription.greaterThanOrEqualToText": "supérieur ou égal à", + "unifiedSearch.kueryAutocomplete.lessThanOperatorDescription": "est {lessThan} une certaine valeur", + "unifiedSearch.kueryAutocomplete.lessThanOperatorDescription.lessThanText": "inférieur à", + "unifiedSearch.kueryAutocomplete.lessThanOrEqualOperatorDescription": "est {lessThanOrEqualTo} une certaine valeur", + "unifiedSearch.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText": "inférieur ou égal à", + "unifiedSearch.kueryAutocomplete.orOperatorDescription": "Nécessite qu’{oneOrMoreArguments} soit ''vrai''.", + "unifiedSearch.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText": "au moins un argument", "discover.advancedSettings.context.defaultSizeText": "Le nombre d'entrées connexes à afficher dans la vue contextuelle", "discover.advancedSettings.context.defaultSizeTitle": "Taille de contexte", "discover.advancedSettings.context.sizeStepText": "L’incrément duquel augmenter ou diminuer la taille de contexte", @@ -8359,7 +8375,6 @@ "xpack.apm.views.metrics.title": "Indicateurs", "xpack.apm.views.nodes.title": "JVM", "xpack.apm.views.overview.title": "Aperçu", - "xpack.apm.views.serviceGroups.breadcrumbLabel": "Services", "xpack.apm.views.serviceGroups.title": "Groupes de services", "xpack.apm.views.serviceInventory.title": "Services", "xpack.apm.views.serviceMap.title": "Carte des services", @@ -31093,137 +31108,6 @@ "xpack.watcher.watchActions.webhook.portIsRequiredValidationMessage": "Le port webhook est requis.", "xpack.watcher.watchActions.webhook.usernameIsRequiredIfPasswordValidationMessage": "Le nom d'utilisateur est requis.", "xpack.watcher.watchEdit.thresholdWatchExpression.aggType.fieldIsRequiredValidationMessage": "Ce champ est requis.", - "xpack.watcher.watcherDescription": "Détectez les modifications survenant dans vos données en créant, gérant et monitorant des alertes.", - "unifiedSearch.noDataPopover.content": "Cette plage temporelle ne contient pas de données. Étendez ou ajustez la plage temporelle pour obtenir plus de champs et pouvoir créer des graphiques.", - "unifiedSearch.noDataPopover.dismissAction": "Ne plus afficher", - "unifiedSearch.noDataPopover.subtitle": "Conseil", - "unifiedSearch.noDataPopover.title": "Ensemble de données vide", - "unifiedSearch.query.queryBar.clearInputLabel": "Effacer l'entrée", - "unifiedSearch.query.queryBar.comboboxAriaLabel": "Rechercher et filtrer la page {pageType}", - "unifiedSearch.query.queryBar.kqlFullLanguageName": "Langage de requête Kibana", - "unifiedSearch.query.queryBar.kqlLanguageName": "KQL", - "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoDocLinkText": "documents", - "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoOptOutText": "Ne plus afficher", - "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoText": "Il semblerait que votre requête porte sur un champ imbriqué. Selon le résultat visé, il existe plusieurs façons de construire une syntaxe KQL pour des requêtes imbriquées. Apprenez-en plus avec notre {link}.", - "unifiedSearch.query.queryBar.KQLNestedQuerySyntaxInfoTitle": "Syntaxe de requête imbriquée KQL", - "unifiedSearch.query.queryBar.kqlOffLabel": "Désactivé", - "unifiedSearch.query.queryBar.kqlOnLabel": "Activé", - "unifiedSearch.query.queryBar.languageSwitcher.toText": "Passer au langage de requête Kibana pour la recherche", - "unifiedSearch.query.queryBar.luceneLanguageName": "Lucene", - "unifiedSearch.query.queryBar.searchInputAriaLabel": "Commencer à taper pour rechercher et filtrer la page {pageType}", - "unifiedSearch.query.queryBar.searchInputPlaceholder": "Recherche", - "unifiedSearch.query.queryBar.syntaxOptionsDescription": "{docsLink} (KQL) offre une syntaxe de requête simplifiée et la prise en charge des champs scriptés. KQL offre également une fonctionnalité de saisie semi-automatique. Si vous désactivez KQL, {nonKqlModeHelpText}.", - "unifiedSearch.query.queryBar.syntaxOptionsDescription.nonKqlModeHelpText": "Kibana utilise Lucene.", - "unifiedSearch.search.searchBar.savedQueryDescriptionLabelText": "Description", - "unifiedSearch.search.searchBar.savedQueryDescriptionText": "Enregistrez le texte et les filtres de la requête que vous souhaitez réutiliser.", - "unifiedSearch.search.searchBar.savedQueryForm.titleConflictText": "Ce nom est en conflit avec une requête enregistrée existante.", - "unifiedSearch.search.searchBar.savedQueryFormCancelButtonText": "Annuler", - "unifiedSearch.search.searchBar.savedQueryFormSaveButtonText": "Enregistrer", - "unifiedSearch.search.searchBar.savedQueryFormTitle": "Enregistrer la requête", - "unifiedSearch.search.searchBar.savedQueryIncludeFiltersLabelText": "Inclure les filtres", - "unifiedSearch.search.searchBar.savedQueryIncludeTimeFilterLabelText": "Inclure le filtre temporel", - "unifiedSearch.search.searchBar.savedQueryNameHelpText": "Un nom est requis. Le nom ne peut pas contenir d'espace vide au début ou à la fin. Le nom doit être unique.", - "unifiedSearch.search.searchBar.savedQueryNameLabelText": "Nom", - "unifiedSearch.search.searchBar.savedQueryNoSavedQueriesText": "Aucune requête enregistrée.", - "unifiedSearch.search.searchBar.savedQueryPopoverButtonText": "Voir les requêtes enregistrées", - "unifiedSearch.search.searchBar.savedQueryPopoverClearButtonAriaLabel": "Effacer la requête enregistrée en cours", - "unifiedSearch.search.searchBar.savedQueryPopoverClearButtonText": "Effacer", - "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionCancelButtonText": "Annuler", - "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionConfirmButtonText": "Supprimer", - "unifiedSearch.search.searchBar.savedQueryPopoverConfirmDeletionTitle": "Supprimer \"{savedQueryName}\" ?", - "unifiedSearch.search.searchBar.savedQueryPopoverDeleteButtonAriaLabel": "Supprimer la requête enregistrée {savedQueryName}", - "unifiedSearch.search.searchBar.savedQueryPopoverSaveAsNewButtonAriaLabel": "Enregistrer en tant que nouvelle requête enregistrée", - "unifiedSearch.search.searchBar.savedQueryPopoverSaveAsNewButtonText": "Enregistrer en tant que nouvelle", - "unifiedSearch.search.searchBar.savedQueryPopoverSaveButtonAriaLabel": "Enregistrer une nouvelle requête enregistrée", - "unifiedSearch.search.searchBar.savedQueryPopoverSaveButtonText": "Enregistrer la requête en cours", - "unifiedSearch.search.searchBar.savedQueryPopoverSaveChangesButtonAriaLabel": "Enregistrer les modifications apportées à {title}", - "unifiedSearch.search.searchBar.savedQueryPopoverSaveChangesButtonText": "Enregistrer les modifications", - "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName}", - "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemDescriptionAriaLabel": "Description de {savedQueryName}", - "unifiedSearch.search.searchBar.savedQueryPopoverSavedQueryListItemSelectedButtonAriaLabel": "Bouton de requête enregistrée {savedQueryName} sélectionné. Appuyez pour effacer les modifications.", - "unifiedSearch.search.searchBar.savedQueryPopoverTitleText": "Requêtes enregistrées", - "unifiedSearch.search.unableToGetSavedQueryToastTitle": "Impossible de charger la requête enregistrée {savedQueryId}", - "unifiedSearch.query.queryBar.syntaxOptionsTitle": "Options de syntaxe", - "unifiedSearch.filter.applyFilterActionTitle": "Appliquer le filtre à la vue en cours", - "unifiedSearch.filter.applyFilters.popupHeader": "Sélectionner les filtres à appliquer", - "unifiedSearch.filter.applyFiltersPopup.cancelButtonLabel": "Annuler", - "unifiedSearch.filter.applyFiltersPopup.saveButtonLabel": "Appliquer", - "unifiedSearch.filter.filterBar.addFilterButtonLabel": "Ajouter un filtre", - "unifiedSearch.filter.filterBar.deleteFilterButtonLabel": "Supprimer", - "unifiedSearch.filter.filterBar.disabledFilterPrefix": "Désactivé", - "unifiedSearch.filter.filterBar.disableFilterButtonLabel": "Désactiver temporairement", - "unifiedSearch.filter.filterBar.editFilterButtonLabel": "Modifier le filtre", - "unifiedSearch.filter.filterBar.enableFilterButtonLabel": "Réactiver", - "unifiedSearch.filter.filterBar.excludeFilterButtonLabel": "Exclure les résultats", - "unifiedSearch.filter.filterBar.filterItemBadgeAriaLabel": "Actions de filtrage", - "unifiedSearch.filter.filterBar.filterItemBadgeIconAriaLabel": "Supprimer {filter}", - "unifiedSearch.filter.filterBar.includeFilterButtonLabel": "Inclure les résultats", - "unifiedSearch.filter.filterBar.indexPatternSelectPlaceholder": "Sélectionner un modèle d'indexation", - "unifiedSearch.filter.filterBar.labelErrorInfo": "Modèle d'indexation {indexPattern} introuvable", - "unifiedSearch.filter.filterBar.labelErrorText": "Erreur", - "unifiedSearch.filter.filterBar.labelWarningInfo": "Le champ {fieldName} n'existe pas dans la vue en cours.", - "unifiedSearch.filter.filterBar.labelWarningText": "Avertissement", - "unifiedSearch.filter.filterBar.moreFilterActionsMessage": "Filtre : {innerText}. Sélectionner pour plus d’actions de filtrage.", - "unifiedSearch.filter.filterBar.negatedFilterPrefix": "NON ", - "unifiedSearch.filter.filterBar.pinFilterButtonLabel": "Épingler dans toutes les applications", - "unifiedSearch.filter.filterBar.pinnedFilterPrefix": "Épinglé", - "unifiedSearch.filter.filterBar.unpinFilterButtonLabel": "Désépingler", - "unifiedSearch.filter.filterEditor.cancelButtonLabel": "Annuler", - "unifiedSearch.filter.filterEditor.createCustomLabelInputLabel": "Étiquette personnalisée", - "unifiedSearch.filter.filterEditor.createCustomLabelSwitchLabel": "Créer une étiquette personnalisée ?", - "unifiedSearch.filter.filterEditor.doesNotExistOperatorOptionLabel": "n'existe pas", - "unifiedSearch.filter.filterEditor.editFilterPopupTitle": "Modifier le filtre", - "unifiedSearch.filter.filterEditor.editFilterValuesButtonLabel": "Modifier les valeurs du filtre", - "unifiedSearch.filter.filterEditor.editQueryDslButtonLabel": "Modifier en tant que Query DSL", - "unifiedSearch.filter.filterEditor.existsOperatorOptionLabel": "existe", - "unifiedSearch.filter.filterEditor.falseOptionLabel": "false", - "unifiedSearch.filter.filterEditor.fieldSelectLabel": "Champ", - "unifiedSearch.filter.filterEditor.fieldSelectPlaceholder": "Sélectionner d'abord un champ", - "unifiedSearch.filter.filterEditor.indexPatternSelectLabel": "Modèle d'indexation", - "unifiedSearch.filter.filterEditor.isBetweenOperatorOptionLabel": "est entre", - "unifiedSearch.filter.filterEditor.isNotBetweenOperatorOptionLabel": "n'est pas entre", - "unifiedSearch.filter.filterEditor.isNotOneOfOperatorOptionLabel": "n'est pas l'une des options suivantes", - "unifiedSearch.filter.filterEditor.isNotOperatorOptionLabel": "n'est pas", - "unifiedSearch.filter.filterEditor.isOneOfOperatorOptionLabel": "est l'une des options suivantes", - "unifiedSearch.filter.filterEditor.isOperatorOptionLabel": "est", - "unifiedSearch.filter.filterEditor.operatorSelectLabel": "Opérateur", - "unifiedSearch.filter.filterEditor.operatorSelectPlaceholderSelect": "Sélectionner", - "unifiedSearch.filter.filterEditor.operatorSelectPlaceholderWaiting": "En attente", - "unifiedSearch.filter.filterEditor.queryDslLabel": "Query DSL d'Elasticsearch", - "unifiedSearch.filter.filterEditor.rangeEndInputPlaceholder": "Fin de la plage", - "unifiedSearch.filter.filterEditor.rangeInputLabel": "Plage", - "unifiedSearch.filter.filterEditor.rangeStartInputPlaceholder": "Début de la plage", - "unifiedSearch.filter.filterEditor.saveButtonLabel": "Enregistrer", - "unifiedSearch.filter.filterEditor.trueOptionLabel": "vrai", - "unifiedSearch.filter.filterEditor.valueInputLabel": "Valeur", - "unifiedSearch.filter.filterEditor.valueInputPlaceholder": "Saisir une valeur", - "unifiedSearch.filter.filterEditor.valueSelectPlaceholder": "Sélectionner une valeur", - "unifiedSearch.filter.filterEditor.valuesSelectLabel": "Valeurs", - "unifiedSearch.filter.filterEditor.valuesSelectPlaceholder": "Sélectionner des valeurs", - "unifiedSearch.filter.options.changeAllFiltersButtonLabel": "Changer tous les filtres", - "unifiedSearch.filter.options.deleteAllFiltersButtonLabel": "Tout supprimer", - "unifiedSearch.filter.options.disableAllFiltersButtonLabel": "Tout désactiver", - "unifiedSearch.filter.options.enableAllFiltersButtonLabel": "Tout activer", - "unifiedSearch.filter.options.invertDisabledFiltersButtonLabel": "Inverser l’activation/désactivation", - "unifiedSearch.filter.options.invertNegatedFiltersButtonLabel": "Inverser l'inclusion", - "unifiedSearch.filter.options.pinAllFiltersButtonLabel": "Tout épingler", - "unifiedSearch.filter.options.unpinAllFiltersButtonLabel": "Tout désépingler", - "unifiedSearch.filter.searchBar.changeAllFiltersTitle": "Changer tous les filtres", - "unifiedSearch.kueryAutocomplete.andOperatorDescription": "Nécessite que {bothArguments} soient ''vrai''.", - "unifiedSearch.kueryAutocomplete.andOperatorDescription.bothArgumentsText": "les deux arguments", - "unifiedSearch.kueryAutocomplete.equalOperatorDescription": "{equals} une certaine valeur", - "unifiedSearch.kueryAutocomplete.equalOperatorDescription.equalsText": "égale", - "unifiedSearch.kueryAutocomplete.existOperatorDescription": "{exists} sous un certain format", - "unifiedSearch.kueryAutocomplete.existOperatorDescription.existsText": "existe", - "unifiedSearch.kueryAutocomplete.greaterThanOperatorDescription": "est {greaterThan} une certaine valeur", - "unifiedSearch.kueryAutocomplete.greaterThanOperatorDescription.greaterThanText": "supérieur à", - "unifiedSearch.kueryAutocomplete.greaterThanOrEqualOperatorDescription": "est {greaterThanOrEqualTo} une certaine valeur", - "unifiedSearch.kueryAutocomplete.greaterThanOrEqualOperatorDescription.greaterThanOrEqualToText": "supérieur ou égal à", - "unifiedSearch.kueryAutocomplete.lessThanOperatorDescription": "est {lessThan} une certaine valeur", - "unifiedSearch.kueryAutocomplete.lessThanOperatorDescription.lessThanText": "inférieur à", - "unifiedSearch.kueryAutocomplete.lessThanOrEqualOperatorDescription": "est {lessThanOrEqualTo} une certaine valeur", - "unifiedSearch.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText": "inférieur ou égal à", - "unifiedSearch.kueryAutocomplete.orOperatorDescription": "Nécessite qu’{oneOrMoreArguments} soit ''vrai''.", - "unifiedSearch.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText": "au moins un argument" + "xpack.watcher.watcherDescription": "Détectez les modifications survenant dans vos données en créant, gérant et monitorant des alertes." } } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 4b8f0b344b2b5..ac5090885883c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2702,10 +2702,6 @@ "data.searchSessions.sessionService.sessionObjectFetchError": "検索セッション情報を取得できませんでした", "data.triggers.applyFilterDescription": "Kibanaフィルターが適用されるとき。単一の値または範囲フィルターにすることができます。", "data.triggers.applyFilterTitle": "フィルターを適用", - "dataViews.deprecations.scriptedFields.manualStepOneMessage": "[スタック管理]>[Kibana]>[データビュー]に移動します。", - "dataViews.deprecations.scriptedFields.manualStepTwoMessage": "ランタイムフィールドを使用するには、スクリプト化されたフィールドがある{numberOfIndexPatternsWithScriptedFields}データビューを更新します。ほとんどの場合、既存のスクリプトを移行するには、「return ;」から「emit();」に変更する必要があります。1つ以上のスクリプト化されたフィールドがあるデータビュー:{allTitles}", - "dataViews.deprecations.scriptedFieldsMessage": "スクリプト化されたフィールドを使用する{numberOfIndexPatternsWithScriptedFields}データビュー({titlesPreview}...)があります。スクリプト化されたフィールドは廃止予定であり、今後は削除されます。ランタイムフィールドを使用してください。", - "dataViews.deprecations.scriptedFieldsTitle": "スクリプト化されたフィールドを使用しているデータビューが見つかりました。", "data.mgmt.searchSessions.actionDelete": "削除", "data.mgmt.searchSessions.actionExtend": "延長", "data.mgmt.searchSessions.actionRename": "名前を編集", @@ -8344,7 +8340,6 @@ "xpack.apm.views.metrics.title": "メトリック", "xpack.apm.views.nodes.title": "JVM", "xpack.apm.views.overview.title": "概要", - "xpack.apm.views.serviceGroups.breadcrumbLabel": "サービス", "xpack.apm.views.serviceGroups.title": "サービスグループ", "xpack.apm.views.serviceInventory.title": "サービス", "xpack.apm.views.serviceMap.title": "サービスマップ", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 649d6e648c0ec..6c597be7e4655 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2810,10 +2810,6 @@ "data.searchSessionName.saveButtonText": "保存", "data.sessions.management.flyoutText": "此搜索会话的配置", "data.sessions.management.flyoutTitle": "检查搜索会话", - "dataViews.deprecations.scriptedFields.manualStepOneMessage": "导航到“堆栈管理”>“Kibana”>“索引模式”。", - "dataViews.deprecations.scriptedFields.manualStepTwoMessage": "更新 {numberOfIndexPatternsWithScriptedFields} 个具有脚本字段的索引模式以改为使用运行时字段。多数情况下,要迁移现有脚本,您需要将“return ;”更改为“emit();”。至少有一个脚本字段的索引模式:{allTitles}", - "dataViews.deprecations.scriptedFieldsMessage": "您具有 {numberOfIndexPatternsWithScriptedFields} 个使用脚本字段的索引模式 ({titlesPreview}...)。脚本字段已过时,将在未来移除。请改为使用运行时脚本。", - "dataViews.deprecations.scriptedFieldsTitle": "找到使用脚本字段的索引模式", "dataViews.deprecations.scriptedFields.manualStepOneMessage": "导航到“堆栈管理”>“Kibana”>“数据视图”。", "dataViews.deprecations.scriptedFields.manualStepTwoMessage": "更新 {numberOfIndexPatternsWithScriptedFields} 个具有脚本字段的数据视图以改为使用运行时字段。多数情况下,要迁移现有脚本,您需要将“return ;”更改为“emit();”。至少有一个脚本字段的数据视图:{allTitles}", "dataViews.deprecations.scriptedFieldsMessage": "您具有 {numberOfIndexPatternsWithScriptedFields} 个使用脚本字段的数据视图 ({titlesPreview}...)。脚本字段已过时,将在未来移除。请改为使用运行时脚本。", @@ -8365,7 +8361,6 @@ "xpack.apm.views.metrics.title": "指标", "xpack.apm.views.nodes.title": "JVM", "xpack.apm.views.overview.title": "概览", - "xpack.apm.views.serviceGroups.breadcrumbLabel": "服务", "xpack.apm.views.serviceGroups.title": "服务组", "xpack.apm.views.serviceInventory.title": "服务", "xpack.apm.views.serviceMap.title": "服务地图", From 71a1f04703cb06f76193b5c78ef517041dfbabec Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Wed, 4 May 2022 13:37:25 +0200 Subject: [PATCH 21/68] Fixes worker silent failure after style violations fixes (#131415) --- .../src/scripts/utils/{worker.ts => synthtrace_worker.ts} | 0 packages/elastic-apm-synthtrace/src/scripts/utils/worker.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/elastic-apm-synthtrace/src/scripts/utils/{worker.ts => synthtrace_worker.ts} (100%) diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/worker.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/synthtrace_worker.ts similarity index 100% rename from packages/elastic-apm-synthtrace/src/scripts/utils/worker.ts rename to packages/elastic-apm-synthtrace/src/scripts/utils/synthtrace_worker.ts diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/worker.js b/packages/elastic-apm-synthtrace/src/scripts/utils/worker.js index 84887f4d9285b..734a9323e5516 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/worker.js +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/worker.js @@ -12,4 +12,4 @@ require('@babel/register')({ presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], }); -require('./worker'); +require('./synthtrace_worker'); From 876d65c4790dedada9e226a6e2b0e80b89f3e255 Mon Sep 17 00:00:00 2001 From: CohenIdo <90558359+CohenIdo@users.noreply.github.com> Date: Wed, 4 May 2022 14:43:36 +0300 Subject: [PATCH 22/68] [Cloud Security] add rules status to benchmark API --- .../cloud_security_posture/common/types.ts | 7 ++ .../fixtures/csp_benchmark_integration.ts | 6 ++ .../routes/benchmarks/benchmarks.test.ts | 57 ++++++++-- .../server/routes/benchmarks/benchmarks.ts | 100 +++++++++++++----- .../update_rules_configuration.ts | 7 +- .../server/saved_objects/csp_rule_type.ts | 8 ++ 6 files changed, 149 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index 4bc388d39ebe4..110e8c071deff 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -47,6 +47,12 @@ export interface ComplianceDashboardData { trend: PostureTrend[]; } +export interface CspRulesStatus { + all: number; + enabled: number; + disabled: number; +} + export interface Benchmark { package_policy: Pick< PackagePolicy, @@ -61,4 +67,5 @@ export interface Benchmark { | 'created_by' >; agent_policy: Pick; + rules: CspRulesStatus; } diff --git a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts index 2bbce9840d800..2f05049c4fe15 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/fixtures/csp_benchmark_integration.ts @@ -36,7 +36,13 @@ export const createCspBenchmarkIntegrationFixture = ({ name: chance.sentence(), agents: chance.integer({ min: 0 }), }, + rules = { + all: chance.integer(), + enabled: chance.integer(), + disabled: chance.integer(), + }, }: CreateCspBenchmarkIntegrationFixtureInput = {}): Benchmark => ({ package_policy, agent_policy, + rules, }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts index 4ed7bdb000344..1bcf5196d1d3d 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.test.ts @@ -23,12 +23,13 @@ import { import { defineGetBenchmarksRoute, PACKAGE_POLICY_SAVED_OBJECT_TYPE, - getPackagePolicies, + getCspPackagePolicies, getAgentPolicies, createBenchmarkEntry, + addPackagePolicyCspRules, } from './benchmarks'; -import { SavedObjectsClientContract } from '@kbn/core/server'; +import { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; import { createMockAgentPolicyService, createPackagePolicyServiceMock, @@ -221,7 +222,7 @@ describe('benchmarks API', () => { it('should format request by package name', async () => { const mockPackagePolicyService = createPackagePolicyServiceMock(); - await getPackagePolicies(mockSoClient, mockPackagePolicyService, 'myPackage', { + await getCspPackagePolicies(mockSoClient, mockPackagePolicyService, 'myPackage', { page: 1, per_page: 100, sort_order: 'desc', @@ -239,7 +240,7 @@ describe('benchmarks API', () => { it('should build sort request by `sort_field` and default `sort_order`', async () => { const mockAgentPolicyService = createPackagePolicyServiceMock(); - await getPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { + await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { page: 1, per_page: 100, sort_field: 'package_policy.name', @@ -260,7 +261,7 @@ describe('benchmarks API', () => { it('should build sort request by `sort_field` and asc `sort_order`', async () => { const mockAgentPolicyService = createPackagePolicyServiceMock(); - await getPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { + await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { page: 1, per_page: 100, sort_field: 'package_policy.name', @@ -282,7 +283,7 @@ describe('benchmarks API', () => { it('should format request by benchmark_name', async () => { const mockAgentPolicyService = createPackagePolicyServiceMock(); - await getPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { + await getCspPackagePolicies(mockSoClient, mockAgentPolicyService, 'myPackage', { page: 1, per_page: 100, sort_order: 'desc', @@ -322,6 +323,32 @@ describe('benchmarks API', () => { }); }); + describe('test addPackagePolicyCspRules', () => { + it('should filter enabled rules', async () => { + const packagePolicy = createPackagePolicyMock(); + mockSoClient.find.mockResolvedValueOnce({ + aggregations: { enabled_status: { doc_count: 2 } }, + page: 1, + per_page: 10000, + total: 3, + saved_objects: [ + { + type: 'csp_rule', + id: '0af387d0-c933-11ec-b6c8-4f8afc058cc3', + }, + ], + } as unknown as SavedObjectsFindResponse); + + const cspRulesStatus = await addPackagePolicyCspRules(mockSoClient, packagePolicy); + + expect(cspRulesStatus).toEqual({ + all: 3, + enabled: 2, + disabled: 1, + }); + }); + }); + describe('test createBenchmarkEntry', () => { it('should build benchmark entry agent policy and package policy', async () => { const packagePolicy = createPackagePolicyMock(); @@ -329,9 +356,18 @@ describe('benchmarks API', () => { // @ts-expect-error agentPolicy.agents = 3; - const enrichAgentPolicy = await createBenchmarkEntry(agentPolicy, packagePolicy); + const cspRulesStatus = { + all: 100, + enabled: 52, + disabled: 48, + }; + const enrichAgentPolicy = await createBenchmarkEntry( + agentPolicy, + packagePolicy, + cspRulesStatus + ); - expect(enrichAgentPolicy).toMatchObject({ + expect(enrichAgentPolicy).toEqual({ package_policy: { id: 'c6d16e42-c32d-4dce-8a88-113cfe276ad1', name: 'endpoint-1', @@ -348,6 +384,11 @@ describe('benchmarks API', () => { }, }, agent_policy: { id: 'some-uuid1', name: 'Test Policy', agents: 3 }, + rules: { + all: 100, + disabled: 48, + enabled: 52, + }, }); }); }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts index a2cb7d06f1f58..6121bbe363e88 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/benchmarks/benchmarks.ts @@ -6,7 +6,7 @@ */ import { uniq, map } from 'lodash'; -import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; import { transformError } from '@kbn/securitysolution-es-utils'; import type { PackagePolicyServiceInterface, @@ -19,6 +19,7 @@ import type { AgentPolicy, ListResult, } from '@kbn/fleet-plugin/common'; +import { cspRuleAssetSavedObjectType, CspRuleSchema } from '../../../common/schemas/csp_rule'; import { BENCHMARKS_ROUTE_PATH, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, @@ -29,7 +30,7 @@ import { BenchmarksQuerySchema, } from '../../../common/schemas/benchmark'; import { CspAppContext } from '../../plugin'; -import type { Benchmark } from '../../../common/types'; +import type { Benchmark, CspRulesStatus } from '../../../common/types'; import { isNonNullable } from '../../../common/utils/helpers'; import { CspRouter } from '../../types'; @@ -44,7 +45,7 @@ const getPackageNameQuery = (packageName: string, benchmarkFilter?: string): str return kquery; }; -export const getPackagePolicies = ( +export const getCspPackagePolicies = ( soClient: SavedObjectsClientContract, packagePolicyService: PackagePolicyServiceInterface, packageName: string, @@ -94,10 +95,49 @@ const addRunningAgentToAgentPolicy = async ( ) ); }; +export interface RulesStatusAggregation { + enabled_status: { + doc_count: number; + }; +} +export const getCspRulesStatus = ( + soClient: SavedObjectsClientContract, + packagePolicy: PackagePolicy +): Promise> => { + const cspRules = soClient.find({ + type: cspRuleAssetSavedObjectType, + filter: `${cspRuleAssetSavedObjectType}.attributes.package_policy_id: ${packagePolicy.id} AND ${cspRuleAssetSavedObjectType}.attributes.policy_id: ${packagePolicy.policy_id}`, + aggs: { + enabled_status: { + filter: { + term: { + [`${cspRuleAssetSavedObjectType}.attributes.enabled`]: true, + }, + }, + }, + }, + perPage: 0, + }); + return cspRules; +}; + +export const addPackagePolicyCspRules = async ( + soClient: SavedObjectsClientContract, + packagePolicy: PackagePolicy +): Promise => { + const rules = await getCspRulesStatus(soClient, packagePolicy); + const packagePolicyRules = { + all: rules.total, + enabled: rules.aggregations?.enabled_status.doc_count || 0, + disabled: rules.total - (rules.aggregations?.enabled_status.doc_count || 0), + }; + return packagePolicyRules; +}; export const createBenchmarkEntry = ( agentPolicy: GetAgentPoliciesResponseItem, - packagePolicy: PackagePolicy + packagePolicy: PackagePolicy, + cspRulesStatus: CspRulesStatus ): Benchmark => ({ package_policy: { id: packagePolicy.id, @@ -121,26 +161,33 @@ export const createBenchmarkEntry = ( name: agentPolicy.name, agents: agentPolicy.agents, }, + rules: cspRulesStatus, }); const createBenchmarks = ( + soClient: SavedObjectsClientContract, agentPolicies: GetAgentPoliciesResponseItem[], - packagePolicies: PackagePolicy[] -): Benchmark[] => - packagePolicies.flatMap((packagePolicy) => { - return agentPolicies - .map((agentPolicy) => { - const agentPkgPolicies = agentPolicy.package_policies as string[]; - const isExistsOnAgent = agentPkgPolicies.find( - (pkgPolicy) => pkgPolicy === packagePolicy.id - ); - if (isExistsOnAgent) { - return createBenchmarkEntry(agentPolicy, packagePolicy); - } - return; - }) - .filter(isNonNullable); - }); + cspPackagePolicies: PackagePolicy[] +): Promise => { + const cspPackagePoliciesMap = new Map( + cspPackagePolicies.map((packagePolicy) => [packagePolicy.id, packagePolicy]) + ); + return Promise.all( + agentPolicies.flatMap((agentPolicy) => { + const cspPackagesOnAgent = agentPolicy.package_policies + .map((pckPolicyId) => { + if (typeof pckPolicyId === 'string') return cspPackagePoliciesMap.get(pckPolicyId); + }) + .filter(isNonNullable); + const benchmarks = cspPackagesOnAgent.map(async (cspPackage) => { + const cspRulesStatus = await addPackagePolicyCspRules(soClient, cspPackage); + const benchmark = createBenchmarkEntry(agentPolicy, cspPackage, cspRulesStatus); + return benchmark; + }); + return benchmarks; + }) + ); +}; export const defineGetBenchmarksRoute = (router: CspRouter, cspContext: CspAppContext): void => router.get( @@ -165,7 +212,7 @@ export const defineGetBenchmarksRoute = (router: CspRouter, cspContext: CspAppCo throw new Error(`Failed to get Fleet services`); } - const packagePolicies = await getPackagePolicies( + const cspPackagePolicies = await getCspPackagePolicies( soClient, packagePolicyService, CLOUD_SECURITY_POSTURE_PACKAGE_NAME, @@ -174,15 +221,20 @@ export const defineGetBenchmarksRoute = (router: CspRouter, cspContext: CspAppCo const agentPolicies = await getAgentPolicies( soClient, - packagePolicies.items, + cspPackagePolicies.items, agentPolicyService ); + const enrichAgentPolicies = await addRunningAgentToAgentPolicy(agentService, agentPolicies); - const benchmarks = createBenchmarks(enrichAgentPolicies, packagePolicies.items); + const benchmarks = await createBenchmarks( + soClient, + enrichAgentPolicies, + cspPackagePolicies.items + ); return response.ok({ body: { - ...packagePolicies, + ...cspPackagePolicies, items: benchmarks, }, }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/configuration/update_rules_configuration.ts b/x-pack/plugins/cloud_security_posture/server/routes/configuration/update_rules_configuration.ts index f0e0e3b8a2bb3..da84747f31354 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/configuration/update_rules_configuration.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/configuration/update_rules_configuration.ts @@ -45,18 +45,17 @@ export const getPackagePolicy = async ( return packagePolicies![0]; }; -export const getCspRules = async ( +export const getCspRules = ( soClient: SavedObjectsClientContract, packagePolicy: PackagePolicy -) => { - const cspRules = await soClient.find({ +): Promise> => { + return soClient.find({ type: cspRuleAssetSavedObjectType, filter: `${cspRuleAssetSavedObjectType}.attributes.package_policy_id: ${packagePolicy.id} AND ${cspRuleAssetSavedObjectType}.attributes.policy_id: ${packagePolicy.policy_id}`, searchFields: ['name'], // TODO: research how to get all rules perPage: 10000, }); - return cspRules; }; export const createRulesConfig = ( diff --git a/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_rule_type.ts b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_rule_type.ts index a6309f321328f..f28bf100e2168 100644 --- a/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_rule_type.ts +++ b/x-pack/plugins/cloud_security_posture/server/saved_objects/csp_rule_type.ts @@ -38,6 +38,14 @@ export const ruleAssetSavedObjectMappings: SavedObjectsType['mapp description: { type: 'text', }, + enabled: { + type: 'boolean', + fields: { + keyword: { + type: 'keyword', // sort + }, + }, + }, }, }; From 8271455691eb2a8b81de2df17207b401728766de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Wed, 4 May 2022 13:44:16 +0200 Subject: [PATCH 23/68] [EBT] Remove unnecessary async from tests (#131500) --- .../client/src/analytics_client/analytics_client.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/analytics/client/src/analytics_client/analytics_client.test.ts b/packages/analytics/client/src/analytics_client/analytics_client.test.ts index cbb1b4131b4a4..9eeade4e8d454 100644 --- a/packages/analytics/client/src/analytics_client/analytics_client.test.ts +++ b/packages/analytics/client/src/analytics_client/analytics_client.test.ts @@ -316,7 +316,7 @@ describe('AnalyticsClient', () => { test( 'Spreads the context updates to the shipper (only after opt-in)', - fakeSchedulers(async (advance) => { + fakeSchedulers((advance) => { const extendContextMock = jest.fn(); analyticsClient.registerShipper(MockedShipper, { extendContextMock }); expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in @@ -345,7 +345,7 @@ describe('AnalyticsClient', () => { test( 'Does not spread the context if opt-in === false', - fakeSchedulers(async (advance) => { + fakeSchedulers((advance) => { const extendContextMock = jest.fn(); analyticsClient.registerShipper(MockedShipper, { extendContextMock }); expect(extendContextMock).toHaveBeenCalledTimes(0); // Not until we have opt-in @@ -357,7 +357,7 @@ describe('AnalyticsClient', () => { test( 'Handles errors in the shipper', - fakeSchedulers(async (advance) => { + fakeSchedulers((advance) => { const extendContextMock = jest.fn().mockImplementation(() => { throw new Error('Something went terribly wrong'); }); From dda625c93397aef8c81b3473f3b7ff2a8392dede Mon Sep 17 00:00:00 2001 From: Tomasz Ciecierski Date: Wed, 4 May 2022 13:48:13 +0200 Subject: [PATCH 24/68] [Osquery] Add logo (#131060) --- x-pack/plugins/osquery/public/plugin.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/osquery/public/plugin.ts b/x-pack/plugins/osquery/public/plugin.ts index e88a866cc545f..e21defbaa8828 100644 --- a/x-pack/plugins/osquery/public/plugin.ts +++ b/x-pack/plugins/osquery/public/plugin.ts @@ -45,6 +45,7 @@ export class OsqueryPlugin implements Plugin Date: Wed, 4 May 2022 15:12:04 +0300 Subject: [PATCH 25/68] [Cases] Export `getCasesMetrics` from the cases UI client (#131493) * Export cases metrics * Fixes * Add integration tests * Add comment * Add signal --- .../plugins/cases/common/api/metrics/case.ts | 3 +++ x-pack/plugins/cases/common/ui/types.ts | 2 ++ x-pack/plugins/cases/public/api/decoders.ts | 8 +++++++ x-pack/plugins/cases/public/api/index.test.ts | 20 +++++++++++++++++- x-pack/plugins/cases/public/api/index.ts | 21 ++++++++++++++++--- .../cases/public/client/api/index.test.ts | 16 +++++++------- .../plugins/cases/public/client/api/index.ts | 11 +++++----- x-pack/plugins/cases/public/mocks.ts | 2 +- x-pack/plugins/cases/public/types.ts | 6 +++--- .../routes/api/metrics/get_case_metrics.ts | 9 ++++++-- .../routes/api/metrics/get_cases_metrics.ts | 8 ++++++- .../cases_api_integration/common/lib/utils.ts | 8 +++---- .../tests/common/metrics/get_case_metrics.ts | 18 ++++++++++++++++ .../tests/common/metrics/get_cases_metrics.ts | 11 ++++++++++ 14 files changed, 115 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/cases/common/api/metrics/case.ts b/x-pack/plugins/cases/common/api/metrics/case.ts index 503d602cf6729..2c3a65764769f 100644 --- a/x-pack/plugins/cases/common/api/metrics/case.ts +++ b/x-pack/plugins/cases/common/api/metrics/case.ts @@ -184,6 +184,9 @@ export const SingleCaseMetricsResponseRt = rt.partial( export const CasesMetricsResponseRt = rt.partial( rt.type({ + /** + * The average resolve time of all cases in seconds + */ mttr: rt.number, }).props ); diff --git a/x-pack/plugins/cases/common/ui/types.ts b/x-pack/plugins/cases/common/ui/types.ts index 54074d7295b45..b993ae6602ae9 100644 --- a/x-pack/plugins/cases/common/ui/types.ts +++ b/x-pack/plugins/cases/common/ui/types.ts @@ -19,6 +19,7 @@ import { CommentResponseAlertsType, CasesFindResponse, CasesStatusResponse, + CasesMetricsResponse, } from '../api'; import { SnakeToCamelCase } from '../types'; @@ -65,6 +66,7 @@ export type CaseExternalService = SnakeToCamelCase; export type Case = Omit, 'comments'> & { comments: Comment[] }; export type Cases = Omit, 'cases'> & { cases: Case[] }; export type CasesStatus = SnakeToCamelCase; +export type CasesMetrics = SnakeToCamelCase; export interface ResolvedCase { case: Case; diff --git a/x-pack/plugins/cases/public/api/decoders.ts b/x-pack/plugins/cases/public/api/decoders.ts index 5275555ce9345..6b9cfdb21742c 100644 --- a/x-pack/plugins/cases/public/api/decoders.ts +++ b/x-pack/plugins/cases/public/api/decoders.ts @@ -16,6 +16,8 @@ import { CasesFindResponseRt, CasesStatusResponse, CasesStatusResponseRt, + CasesMetricsResponse, + CasesMetricsResponseRt, } from '../../common/api'; export const decodeCasesFindResponse = (respCases?: CasesFindResponse) => @@ -26,3 +28,9 @@ export const decodeCasesStatusResponse = (respCase?: CasesStatusResponse) => CasesStatusResponseRt.decode(respCase), fold(throwErrors(createToasterPlainError), identity) ); + +export const decodeCasesMetricsResponse = (metrics?: CasesMetricsResponse) => + pipe( + CasesMetricsResponseRt.decode(metrics), + fold(throwErrors(createToasterPlainError), identity) + ); diff --git a/x-pack/plugins/cases/public/api/index.test.ts b/x-pack/plugins/cases/public/api/index.test.ts index ed0bed55f6c97..321a1db206846 100644 --- a/x-pack/plugins/cases/public/api/index.test.ts +++ b/x-pack/plugins/cases/public/api/index.test.ts @@ -6,7 +6,7 @@ */ import { httpServiceMock } from '@kbn/core/public/mocks'; -import { getCases } from '.'; +import { getCases, getCasesMetrics } from '.'; import { allCases, allCasesSnake } from '../containers/mock'; describe('api', () => { @@ -29,4 +29,22 @@ describe('api', () => { }); }); }); + + describe('getCasesMetrics', () => { + const http = httpServiceMock.createStartContract({ basePath: '' }); + http.get.mockResolvedValue({ mttr: 0 }); + + it('should return the correct response', async () => { + expect( + await getCasesMetrics({ http, query: { features: ['mttr'], from: 'now-1d' } }) + ).toEqual({ mttr: 0 }); + }); + + it('should have been called with the correct path', async () => { + await getCasesMetrics({ http, query: { features: ['mttr'], to: 'now-1d' } }); + expect(http.get).toHaveBeenCalledWith('/api/cases/metrics', { + query: { features: ['mttr'], to: 'now-1d' }, + }); + }); + }); }); diff --git a/x-pack/plugins/cases/public/api/index.ts b/x-pack/plugins/cases/public/api/index.ts index 33eb4ba6576c9..209c0ad619d4b 100644 --- a/x-pack/plugins/cases/public/api/index.ts +++ b/x-pack/plugins/cases/public/api/index.ts @@ -6,16 +6,22 @@ */ import { HttpStart } from '@kbn/core/public'; -import { Cases, CasesStatus } from '../../common/ui'; -import { CASE_FIND_URL, CASE_STATUS_URL } from '../../common/constants'; +import { Cases, CasesStatus, CasesMetrics } from '../../common/ui'; +import { CASE_FIND_URL, CASE_METRICS_URL, CASE_STATUS_URL } from '../../common/constants'; import { CasesFindRequest, CasesFindResponse, + CasesMetricsRequest, + CasesMetricsResponse, CasesStatusRequest, CasesStatusResponse, } from '../../common/api'; import { convertAllCasesToCamel, convertToCamelCase } from './utils'; -import { decodeCasesFindResponse, decodeCasesStatusResponse } from './decoders'; +import { + decodeCasesFindResponse, + decodeCasesMetricsResponse, + decodeCasesStatusResponse, +} from './decoders'; export interface HTTPService { http: HttpStart; @@ -43,3 +49,12 @@ export const getCasesStatus = async ({ return convertToCamelCase(decodeCasesStatusResponse(response)); }; + +export const getCasesMetrics = async ({ + http, + signal, + query, +}: HTTPService & { query: CasesMetricsRequest }): Promise => { + const res = await http.get(CASE_METRICS_URL, { signal, query }); + return convertToCamelCase(decodeCasesMetricsResponse(res)); +}; diff --git a/x-pack/plugins/cases/public/client/api/index.test.ts b/x-pack/plugins/cases/public/client/api/index.test.ts index dcefecf87c476..dacea3350bd4a 100644 --- a/x-pack/plugins/cases/public/client/api/index.test.ts +++ b/x-pack/plugins/cases/public/client/api/index.test.ts @@ -7,7 +7,7 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; import { createClientAPI } from '.'; -import { allCases, casesStatus, allCasesSnake } from '../../containers/mock'; +import { allCases, allCasesSnake } from '../../containers/mock'; describe('createClientAPI', () => { beforeEach(() => { @@ -62,19 +62,21 @@ describe('createClientAPI', () => { }); }); - describe('getAllCasesMetrics', () => { + describe('getCasesMetrics', () => { const http = httpServiceMock.createStartContract({ basePath: '' }); const api = createClientAPI({ http }); - http.get.mockResolvedValue(casesStatus); + http.get.mockResolvedValue({ mttr: 0 }); it('should return the correct response', async () => { - expect(await api.cases.getAllCasesMetrics({ from: 'now-1d' })).toEqual(casesStatus); + expect(await api.cases.getCasesMetrics({ features: ['mttr'], from: 'now-1d' })).toEqual({ + mttr: 0, + }); }); it('should have been called with the correct path', async () => { - await api.cases.getAllCasesMetrics({ from: 'now-1d' }); - expect(http.get).toHaveBeenCalledWith('/api/cases/status', { - query: { from: 'now-1d' }, + await api.cases.getCasesMetrics({ features: ['mttr'], from: 'now-1d' }); + expect(http.get).toHaveBeenCalledWith('/api/cases/metrics', { + query: { features: ['mttr'], from: 'now-1d' }, }); }); }); diff --git a/x-pack/plugins/cases/public/client/api/index.ts b/x-pack/plugins/cases/public/client/api/index.ts index a4a16489d4dc9..e9caee514a9cd 100644 --- a/x-pack/plugins/cases/public/client/api/index.ts +++ b/x-pack/plugins/cases/public/client/api/index.ts @@ -12,11 +12,10 @@ import { CasesFindRequest, getCasesFromAlertsUrl, CasesStatusRequest, - CasesStatusResponse, + CasesMetricsRequest, } from '../../../common/api'; -import { CASE_STATUS_URL } from '../../../common/constants'; -import { Cases, CasesStatus } from '../../../common/ui'; -import { getCases, getCasesStatus } from '../../api'; +import { Cases, CasesStatus, CasesMetrics } from '../../../common/ui'; +import { getCases, getCasesMetrics, getCasesStatus } from '../../api'; import { CasesUiStart } from '../../types'; export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['api'] => { @@ -29,10 +28,10 @@ export const createClientAPI = ({ http }: { http: HttpStart }): CasesUiStart['ap cases: { find: (query: CasesFindRequest, signal?: AbortSignal): Promise => getCases({ http, query, signal }), - getAllCasesMetrics: (query: CasesStatusRequest): Promise => - http.get(CASE_STATUS_URL, { query }), getCasesStatus: (query: CasesStatusRequest, signal?: AbortSignal): Promise => getCasesStatus({ http, query, signal }), + getCasesMetrics: (query: CasesMetricsRequest, signal?: AbortSignal): Promise => + getCasesMetrics({ http, signal, query }), }, }; }; diff --git a/x-pack/plugins/cases/public/mocks.ts b/x-pack/plugins/cases/public/mocks.ts index ffaf7de51d05f..5ec7a10c88acc 100644 --- a/x-pack/plugins/cases/public/mocks.ts +++ b/x-pack/plugins/cases/public/mocks.ts @@ -10,7 +10,7 @@ import { CasesUiStart } from './types'; const apiMock: jest.Mocked = { getRelatedCases: jest.fn(), - cases: { find: jest.fn(), getAllCasesMetrics: jest.fn(), getCasesStatus: jest.fn() }, + cases: { find: jest.fn(), getCasesMetrics: jest.fn(), getCasesStatus: jest.fn() }, }; const uiMock: jest.Mocked = { diff --git a/x-pack/plugins/cases/public/types.ts b/x-pack/plugins/cases/public/types.ts index b8b8199329c95..bff5e5fd14700 100644 --- a/x-pack/plugins/cases/public/types.ts +++ b/x-pack/plugins/cases/public/types.ts @@ -21,8 +21,8 @@ import { CasesByAlertId, CasesByAlertIDRequest, CasesFindRequest, + CasesMetricsRequest, CasesStatusRequest, - CasesStatusResponse, CommentRequestAlertType, CommentRequestUserType, } from '../common/api'; @@ -35,7 +35,7 @@ import type { GetCasesProps } from './client/ui/get_cases'; import { GetAllCasesSelectorModalProps } from './client/ui/get_all_cases_selector_modal'; import { GetCreateCaseFlyoutProps } from './client/ui/get_create_case_flyout'; import { GetRecentCasesProps } from './client/ui/get_recent_cases'; -import { Cases, CasesStatus } from '../common/ui'; +import { Cases, CasesStatus, CasesMetrics } from '../common/ui'; export interface CasesPluginSetup { security: SecurityPluginSetup; @@ -77,8 +77,8 @@ export interface CasesUiStart { getRelatedCases: (alertId: string, query: CasesByAlertIDRequest) => Promise; cases: { find: (query: CasesFindRequest, signal?: AbortSignal) => Promise; - getAllCasesMetrics: (query: CasesStatusRequest) => Promise; getCasesStatus: (query: CasesStatusRequest, signal?: AbortSignal) => Promise; + getCasesMetrics: (query: CasesMetricsRequest, signal?: AbortSignal) => Promise; }; }; ui: { diff --git a/x-pack/plugins/cases/server/routes/api/metrics/get_case_metrics.ts b/x-pack/plugins/cases/server/routes/api/metrics/get_case_metrics.ts index 13bfa2093f623..394c0099b4991 100644 --- a/x-pack/plugins/cases/server/routes/api/metrics/get_case_metrics.ts +++ b/x-pack/plugins/cases/server/routes/api/metrics/get_case_metrics.ts @@ -19,17 +19,22 @@ export const getCaseMetricRoute = createCasesRoute({ case_id: schema.string({ minLength: 1 }), }), query: schema.object({ - features: schema.arrayOf(schema.string({ minLength: 1 })), + features: schema.oneOf([ + schema.arrayOf(schema.string({ minLength: 1 })), + schema.string({ minLength: 1 }), + ]), }), }, handler: async ({ context, request, response }) => { try { const caseContext = await context.cases; const client = await caseContext.getCasesClient(); + const { features } = request.query; + return response.ok({ body: await client.metrics.getCaseMetrics({ caseId: request.params.case_id, - features: request.query.features, + features: Array.isArray(features) ? features : [features], }), }); } catch (error) { diff --git a/x-pack/plugins/cases/server/routes/api/metrics/get_cases_metrics.ts b/x-pack/plugins/cases/server/routes/api/metrics/get_cases_metrics.ts index 3eb9ec26a9297..44d351571edbb 100644 --- a/x-pack/plugins/cases/server/routes/api/metrics/get_cases_metrics.ts +++ b/x-pack/plugins/cases/server/routes/api/metrics/get_cases_metrics.ts @@ -16,7 +16,10 @@ export const getCasesMetricRoute = createCasesRoute({ path: CASE_METRICS_URL, params: { query: schema.object({ - features: schema.arrayOf(schema.string({ minLength: 1 })), + features: schema.oneOf([ + schema.arrayOf(schema.string({ minLength: 1 })), + schema.string({ minLength: 1 }), + ]), owner: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])), from: schema.maybe(schema.string()), to: schema.maybe(schema.string()), @@ -26,9 +29,12 @@ export const getCasesMetricRoute = createCasesRoute({ try { const caseContext = await context.cases; const client = await caseContext.getCasesClient(); + const { features } = request.query; + return response.ok({ body: await client.metrics.getCasesMetrics({ ...request.query, + features: Array.isArray(features) ? features : [features], }), }); } catch (error) { diff --git a/x-pack/test/cases_api_integration/common/lib/utils.ts b/x-pack/test/cases_api_integration/common/lib/utils.ts index bb8f31abefd47..825f50b792cc6 100644 --- a/x-pack/test/cases_api_integration/common/lib/utils.ts +++ b/x-pack/test/cases_api_integration/common/lib/utils.ts @@ -1010,13 +1010,13 @@ export const getCaseMetrics = async ({ }: { supertest: SuperTest.SuperTest; caseId: string; - features: string[]; + features: string[] | string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; }): Promise => { const { body: metricsResponse } = await supertest .get(`${getSpaceUrlPrefix(auth?.space)}${CASES_URL}/metrics/${caseId}`) - .query({ features: JSON.stringify(features) }) + .query({ features }) .auth(auth.user.username, auth.user.password) .expect(expectedHttpCode); @@ -1277,14 +1277,14 @@ export const getCasesMetrics = async ({ auth = { user: superUser, space: null }, }: { supertest: SuperTest.SuperTest; - features: string[]; + features: string[] | string; query?: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; }): Promise => { const { body: metricsResponse } = await supertest .get(`${getSpaceUrlPrefix(auth?.space)}${CASES_URL}/metrics`) - .query({ features: JSON.stringify(features), ...query }) + .query({ features, ...query }) .auth(auth.user.username, auth.user.password) .expect(expectedHttpCode); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics.ts index cf1b842db0fe7..d08a00ab4f088 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_case_metrics.ts @@ -30,6 +30,24 @@ export default ({ getService }: FtrProviderContext): void => { const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('case metrics', () => { + it('accepts the features as string', async () => { + const newCase = await createCase(supertest, getPostCaseRequest()); + + const metrics = await getCaseMetrics({ + supertest, + caseId: newCase.id, + features: 'connectors', + }); + + expect(metrics).to.eql({ + connectors: { + total: 0, + }, + }); + + await deleteAllCaseItems(es); + }); + describe('closed case from kbn archive', () => { const closedCaseId = 'e49ad6e0-cf9d-11eb-a603-13e7747d215z'; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_cases_metrics.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_cases_metrics.ts index c1abfada39dd2..e3e0c2cb20570 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_cases_metrics.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/metrics/get_cases_metrics.ts @@ -34,6 +34,17 @@ export default ({ getService }: FtrProviderContext): void => { const kibanaServer = getService('kibanaServer'); describe('all cases metrics', () => { + it('accepts the features as string', async () => { + const metrics = await getCasesMetrics({ + supertest, + features: 'mttr', + }); + + expect(metrics).to.eql({ mttr: 0 }); + + await deleteAllCaseItems(es); + }); + describe('MTTR', () => { it('responses with zero if there are no cases', async () => { const metrics = await getCasesMetrics({ From dc529800adfddb791da02879c6edb23a6647807d Mon Sep 17 00:00:00 2001 From: Matthew Kime Date: Wed, 4 May 2022 07:19:10 -0500 Subject: [PATCH 26/68] passing default selection enables selection. boo (#131473) --- .../components/index_pattern_table/index_pattern_table.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx index bff6ea4b82777..6ad017a323969 100644 --- a/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -316,7 +316,7 @@ export const IndexPatternTable = ({ pagination={pagination} sorting={sorting} search={search} - selection={selection} + selection={dataViews.getCanSaveSync() ? selection : undefined} /> {displayIndexPatternEditor} From 81161c26acfdaf443123b60cdca46955966575ca Mon Sep 17 00:00:00 2001 From: Bhavya RM Date: Wed, 4 May 2022 09:58:19 -0400 Subject: [PATCH 27/68] Fixing test data for import and export between versions tests (#131470) --- .../exports/_7.13_import_saved_objects.ndjson | 170 +++++++++--------- .../import_saved_objects_between_versions.ts | 2 +- 2 files changed, 84 insertions(+), 88 deletions(-) diff --git a/x-pack/test/functional/apps/saved_objects_management/exports/_7.13_import_saved_objects.ndjson b/x-pack/test/functional/apps/saved_objects_management/exports/_7.13_import_saved_objects.ndjson index 21be31349af0f..8f2aa535f305c 100644 --- a/x-pack/test/functional/apps/saved_objects_management/exports/_7.13_import_saved_objects.ndjson +++ b/x-pack/test/functional/apps/saved_objects_management/exports/_7.13_import_saved_objects.ndjson @@ -1,87 +1,83 @@ -{"attributes":{"accessCount":0,"accessDate":1621977234367,"createDate":1621977234367,"url":"/app/dashboards#/view/154944b0-6249-11eb-aebf-c306684b328d?embed=true&_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(description:%27%27,filters:!(),fullScreenMode:!f,options:(darkTheme:!f,hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(enhancements:()),gridData:(h:15,i:%271%27,w:24,x:0,y:0),id:%2736b91810-6239-11eb-aebf-c306684b328d%27,panelIndex:%271%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%272%27,w:24,x:24,y:0),id:%270a274320-61cc-11eb-aebf-c306684b328d%27,panelIndex:%272%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%273%27,w:24,x:0,y:15),id:e4aef350-623d-11eb-aebf-c306684b328d,panelIndex:%273%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%274%27,w:24,x:24,y:15),id:f92e5630-623e-11eb-aebf-c306684b328d,panelIndex:%274%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%275%27,w:24,x:0,y:30),id:%279853d4d0-623d-11eb-aebf-c306684b328d%27,panelIndex:%275%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%276%27,w:24,x:24,y:30),id:%276ecb33b0-623d-11eb-aebf-c306684b328d%27,panelIndex:%276%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%277%27,w:24,x:0,y:45),id:b8e35c80-623c-11eb-aebf-c306684b328d,panelIndex:%277%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%278%27,w:24,x:24,y:45),id:f1bc75d0-6239-11eb-aebf-c306684b328d,panelIndex:%278%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%279%27,w:24,x:0,y:60),id:%270d8a8860-623a-11eb-aebf-c306684b328d%27,panelIndex:%279%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2710%27,w:24,x:24,y:60),id:d79fe3d0-6239-11eb-aebf-c306684b328d,panelIndex:%2710%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2711%27,w:24,x:0,y:75),id:%27318375a0-6240-11eb-aebf-c306684b328d%27,panelIndex:%2711%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2712%27,w:24,x:24,y:75),id:e461eb20-6245-11eb-aebf-c306684b328d,panelIndex:%2712%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2713%27,w:24,x:0,y:90),id:%2725bdc750-6242-11eb-aebf-c306684b328d%27,panelIndex:%2713%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2714%27,w:24,x:24,y:90),id:%2771dd7bc0-6248-11eb-aebf-c306684b328d%27,panelIndex:%2714%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2715%27,w:24,x:0,y:105),id:%276aea48a0-6240-11eb-aebf-c306684b328d%27,panelIndex:%2715%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2716%27,w:24,x:24,y:105),id:%2732b681f0-6241-11eb-aebf-c306684b328d%27,panelIndex:%2716%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2717%27,w:24,x:0,y:120),id:ccca99e0-6244-11eb-aebf-c306684b328d,panelIndex:%2717%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2718%27,w:24,x:24,y:120),id:a4d7be80-6245-11eb-aebf-c306684b328d,panelIndex:%2718%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2719%27,w:24,x:0,y:135),id:c94d8440-6248-11eb-aebf-c306684b328d,panelIndex:%2719%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2720%27,w:24,x:24,y:135),id:db6226f0-61c0-11eb-aebf-c306684b328d,panelIndex:%2720%27,type:search,version:%277.13.1%27)),query:(language:lucene,query:%27%27),tags:!(),timeRestore:!f,title:logstash_dashboardwithtime,viewMode:view)"},"coreMigrationVersion":"7.13.2","id":"058bc10f0578013fc41ddedc9a1dcd1e","references":[],"sort":[1623693556928,448],"type":"url","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NDUsNF0="} -{"attributes":{"color":"#ba898f","description":"","name":"By value tag"},"coreMigrationVersion":"7.13.2","id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","references":[],"sort":[1623415891791,116],"type":"tag","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0MzEsNF0="} -{"attributes":{"fieldAttrs":"{\"ip\":{\"count\":2},\"geo.dest\":{\"count\":1}}","fields":"[]","runtimeFieldMap":"{}","timeFieldName":"@timestamp","title":"logstash-*"},"coreMigrationVersion":"7.13.2","id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1623415891791,120],"type":"index-pattern","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0MzMsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"60aaea59-d871-4e90-9ff3-78946d6bef90\"},\"panelIndex\":\"60aaea59-d871-4e90-9ff3-78946d6bef90\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\":{\"columns\":{\"65625f0d-e7f1-4370-b939-7db27af74de7\":{\"label\":\"Top values of geo.srcdest\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":true,\"params\":{\"size\":18,\"orderBy\":{\"type\":\"column\",\"columnId\":\"553a353f-dac5-4a52-a25d-52c6e1462597\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"553a353f-dac5-4a52-a25d-52c6e1462597\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"}},\"columnOrder\":[\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"553a353f-dac5-4a52-a25d-52c6e1462597\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\",\"groups\":[\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"65625f0d-e7f1-4370-b939-7db27af74de7\"],\"metric\":\"553a353f-dac5-4a52-a25d-52c6e1462597\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"43fcac20-ca27-11eb-bf5e-3de94e83d4f0\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"43fcac20-ca27-11eb-bf5e-3de94e83d4f0\",\"name\":\"indexpattern-datasource-layer-2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9ed45b8b-534b-4fac-9fee-436896b90039\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"circular drilldown\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}},\"type\":\"lens\"}}]","timeRestore":false,"title":"lens_panel_drilldown","version":1},"coreMigrationVersion":"7.13.2","id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"indexpattern-datasource-layer-2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea","type":"index-pattern"},{"id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","name":"drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9ed45b8b-534b-4fac-9fee-436896b90039:dashboardId","type":"dashboard"},{"id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","name":"tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1623415891791,125],"type":"dashboard","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0MzQsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"095e13b2-d0ac-47db-a62b-0aca28931402\"},\"panelIndex\":\"095e13b2-d0ac-47db-a62b-0aca28931402\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"f61694eb-94ed-495d-9ce8-63592f040b0b\":{\"columns\":{\"75ddcdb4-3050-4545-b401-509384b0d532\":{\"label\":\"Top values of machine.os.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"machine.os.raw\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"273e31ef-7c2d-4d0e-9063-5528f4011a51\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\"}},\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\":{\"label\":\"Average of bytes\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"75ddcdb4-3050-4545-b401-509384b0d532\",\"273e31ef-7c2d-4d0e-9063-5528f4011a51\",\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\",\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"f61694eb-94ed-495d-9ce8-63592f040b0b\",\"accessors\":[\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\",\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"273e31ef-7c2d-4d0e-9063-5528f4011a51\",\"splitAccessor\":\"75ddcdb4-3050-4545-b401-509384b0d532\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"43fcac20-ca27-11eb-bf5e-3de94e83d4f0\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"43fcac20-ca27-11eb-bf5e-3de94e83d4f0\",\"name\":\"indexpattern-datasource-layer-f61694eb-94ed-495d-9ce8-63592f040b0b\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"da7ad2b6-1e4a-40b5-9123-d0ec2bde858d\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"lens_panel_drilldown\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"map\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"153bb2dc-c4f5-4fcc-a45a-4e61cdaad8c2\"},\"panelIndex\":\"153bb2dc-c4f5-4fcc-a45a-4e61cdaad8c2\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"layerListJSON\":\"[{\\\"sourceDescriptor\\\":{\\\"type\\\":\\\"EMS_TMS\\\",\\\"isAutoSelect\\\":true},\\\"id\\\":\\\"16b378f6-4b68-4d17-8be4-3da333440869\\\",\\\"label\\\":null,\\\"minZoom\\\":0,\\\"maxZoom\\\":24,\\\"alpha\\\":1,\\\"visible\\\":true,\\\"style\\\":{\\\"type\\\":\\\"TILE\\\"},\\\"type\\\":\\\"VECTOR_TILE\\\"},{\\\"sourceDescriptor\\\":{\\\"indexPatternId\\\":\\\"43fcac20-ca27-11eb-bf5e-3de94e83d4f0\\\",\\\"geoField\\\":\\\"geo.coordinates\\\",\\\"filterByMapBounds\\\":true,\\\"scalingType\\\":\\\"CLUSTERS\\\",\\\"topHitsSplitField\\\":\\\"\\\",\\\"topHitsSize\\\":1,\\\"id\\\":\\\"86ff9ac9-9ccf-44b0-8b90-a4b779f5bc38\\\",\\\"type\\\":\\\"ES_SEARCH\\\",\\\"applyGlobalQuery\\\":true,\\\"applyGlobalTime\\\":true,\\\"tooltipProperties\\\":[\\\"extension\\\",\\\"geo.dest\\\",\\\"response\\\"],\\\"sortField\\\":\\\"\\\",\\\"sortOrder\\\":\\\"desc\\\"},\\\"id\\\":\\\"3d062d54-73de-4be7-8ae2-11e9b385f7d9\\\",\\\"label\\\":\\\"\\\",\\\"minZoom\\\":0,\\\"maxZoom\\\":24,\\\"alpha\\\":0.75,\\\"visible\\\":true,\\\"style\\\":{\\\"type\\\":\\\"VECTOR\\\",\\\"properties\\\":{\\\"icon\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"value\\\":\\\"marker\\\"}},\\\"fillColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#54B399\\\"}},\\\"lineColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#41937c\\\"}},\\\"lineWidth\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":1}},\\\"iconSize\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":6}},\\\"iconOrientation\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"orientation\\\":0}},\\\"labelText\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"value\\\":\\\"\\\"}},\\\"labelColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#000000\\\"}},\\\"labelSize\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":14}},\\\"labelBorderColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#FFFFFF\\\"}},\\\"symbolizeAs\\\":{\\\"options\\\":{\\\"value\\\":\\\"circle\\\"}},\\\"labelBorderSize\\\":{\\\"options\\\":{\\\"size\\\":\\\"SMALL\\\"}}},\\\"isTimeAware\\\":true},\\\"type\\\":\\\"BLENDED_VECTOR\\\",\\\"joins\\\":[]}]\",\"mapStateJSON\":\"{\\\"zoom\\\":1.38,\\\"center\\\":{\\\"lon\\\":0,\\\"lat\\\":19.94277},\\\"timeFilters\\\":{\\\"from\\\":\\\"now-15y\\\",\\\"to\\\":\\\"now\\\"},\\\"refreshConfig\\\":{\\\"isPaused\\\":true,\\\"interval\\\":0},\\\"query\\\":{\\\"query\\\":\\\"\\\",\\\"language\\\":\\\"kuery\\\"},\\\"filters\\\":[],\\\"settings\\\":{\\\"autoFitToDataBounds\\\":false,\\\"backgroundColor\\\":\\\"#ffffff\\\",\\\"disableInteractive\\\":false,\\\"disableTooltipControl\\\":false,\\\"hideToolbarOverlay\\\":false,\\\"hideLayerControl\\\":false,\\\"hideViewControl\\\":false,\\\"initialLocation\\\":\\\"LAST_SAVED_LOCATION\\\",\\\"fixedLocation\\\":{\\\"lat\\\":0,\\\"lon\\\":0,\\\"zoom\\\":2},\\\"browserLocation\\\":{\\\"zoom\\\":2},\\\"maxZoom\\\":24,\\\"minZoom\\\":0,\\\"showScaleControl\\\":false,\\\"showSpatialFilters\\\":true,\\\"spatialFiltersAlpa\\\":0.3,\\\"spatialFiltersFillColor\\\":\\\"#DA8B45\\\",\\\"spatialFiltersLineColor\\\":\\\"#DA8B45\\\"}}\",\"uiStateJSON\":\"{\\\"isLayerTOCOpen\\\":true,\\\"openTOCDetails\\\":[]}\"},\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.38},\"mapBuffer\":{\"minLon\":-214.7723,\"minLat\":-74.644155,\"maxLon\":214.7723,\"maxLat\":102.864625},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"b10e564b-7d42-45f5-8c26-a9220c405834\",\"triggers\":[\"CONTEXT_MENU_TRIGGER\"],\"action\":{\"name\":\"URL drilldown\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/0abce1c0-ca2a-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:geo.srcdest,negate:!f,params:!('IN:CN'),type:phrases,value:'IN:CN'),query:(bool:(minimum_should_match:1,should:!((match_phrase:(geo.srcdest:'IN:CN'))))))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}}]}},\"type\":\"map\"}},{\"version\":\"7.13.1\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"5de83d82-bbd1-4d30-be61-dd6724f32c07\"},\"panelIndex\":\"5de83d82-bbd1-4d30-be61-dd6724f32c07\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"metrics\",\"params\":{\"annotations\":[{\"fields\":\"response.raw\",\"template\":\"{{response.raw}}\",\"index_pattern\":\"logstash-*\",\"query_string\":{\"query\":\"response.raw :\\\"404\\\" \",\"language\":\"kuery\"},\"color\":\"#F00\",\"icon\":\"fa-bomb\",\"id\":\"37395960-ca28-11eb-9eac-2f3ccefcbeef\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1,\"time_field\":\"@timestamp\"}],\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"axis_scale\":\"normal\",\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"index_pattern\":\"logstash-*\",\"interval\":\"\",\"isModelInvalid\":false,\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"number\",\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"line_width\":1,\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"point_size\":1,\"separate_axis\":0,\"split_color_mode\":\"kibana\",\"split_mode\":\"everything\",\"stacked\":\"none\"}],\"show_grid\":1,\"show_legend\":1,\"time_field\":\"@timestamp\",\"tooltip_mode\":\"show_all\",\"type\":\"timeseries\",\"use_kibana_indexes\":false},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"23d04651-266f-4f0a-8eef-6f190f0a84af\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"dashboard\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}},\"type\":\"visualization\"}},{\"version\":\"7.13.1\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"a254a623-a9af-4372-851b-572fa95b0902\"},\"panelIndex\":\"a254a623-a9af-4372-851b-572fa95b0902\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n/*\\n\\nWelcome to Vega visualizations. Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite. In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it. Use help icon to view Vega examples, tutorials, and other docs. Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range. You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n $schema: https://vega.github.io/schema/vega-lite/v4.json\\n title: Event counts from all indexes\\n\\n // Define the data source\\n data: {\\n url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\". They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n // Apply dashboard context filters when set\\n %context%: true\\n // Filter the time picker (upper right corner) with this field\\n %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for : https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n // Which index to search\\n index: _all\\n // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n body: {\\n aggs: {\\n time_buckets: {\\n date_histogram: {\\n // Use date histogram aggregation on @timestamp field\\n field: @timestamp\\n // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n interval: {%autointerval%: true}\\n // Make sure we get an entire range, even if it has no data\\n extended_bounds: {\\n // Use the current time range's start and end\\n min: {%timefilter%: \\\"min\\\"}\\n max: {%timefilter%: \\\"max\\\"}\\n }\\n // Use this for linear (e.g. line, area) graphs. Without it, empty buckets will not show up\\n min_doc_count: 0\\n }\\n }\\n }\\n // Speed up the response by only including aggregation results\\n size: 0\\n }\\n }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n time_buckets: {\\n buckets: [\\n {\\n key_as_string: 2015-11-30T22:00:00.000Z\\n key: 1448920800000\\n doc_count: 0\\n },\\n {\\n key_as_string: 2015-11-30T23:00:00.000Z\\n key: 1448924400000\\n doc_count: 0\\n }\\n ...\\n ]\\n }\\n}\\n\\nFor our graph, we only need the list of bucket values. Use the format.property to discard everything else.\\n*/\\n format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n }\\n\\n // \\\"mark\\\" is the graphics element used to show our data. Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick. See https://vega.github.io/vega-lite/docs/mark.html\\n mark: line\\n\\n // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way. See https://vega.github.io/vega-lite/docs/encoding.html\\n encoding: {\\n x: {\\n // The \\\"key\\\" value is the timestamp in milliseconds. Use it for X axis.\\n field: key\\n type: temporal\\n axis: {title: false} // Customize X axis format\\n }\\n y: {\\n // The \\\"doc_count\\\" is the count per bucket. Use it for Y axis.\\n field: doc_count\\n type: quantitative\\n axis: {title: \\\"Document count\\\"}\\n }\\n }\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"index\":\"43fcac20-ca27-11eb-bf5e-3de94e83d4f0\",\"key\":\"geo.srcdest\",\"negate\":false,\"params\":{\"query\":\"CN:CN\"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"geo.srcdest\":\"CN:CN\"}}}]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"cfd2521d-15a0-4c64-b0ab-d2dc18f396e3\",\"triggers\":[\"CONTEXT_MENU_TRIGGER\"],\"action\":{\"name\":\"URL\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/4acce030-ca2a-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:ip,negate:!f,params:(query:'57.237.11.219'),type:phrase),query:(match_phrase:(ip:'57.237.11.219')))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}}]}},\"type\":\"visualization\"}},{\"version\":\"7.13.1\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"7f0506ed-1f30-410f-bcd7-3f70623aa5ba\"},\"panelIndex\":\"7f0506ed-1f30-410f-bcd7-3f70623aa5ba\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true},\"uiState\":{},\"data\":{\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"significant_terms\",\"params\":{\"field\":\"geo.srcdest\",\"size\":77},\"schema\":\"segment\"}],\"searchSource\":{\"index\":\"43fcac20-ca27-11eb-bf5e-3de94e83d4f0\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{},\"type\":\"visualization\"}}]","timeRestore":false,"title":"logstash_by_value_dashboard","version":1},"coreMigrationVersion":"7.13.2","id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"indexpattern-datasource-layer-f61694eb-94ed-495d-9ce8-63592f040b0b","type":"index-pattern"},{"id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","name":"drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:da7ad2b6-1e4a-40b5-9123-d0ec2bde858d:dashboardId","type":"dashboard"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"layer_1_source_index_pattern","type":"index-pattern"},{"id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","name":"drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:23d04651-266f-4f0a-8eef-6f190f0a84af:dashboardId","type":"dashboard"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","name":"tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1623415891791,134],"type":"dashboard","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0MzUsNF0="} -{"attributes":{"fieldAttrs":"{\"machine.os\":{\"count\":1},\"spaces\":{\"count\":1},\"type\":{\"count\":1},\"bytes_scripted\":{\"count\":1}}","fields":"[{\"count\":1,\"script\":\"doc['bytes'].value*1024\",\"lang\":\"painless\",\"name\":\"bytes_scripted\",\"type\":\"number\",\"scripted\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]","runtimeFieldMap":"{}","timeFieldName":"@timestamp","title":"logstash-*"},"coreMigrationVersion":"7.13.2","id":"56b34100-619d-11eb-aebf-c306684b328d","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1623693556928,449],"type":"index-pattern","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NDYsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_scriptedfieldviz","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}","version":1,"visState":"{\"title\":\"logstash_scriptedfieldviz\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":true,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes_scripted\",\"ranges\":[{\"from\":0,\"to\":40000},{\"from\":40001,\"to\":20000000}]}}]}"},"coreMigrationVersion":"7.13.2","id":"0a274320-61cc-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,451],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NDcsNF0="} -{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"type\":\"phrases\",\"key\":\"geo.srcdest\",\"value\":\"IN:CN\",\"params\":[\"IN:CN\"],\"alias\":null,\"negate\":false,\"disabled\":false,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"bool\":{\"should\":[{\"match_phrase\":{\"geo.srcdest\":\"IN:CN\"}}],\"minimum_should_match\":1}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"search_saved","version":1},"coreMigrationVersion":"7.13.2","id":"0abce1c0-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1623415891791,137],"type":"search","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0MzYsNF0="} -{"attributes":{"color":"#81a93f","description":"","name":"logstash_tag"},"coreMigrationVersion":"7.13.2","id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","references":[],"sort":[1623693556928,452],"type":"tag","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NDgsNF0="} -{"attributes":{"description":"","layerListJSON":"[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"4c2394ca-a6a2-4f8d-9631-259eb3a9627f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"},{\"sourceDescriptor\":{\"geoField\":\"geo.coordinates\",\"filterByMapBounds\":true,\"scalingType\":\"CLUSTERS\",\"id\":\"7555324e-e793-4b7d-a9d2-cd63e6b7fe3d\",\"type\":\"ES_SEARCH\",\"applyGlobalQuery\":true,\"applyGlobalTime\":true,\"tooltipProperties\":[\"geo.srcdest\",\"machine.os\",\"type\"],\"sortField\":\"bytes_scripted\",\"sortOrder\":\"desc\",\"topHitsSplitField\":\"\",\"topHitsSize\":1,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"id\":\"6a493d8b-a220-46bc-8906-a1a7569799e0\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"colorCategory\":\"palette_0\",\"field\":{\"name\":\"extension.raw\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3},\"type\":\"CATEGORICAL\"}},\"lineColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"colorCategory\":\"palette_0\",\"field\":{\"name\":\"machine.os.raw\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3},\"type\":\"CATEGORICAL\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"type\":\"BLENDED_VECTOR\",\"joins\":[]}]","mapStateJSON":"{\"zoom\":1.56,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15y\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"logstash_maps","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"7.13.2","id":"0c5974f0-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"map":"7.12.0"},"references":[{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"layer_1_source_index_pattern","type":"index-pattern"}],"sort":[1623693556928,455],"type":"map","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NDksNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_datatable","uiStateJSON":"{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}","version":1,"visState":"{\"title\":\"logstash_datatable\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":true,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"bucket\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"response.raw\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"0d8a8860-623a-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,457],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTAsNF0="} -{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"35fd070e-5bbc-4906-bf69-8548a213d7a0":{"columnOrder":["2bf7969f-0371-4df2-a398-0a191e428ce5","aab812d6-609b-444d-9990-1e67f85fd85d","e9829e8a-c484-4c9d-b489-f1eb3fb138d2","4fc9fb3b-29a5-4679-ab3c-90d5daaf0661"],"columns":{"2bf7969f-0371-4df2-a398-0a191e428ce5":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"4fc9fb3b-29a5-4679-ab3c-90d5daaf0661":{"dataType":"number","isBucketed":false,"label":"Moving average of Median of bytes","operationType":"moving_average","params":{"window":5},"references":["e9829e8a-c484-4c9d-b489-f1eb3fb138d2"],"scale":"ratio"},"aab812d6-609b-444d-9990-1e67f85fd85d":{"dataType":"number","isBucketed":false,"label":"Average of bytes","operationType":"average","scale":"ratio","sourceField":"bytes"},"e9829e8a-c484-4c9d-b489-f1eb3fb138d2":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","scale":"ratio","sourceField":"bytes"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["aab812d6-609b-444d-9990-1e67f85fd85d","4fc9fb3b-29a5-4679-ab3c-90d5daaf0661"],"layerId":"35fd070e-5bbc-4906-bf69-8548a213d7a0","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"2bf7969f-0371-4df2-a398-0a191e428ce5"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barvertical_stacked_average","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-35fd070e-5bbc-4906-bf69-8548a213d7a0","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,461],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTEsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_area_chart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_area_chart\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2010-01-28T19:25:55.242Z\",\"to\":\"2021-01-28T19:40:55.242Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"machine OS\"}}]}"},"coreMigrationVersion":"7.13.2","id":"36b91810-6239-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,463],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTIsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_horizontal","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_horizontal\",\"type\":\"horizontal_bar\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":200},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":75,\"filter\":true,\"truncate\":100},\"title\":{\"text\":\"no of documents\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"normal\",\"data\":{\"label\":\"no of documents\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"no of documents\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"agent.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"extension.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"e4aef350-623d-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,465],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTMsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_linechart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_linechart\",\"type\":\"line\",\"params\":{\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"radiusRatio\":51,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-09-18T06:38:43.311Z\",\"to\":\"2015-09-26T04:02:51.104Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"radius\",\"params\":{\"field\":\"bytes\",\"customLabel\":\"bubbles\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"f92e5630-623e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,467],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTQsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_heatmap","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0% - 25%\":\"rgb(255,255,204)\",\"25% - 50%\":\"rgb(254,217,118)\",\"50% - 75%\":\"rgb(253,141,60)\",\"75% - 100%\":\"rgb(227,27,28)\"}}}","version":1,"visState":"{\"title\":\"logstash_heatmap\",\"type\":\"heatmap\",\"params\":{\"type\":\"heatmap\",\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Yellow to Red\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":true,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"overwriteColor\":false,\"color\":\"#555\"}}],\"row\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"response.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"9853d4d0-623d-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,469],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTUsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_goalchart","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0 - 33\":\"rgb(0,104,55)\",\"33 - 67\":\"rgb(255,255,190)\",\"67 - 100\":\"rgb(165,0,38)\"}}}","version":1,"visState":"{\"title\":\"logstash_goalchart\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":true,\"gaugeType\":\"Circle\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000},{\"from\":10001,\"to\":20000},{\"from\":20001,\"to\":30000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60},\"minAngle\":0,\"maxAngle\":6.283185307179586}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"group\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}]}"},"coreMigrationVersion":"7.13.2","id":"6ecb33b0-623d-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,471],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTYsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_gauge","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0 - 50\":\"rgb(0,104,55)\",\"50 - 75\":\"rgb(255,255,190)\",\"75 - 100\":\"rgb(165,0,38)\"}}}","version":1,"visState":"{\"title\":\"logstash_gauge\",\"type\":\"gauge\",\"params\":{\"type\":\"gauge\",\"addTooltip\":true,\"addLegend\":true,\"isDisplayWarning\":false,\"gauge\":{\"extendRange\":true,\"percentageMode\":false,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Labels\",\"colorsRange\":[{\"from\":0,\"to\":50},{\"from\":50,\"to\":75},{\"from\":75,\"to\":100}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\"},\"type\":\"meter\",\"style\":{\"bgWidth\":0.9,\"width\":0.9,\"mask\":false,\"bgMask\":false,\"maskBars\":50,\"bgFill\":\"#eee\",\"bgColor\":false,\"subText\":\"\",\"fontSize\":60,\"labelColor\":true},\"alignment\":\"horizontal\"}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes\",\"ranges\":[{\"from\":0,\"to\":10001},{\"from\":10002,\"to\":1000000}],\"json\":\"\"}}]}"},"coreMigrationVersion":"7.13.2","id":"b8e35c80-623c-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,473],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTcsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_coordinatemaps","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_coordinatemaps\",\"type\":\"tile_map\",\"params\":{\"colorSchema\":\"Yellow to Red\",\"mapType\":\"Scaled Circle Markers\",\"isDesaturated\":false,\"addTooltip\":true,\"heatClusterSize\":1.5,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[0,0],\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"selectedTmsLayer\":{\"origin\":\"elastic_maps_service\",\"id\":\"road_map\",\"minZoom\":0,\"maxZoom\":18,\"attribution\":\"

© OpenStreetMap contributors|OpenMapTiles|Elastic Maps Service

\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.coordinates\",\"autoPrecision\":true,\"isFilteredByCollar\":true,\"useGeocentroid\":true,\"mapZoom\":2,\"mapCenter\":[0,0],\"precision\":2,\"customLabel\":\"logstash src/dest\"}}]}"},"coreMigrationVersion":"7.13.2","id":"f1bc75d0-6239-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,475],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTgsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"logstash_inputcontrols","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_inputcontrols\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1611928563867\",\"fieldName\":\"machine.ram\",\"parent\":\"\",\"label\":\"Logstash RAM\",\"type\":\"range\",\"options\":{\"decimalPlaces\":0,\"step\":1024},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1611928586274\",\"fieldName\":\"machine.os.raw\",\"parent\":\"\",\"label\":\"Logstash OS\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"},"coreMigrationVersion":"7.13.2","id":"d79fe3d0-6239-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"control_0_index_pattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"control_1_index_pattern","type":"index-pattern"}],"sort":[1623693556928,478],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NTksNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"logstash_markdown","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_markdown\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":true,\"markdown\":\"Kibana is built with JS https://www.javascript.com/\"},\"aggs\":[]}"},"coreMigrationVersion":"7.13.2","id":"318375a0-6240-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1623693556928,479],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjAsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"logstash_vegaviz","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_vegaviz\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n/*\\n\\nWelcome to Vega visualizations. Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite. In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it. Use help icon to view Vega examples, tutorials, and other docs. Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range. You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n $schema: https://vega.github.io/schema/vega-lite/v2.json\\n title: Event counts from all indexes\\n\\n // Define the data source\\n data: {\\n url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\". They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n // Apply dashboard context filters when set\\n %context%: true\\n // Filter the time picker (upper right corner) with this field\\n %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for : https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n // Which index to search\\n index: logstash-*\\n // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n body: {\\n aggs: {\\n time_buckets: {\\n date_histogram: {\\n // Use date histogram aggregation on @timestamp field\\n field: @timestamp\\n // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n interval: {%autointerval%: true}\\n // Make sure we get an entire range, even if it has no data\\n extended_bounds: {\\n // Use the current time range's start and end\\n min: {%timefilter%: \\\"min\\\"}\\n max: {%timefilter%: \\\"max\\\"}\\n }\\n // Use this for linear (e.g. line, area) graphs. Without it, empty buckets will not show up\\n min_doc_count: 13\\n }\\n }\\n }\\n // Speed up the response by only including aggregation results\\n size: 0\\n }\\n }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n time_buckets: {\\n buckets: [\\n {\\n key_as_string: 2015-11-30T22:00:00.000Z\\n key: 1448920800000\\n doc_count: 0\\n },\\n {\\n key_as_string: 2015-11-30T23:00:00.000Z\\n key: 1448924400000\\n doc_count: 0\\n }\\n ...\\n ]\\n }\\n}\\n\\nFor our graph, we only need the list of bucket values. Use the format.property to discard everything else.\\n*/\\n format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n }\\n\\n // \\\"mark\\\" is the graphics element used to show our data. Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick. See https://vega.github.io/vega-lite/docs/mark.html\\n mark: line\\n\\n // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way. See https://vega.github.io/vega-lite/docs/encoding.html\\n encoding: {\\n x: {\\n // The \\\"key\\\" value is the timestamp in milliseconds. Use it for X axis.\\n field: key\\n type: temporal\\n axis: {title: false} // Customize X axis format\\n }\\n y: {\\n // The \\\"doc_count\\\" is the count per bucket. Use it for Y axis.\\n field: doc_count\\n type: quantitative\\n axis: {title: \\\"Document count\\\"}\\n }\\n }\\n}\\n\"},\"aggs\":[]}"},"coreMigrationVersion":"7.13.2","id":"e461eb20-6245-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1623693556928,480],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjEsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_regionmap","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_regionmap\",\"type\":\"region_map\",\"params\":{\"addTooltip\":true,\"colorSchema\":\"Yellow to Red\",\"emsHotLink\":\"https://maps.elastic.co/v6.7?locale=en#file/world_countries\",\"isDisplayWarning\":true,\"legendPosition\":\"bottomright\",\"mapCenter\":[0,0],\"mapZoom\":2,\"outlineWeight\":1,\"selectedJoinField\":{\"type\":\"id\",\"name\":\"iso2\",\"description\":\"ISO 3166-1 alpha-2 code\"},\"showAllShapes\":true,\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"selectedTmsLayer\":{\"origin\":\"elastic_maps_service\",\"id\":\"road_map\",\"minZoom\":0,\"maxZoom\":18,\"attribution\":\"

© OpenStreetMap contributors|OpenMapTiles|Elastic Maps Service

\"}},\"selectedLayer\":{\"name\":\"World Countries\",\"origin\":\"elastic_maps_service\",\"id\":\"world_countries\",\"created_at\":\"2017-04-26T17:12:15.978370\",\"attribution\":\"Made with NaturalEarth | Elastic Maps Service\",\"fields\":[{\"type\":\"id\",\"name\":\"iso2\",\"description\":\"ISO 3166-1 alpha-2 code\"},{\"type\":\"id\",\"name\":\"iso3\",\"description\":\"ISO 3166-1 alpha-3 code\"},{\"type\":\"property\",\"name\":\"name\",\"description\":\"name\"}],\"format\":{\"type\":\"geojson\"},\"layerId\":\"elastic_maps_service.World Countries\",\"isEMS\":true}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.dest\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"25bdc750-6242-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,482],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjIsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_verticalbarchart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_verticalbarchart\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\",\"defaultYExtents\":true},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":true,\"row\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-09-18T06:38:43.311Z\",\"to\":\"2015-09-26T04:02:51.104Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"h\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"scaleMetricValues\":true}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"response.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Response code\"}}]}"},"coreMigrationVersion":"7.13.2","id":"71dd7bc0-6248-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,484],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjMsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_metricviz","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_metricviz\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes_scripted\",\"ranges\":[{\"from\":0,\"to\":10000},{\"from\":10001,\"to\":300000}]}}]}"},"coreMigrationVersion":"7.13.2","id":"6aea48a0-6240-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,486],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjQsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_piechart","uiStateJSON":"{}","version":1,"visState":"{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"field\":\"machine.os.raw\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"size\":5},\"schema\":\"segment\",\"type\":\"terms\"}],\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":true,\"labels\":{\"last_level\":true,\"show\":false,\"truncate\":100,\"values\":true},\"legendPosition\":\"right\",\"type\":\"pie\"},\"title\":\"logstash_piechart\",\"type\":\"pie\"}"},"coreMigrationVersion":"7.13.2","id":"32b681f0-6241-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,488],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjUsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_tagcloud","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_tagcloud\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"log\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.srcdest\",\"size\":23,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"ccca99e0-6244-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,490],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjYsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"title":"logstash_timelion","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_timelion\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(q='machine.os.raw:win xp' , index=logstash-*)\",\"interval\":\"auto\"},\"aggs\":[]}"},"coreMigrationVersion":"7.13.2","id":"a4d7be80-6245-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1623693556928,491],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjcsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{}"},"title":"logstash_tsvb","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_tsvb\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"show_grid\":1,\"annotations\":[{\"fields\":\"machine.os.raw\",\"template\":\"{{machine.os.raw}}\",\"index_pattern\":\"logstash-*\",\"query_string\":{\"query\":\"machine.os.raw :\\\"win xp\\\" \",\"language\":\"lucene\"},\"id\":\"aa43ceb0-6248-11eb-9a82-ef1c6e6c0265\",\"color\":\"#F00\",\"time_field\":\"@timestamp\",\"icon\":\"fa-tag\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1}],\"use_kibana_indexes\":false},\"aggs\":[]}"},"coreMigrationVersion":"7.13.2","id":"c94d8440-6248-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1623693556928,492],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjgsNF0="} -{"attributes":{"columns":["bytes_scripted"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"machine.os.raw :\\\"win xp\\\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"logstash_scripted_saved_search","version":1},"coreMigrationVersion":"7.13.2","id":"db6226f0-61c0-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,494],"type":"search","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NjksNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"7\",\"w\":24,\"x\":0,\"y\":45},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"8\",\"w\":24,\"x\":24,\"y\":45},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"9\",\"w\":24,\"x\":0,\"y\":60},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"10\",\"w\":24,\"x\":24,\"y\":60},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"11\",\"w\":24,\"x\":0,\"y\":75},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"12\",\"w\":24,\"x\":24,\"y\":75},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"13\",\"w\":24,\"x\":0,\"y\":90},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"14\",\"w\":24,\"x\":24,\"y\":90},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"15\",\"w\":24,\"x\":0,\"y\":105},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"16\",\"w\":24,\"x\":24,\"y\":105},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"17\",\"w\":24,\"x\":0,\"y\":120},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"18\",\"w\":24,\"x\":24,\"y\":120},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"19\",\"w\":24,\"x\":0,\"y\":135},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"20\",\"w\":24,\"x\":24,\"y\":135},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"}]","timeRestore":false,"title":"logstash_dashboardwithtime","version":1},"coreMigrationVersion":"7.13.2","id":"154944b0-6249-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"36b91810-6239-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"0a274320-61cc-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"e4aef350-623d-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"f92e5630-623e-11eb-aebf-c306684b328d","name":"4:panel_4","type":"visualization"},{"id":"9853d4d0-623d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"visualization"},{"id":"6ecb33b0-623d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"visualization"},{"id":"b8e35c80-623c-11eb-aebf-c306684b328d","name":"7:panel_7","type":"visualization"},{"id":"f1bc75d0-6239-11eb-aebf-c306684b328d","name":"8:panel_8","type":"visualization"},{"id":"0d8a8860-623a-11eb-aebf-c306684b328d","name":"9:panel_9","type":"visualization"},{"id":"d79fe3d0-6239-11eb-aebf-c306684b328d","name":"10:panel_10","type":"visualization"},{"id":"318375a0-6240-11eb-aebf-c306684b328d","name":"11:panel_11","type":"visualization"},{"id":"e461eb20-6245-11eb-aebf-c306684b328d","name":"12:panel_12","type":"visualization"},{"id":"25bdc750-6242-11eb-aebf-c306684b328d","name":"13:panel_13","type":"visualization"},{"id":"71dd7bc0-6248-11eb-aebf-c306684b328d","name":"14:panel_14","type":"visualization"},{"id":"6aea48a0-6240-11eb-aebf-c306684b328d","name":"15:panel_15","type":"visualization"},{"id":"32b681f0-6241-11eb-aebf-c306684b328d","name":"16:panel_16","type":"visualization"},{"id":"ccca99e0-6244-11eb-aebf-c306684b328d","name":"17:panel_17","type":"visualization"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"18:panel_18","type":"visualization"},{"id":"c94d8440-6248-11eb-aebf-c306684b328d","name":"19:panel_19","type":"visualization"},{"id":"db6226f0-61c0-11eb-aebf-c306684b328d","name":"20:panel_20","type":"search"}],"sort":[1623693556928,515],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzAsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"26e2cf99-d931-4320-9e15-9dbc148f3534":{"columnOrder":["6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e","beb72af1-239c-46d8-823b-b00d1e2ace43"],"columns":{"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e":{"dataType":"string","isBucketed":true,"label":"Top values of url.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"beb72af1-239c-46d8-823b-b00d1e2ace43","type":"column"},"orderDirection":"desc","otherBucket":true,"size":20},"scale":"ordinal","sourceField":"url.raw"},"beb72af1-239c-46d8-823b-b00d1e2ace43":{"dataType":"number","isBucketed":false,"label":"Unique count of geo.srcdest","operationType":"unique_count","scale":"ratio","sourceField":"geo.srcdest"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e","6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e","6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e"],"layerId":"26e2cf99-d931-4320-9e15-9dbc148f3534","legendDisplay":"default","metric":"beb72af1-239c-46d8-823b-b00d1e2ace43","nestedLegend":false,"numberDisplay":"percent"}],"shape":"donut"}},"title":"lens_pie_chart","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.2","id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,519],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzEsNF0="} -{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"a3ac0e3d-63ec-49b2-882a-b34680a967ba":{"columnOrder":["352a2c02-aa6f-4a35-b776-45c3715a6c5e","8ef68cbb-e039-49d6-b15e-be81559f4b55","14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a"],"columns":{"14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"352a2c02-aa6f-4a35-b776-45c3715a6c5e":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a","type":"column"},"orderDirection":"desc","otherBucket":true,"size":67},"scale":"ordinal","sourceField":"geo.srcdest"},"8ef68cbb-e039-49d6-b15e-be81559f4b55":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a"],"layerId":"a3ac0e3d-63ec-49b2-882a-b34680a967ba","position":"top","seriesType":"bar_percentage_stacked","showGridlines":false,"splitAccessor":"352a2c02-aa6f-4a35-b776-45c3715a6c5e","xAccessor":"8ef68cbb-e039-49d6-b15e-be81559f4b55"}],"legend":{"isVisible":true,"position":"top","showSingleSeries":true},"preferredSeriesType":"bar_percentage_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_bar_verticalpercentage","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-a3ac0e3d-63ec-49b2-882a-b34680a967ba","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,523],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzIsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"037b7937-790b-4d2d-94a5-7f5837a6ef05":{"columnOrder":["b3d46616-75e0-419e-97ea-91148961ef94","025a0fb3-dc44-4f5c-b517-2d71d3f26f14","c476db14-0cc1-40ec-863e-d2779256a407"],"columns":{"025a0fb3-dc44-4f5c-b517-2d71d3f26f14":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"b3d46616-75e0-419e-97ea-91148961ef94":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c476db14-0cc1-40ec-863e-d2779256a407","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"geo.srcdest"},"c476db14-0cc1-40ec-863e-d2779256a407":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"lucene","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c476db14-0cc1-40ec-863e-d2779256a407"],"layerId":"037b7937-790b-4d2d-94a5-7f5837a6ef05","position":"top","seriesType":"bar_stacked","showGridlines":false,"splitAccessor":"b3d46616-75e0-419e-97ea-91148961ef94","xAccessor":"025a0fb3-dc44-4f5c-b517-2d71d3f26f14"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barchart_vertical","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,527],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzMsNF0="} -{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"212688dc-e7d7-4875-a221-09e6191bdcf7":{"columnOrder":["05410186-83c4-460a-82bf-dd7e9d998c9f","e8659feb-1db4-4706-9147-ac1fd513a1ba","c9a32fd0-a465-44fb-8adc-b957fb72cad5"],"columns":{"05410186-83c4-460a-82bf-dd7e9d998c9f":{"dataType":"string","isBucketed":true,"label":"Top values of extension.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c9a32fd0-a465-44fb-8adc-b957fb72cad5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"extension.raw"},"c9a32fd0-a465-44fb-8adc-b957fb72cad5":{"dataType":"number","isBucketed":false,"label":"Average of bytes","operationType":"average","scale":"ratio","sourceField":"bytes"},"e8659feb-1db4-4706-9147-ac1fd513a1ba":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c9a32fd0-a465-44fb-8adc-b957fb72cad5"],"layerId":"212688dc-e7d7-4875-a221-09e6191bdcf7","position":"top","seriesType":"bar_horizontal_stacked","showGridlines":false,"splitAccessor":"05410186-83c4-460a-82bf-dd7e9d998c9f","xAccessor":"e8659feb-1db4-4706-9147-ac1fd513a1ba"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_horizontal_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barhorizontal_stacked","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-212688dc-e7d7-4875-a221-09e6191bdcf7","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,531],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzQsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"7ab04fd4-04da-4023-8899-d94620193607":{"columnOrder":["0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7","9eb851dd-31f6-481a-84d1-9ecce53a6ad2","f6b271a7-509b-4c37-b7b6-ac5be4bcb49a"],"columns":{"0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7":{"dataType":"string","isBucketed":true,"label":"Top values of request.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"f6b271a7-509b-4c37-b7b6-ac5be4bcb49a","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"request.raw"},"9eb851dd-31f6-481a-84d1-9ecce53a6ad2":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"f6b271a7-509b-4c37-b7b6-ac5be4bcb49a":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["f6b271a7-509b-4c37-b7b6-ac5be4bcb49a"],"layerId":"7ab04fd4-04da-4023-8899-d94620193607","position":"top","seriesType":"bar_horizontal_percentage_stacked","showGridlines":false,"splitAccessor":"0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7","xAccessor":"9eb851dd-31f6-481a-84d1-9ecce53a6ad2"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_horizontal_percentage_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barhorizontalpercentage","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-7ab04fd4-04da-4023-8899-d94620193607","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,535],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzUsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"037b7937-790b-4d2d-94a5-7f5837a6ef05":{"columnOrder":["b3d46616-75e0-419e-97ea-91148961ef94","025a0fb3-dc44-4f5c-b517-2d71d3f26f14","c476db14-0cc1-40ec-863e-d2779256a407"],"columns":{"025a0fb3-dc44-4f5c-b517-2d71d3f26f14":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"b3d46616-75e0-419e-97ea-91148961ef94":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c476db14-0cc1-40ec-863e-d2779256a407","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"geo.srcdest"},"c476db14-0cc1-40ec-863e-d2779256a407":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"lucene","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c476db14-0cc1-40ec-863e-d2779256a407"],"layerId":"037b7937-790b-4d2d-94a5-7f5837a6ef05","position":"top","seriesType":"bar_stacked","showGridlines":false,"splitAccessor":"b3d46616-75e0-419e-97ea-91148961ef94","xAccessor":"025a0fb3-dc44-4f5c-b517-2d71d3f26f14"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_visualization","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693677171,767],"type":"lens","updated_at":"2021-06-14T18:01:17.171Z","version":"WzE3NDEsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"72783e5f-aa7b-4b8a-b26c-a3e4d051340e":{"columnOrder":["0f619652-9ff1-453b-ae1f-7371baa82f55"],"columns":{"0f619652-9ff1-453b-ae1f-7371baa82f55":{"dataType":"number","isBucketed":false,"label":"Average of phpmemory","operationType":"average","params":{"format":{"id":"percent","params":{"decimals":10}}},"scale":"ratio","sourceField":"phpmemory"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"accessor":"0f619652-9ff1-453b-ae1f-7371baa82f55","layerId":"72783e5f-aa7b-4b8a-b26c-a3e4d051340e"}},"title":"lens_metric","visualizationType":"lnsMetric"},"coreMigrationVersion":"7.13.2","id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-72783e5f-aa7b-4b8a-b26c-a3e4d051340e","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,543],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzcsNF0="} -{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"bb478774-f9e8-4380-bf3a-f4a89a4d79b5":{"columnOrder":["4573ae8f-8f9d-4918-b496-c08f7102c6e1","cebdc6c5-3587-4f57-879c-dd63ea99cf03"],"columns":{"4573ae8f-8f9d-4918-b496-c08f7102c6e1":{"dataType":"string","isBucketed":true,"label":"Top values of machine.os.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"cebdc6c5-3587-4f57-879c-dd63ea99cf03","type":"column"},"orderDirection":"desc","otherBucket":true,"size":5},"scale":"ordinal","sourceField":"machine.os.raw"},"cebdc6c5-3587-4f57-879c-dd63ea99cf03":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["4573ae8f-8f9d-4918-b496-c08f7102c6e1"],"layerId":"bb478774-f9e8-4380-bf3a-f4a89a4d79b5","legendDisplay":"default","metric":"cebdc6c5-3587-4f57-879c-dd63ea99cf03","nestedLegend":false,"numberDisplay":"percent"}],"shape":"pie"}},"title":"lens_piechart","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.2","id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-bb478774-f9e8-4380-bf3a-f4a89a4d79b5","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,547],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzgsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"a1b85651-db29-441f-8f08-cf1b9b6f7bf1":{"columnOrder":["2b3bdc32-0be0-49dc-993d-4630b0bd1185","b85cc0a7-0b18-4b08-b7f0-c617f80cf903","03203126-8286-444d-b5b3-4f399eaf2c26","44305317-61e8-4600-9f3c-ac4070e0c529"],"columns":{"03203126-8286-444d-b5b3-4f399eaf2c26":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"2b3bdc32-0be0-49dc-993d-4630b0bd1185":{"dataType":"string","isBucketed":true,"label":"Top values of extension.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"44305317-61e8-4600-9f3c-ac4070e0c529","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"extension.raw"},"44305317-61e8-4600-9f3c-ac4070e0c529":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"b85cc0a7-0b18-4b08-b7f0-c617f80cf903":{"dataType":"string","isBucketed":true,"label":"Top values of machine.os.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"44305317-61e8-4600-9f3c-ac4070e0c529","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"machine.os.raw"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"columns":[{"columnId":"2b3bdc32-0be0-49dc-993d-4630b0bd1185","isTransposed":false},{"columnId":"b85cc0a7-0b18-4b08-b7f0-c617f80cf903","isTransposed":false},{"columnId":"03203126-8286-444d-b5b3-4f399eaf2c26","isTransposed":false},{"columnId":"44305317-61e8-4600-9f3c-ac4070e0c529","isTransposed":false}],"layerId":"a1b85651-db29-441f-8f08-cf1b9b6f7bf1"}},"title":"lens_table","visualizationType":"lnsDatatable"},"coreMigrationVersion":"7.13.2","id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-a1b85651-db29-441f-8f08-cf1b9b6f7bf1","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,551],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2NzksNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9":{"columnOrder":["08a1af05-743d-480e-9056-3405b1bdda7d","bae35990-75c2-487f-94eb-d8e03d2eda33"],"columns":{"08a1af05-743d-480e-9056-3405b1bdda7d":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"bae35990-75c2-487f-94eb-d8e03d2eda33","type":"column"},"orderDirection":"desc","otherBucket":true,"size":25},"scale":"ordinal","sourceField":"geo.srcdest"},"bae35990-75c2-487f-94eb-d8e03d2eda33":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["08a1af05-743d-480e-9056-3405b1bdda7d","08a1af05-743d-480e-9056-3405b1bdda7d","08a1af05-743d-480e-9056-3405b1bdda7d"],"layerId":"4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9","legendDisplay":"default","metric":"bae35990-75c2-487f-94eb-d8e03d2eda33","nestedLegend":false,"numberDisplay":"percent"}],"shape":"treemap"}},"title":"lens_treemap","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.2","id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,555],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODAsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"e84503c1-4dbd-4ac6-9ac9-ad938654680f":{"columnOrder":["38c73fd4-6330-4162-8a7b-1a059f005da8","e8d4dad2-ac30-4741-aca0-904eb1fc8455","70433aa7-3c2c-4e6c-b8cf-4218c995cff5"],"columns":{"38c73fd4-6330-4162-8a7b-1a059f005da8":{"dataType":"string","isBucketed":true,"label":"Top values of url.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"70433aa7-3c2c-4e6c-b8cf-4218c995cff5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"url.raw"},"70433aa7-3c2c-4e6c-b8cf-4218c995cff5":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"e8d4dad2-ac30-4741-aca0-904eb1fc8455":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["70433aa7-3c2c-4e6c-b8cf-4218c995cff5"],"layerId":"e84503c1-4dbd-4ac6-9ac9-ad938654680f","position":"top","seriesType":"line","showGridlines":false,"splitAccessor":"38c73fd4-6330-4162-8a7b-1a059f005da8","xAccessor":"e8d4dad2-ac30-4741-aca0-904eb1fc8455"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"line","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_line_chart","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-e84503c1-4dbd-4ac6-9ac9-ad938654680f","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,559],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODEsNF0="} -{"attributes":{"fieldAttrs":"{\"speaker\":{\"count\":1},\"text_entry\":{\"count\":6},\"type\":{\"count\":3}}","fields":"[]","runtimeFieldMap":"{}","title":"shakespeare"},"coreMigrationVersion":"7.13.2","id":"4e937b20-619d-11eb-aebf-c306684b328d","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1623693556928,560],"type":"index-pattern","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODIsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"d35680ce-c285-4fae-89d6-1245671bbc78":{"columnOrder":["2bcbffbe-c24d-4e74-8a03-9a6da7db70c0","6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff","8319857d-a03b-4158-bdf1-2a788e510445"],"columns":{"2bcbffbe-c24d-4e74-8a03-9a6da7db70c0":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff":{"dataType":"number","isBucketed":false,"label":"Average of bytes","operationType":"average","scale":"ratio","sourceField":"bytes"},"8319857d-a03b-4158-bdf1-2a788e510445":{"dataType":"number","isBucketed":false,"label":"Sum of bytes_scripted","operationType":"sum","params":{"format":{"id":"number","params":{"decimals":2}}},"scale":"ratio","sourceField":"bytes_scripted"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff","8319857d-a03b-4158-bdf1-2a788e510445"],"layerId":"d35680ce-c285-4fae-89d6-1245671bbc78","position":"top","seriesType":"area","showGridlines":false,"xAccessor":"2bcbffbe-c24d-4e74-8a03-9a6da7db70c0","yConfig":[{"axisMode":"auto","forAccessor":"8319857d-a03b-4158-bdf1-2a788e510445"}]}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"area","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_area_chart","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-d35680ce-c285-4fae-89d6-1245671bbc78","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,564],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODMsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"70bd567e-8e67-4696-a406-313b06344fa9":{"columnOrder":["96ddedfb-043b-479e-a746-600e72ab546e","d325b7da-4266-4035-9b13-5f853615149a","2fc1391b-17d1-4c49-9ddc-06ff307e3520","1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3"],"columns":{"1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3":{"dataType":"number","isBucketed":false,"label":"Average of machine.ram","operationType":"average","scale":"ratio","sourceField":"machine.ram"},"2fc1391b-17d1-4c49-9ddc-06ff307e3520":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"96ddedfb-043b-479e-a746-600e72ab546e":{"dataType":"string","isBucketed":true,"label":"Top values of machine.os.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"2fc1391b-17d1-4c49-9ddc-06ff307e3520","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"machine.os.raw"},"d325b7da-4266-4035-9b13-5f853615149a":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["2fc1391b-17d1-4c49-9ddc-06ff307e3520","1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3"],"layerId":"70bd567e-8e67-4696-a406-313b06344fa9","position":"top","seriesType":"area_stacked","showGridlines":false,"splitAccessor":"96ddedfb-043b-479e-a746-600e72ab546e","xAccessor":"d325b7da-4266-4035-9b13-5f853615149a"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"area_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_area_stacked","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-70bd567e-8e67-4696-a406-313b06344fa9","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,568],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODQsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\"},\"panelIndex\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"26e2cf99-d931-4320-9e15-9dbc148f3534\":{\"columns\":{\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\":{\"label\":\"Top values of url.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"url.raw\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"beb72af1-239c-46d8-823b-b00d1e2ace43\":{\"label\":\"Unique count of geo.srcdest\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":false}},\"columnOrder\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"beb72af1-239c-46d8-823b-b00d1e2ace43\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"26e2cf99-d931-4320-9e15-9dbc148f3534\",\"groups\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\"],\"metric\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534\"}]},\"enhancements\":{},\"type\":\"lens\"},\"panelRefName\":\"panel_2e80716f-c1b6-46f2-be2b-35db744b5031\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"da8843e0-6789-4aae-bcd0-81f270538719\"},\"panelIndex\":\"da8843e0-6789-4aae-bcd0-81f270538719\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_da8843e0-6789-4aae-bcd0-81f270538719\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},\"panelIndex\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"869754a7-edf0-478f-a7f1-80374f63108a\"},\"panelIndex\":\"869754a7-edf0-478f-a7f1-80374f63108a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_869754a7-edf0-478f-a7f1-80374f63108a\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"67111cf4-338e-453f-8621-e8dea64082d1\"},\"panelIndex\":\"67111cf4-338e-453f-8621-e8dea64082d1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_67111cf4-338e-453f-8621-e8dea64082d1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},\"panelIndex\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\"},\"panelIndex\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_88847944-ae1b-45fd-b102-3b45f9bea04b\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\"},\"panelIndex\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5a7924c7-eac0-4573-9199-fecec5b82e9e\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\"},\"panelIndex\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f8f49591-f071-4a96-b1ed-cd65daff5648\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9f357f47-c2a0-421f-a456-9583c40837ab\"},\"panelIndex\":\"9f357f47-c2a0-421f-a456-9583c40837ab\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9f357f47-c2a0-421f-a456-9583c40837ab\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\"},\"panelIndex\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cb383e9-1e80-44f9-80d5-7b8c585668db\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\"},\"panelIndex\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_57f5f0bf-6610-4599-aad4-37484640b5e2\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},\"panelIndex\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"dd1718fd-74ee-4032-851b-db97e893825d\"},\"panelIndex\":\"dd1718fd-74ee-4032-851b-db97e893825d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd1718fd-74ee-4032-851b-db97e893825d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"98a556ee-078b-4e03-93a8-29996133cdcb\"},\"panelIndex\":\"98a556ee-078b-4e03-93a8-29996133cdcb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\":{\"columns\":{\"ce9117a2-773c-474c-8fb1-18940cf58b38\":{\"label\":\"Top values of type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"type\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"a3d10552-e352-40d0-a156-e86112c0501a\":{\"label\":\"Top values of _type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"_type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"9c5db2f3-9eb0-4667-9a74-3318301de251\":{\"label\":\"Sum of bytes\",\"dataType\":\"number\",\"operationType\":\"sum\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"a3d10552-e352-40d0-a156-e86112c0501a\",\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\",\"accessors\":[\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"splitAccessor\":\"a3d10552-e352-40d0-a156-e86112c0501a\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},\"panelIndex\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},{\"version\":\"7.13.1\",\"type\":\"map\",\"gridData\":{\"x\":0,\"y\":120,\"w\":24,\"h\":15,\"i\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\"},\"panelIndex\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.56},\"mapBuffer\":{\"minLon\":-210.32666,\"minLat\":-64.8435,\"maxLon\":210.32666,\"maxLat\":95.13806},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{}},\"panelRefName\":\"panel_dcc0defa-3376-465c-9b5b-2ba69528848c\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_maps_dashboard_logstash","version":1},"coreMigrationVersion":"7.13.2","id":"16d86080-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:panel_2e80716f-c1b6-46f2-be2b-35db744b5031","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","name":"da8843e0-6789-4aae-bcd0-81f270538719:panel_da8843e0-6789-4aae-bcd0-81f270538719","type":"lens"},{"id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","name":"adcd4418-7299-4efa-b369-5f71a7b4ebe0:panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0","type":"lens"},{"id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","name":"869754a7-edf0-478f-a7f1-80374f63108a:panel_869754a7-edf0-478f-a7f1-80374f63108a","type":"lens"},{"id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","name":"67111cf4-338e-453f-8621-e8dea64082d1:panel_67111cf4-338e-453f-8621-e8dea64082d1","type":"lens"},{"id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","name":"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d:panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d","type":"lens"},{"id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","name":"88847944-ae1b-45fd-b102-3b45f9bea04b:panel_88847944-ae1b-45fd-b102-3b45f9bea04b","type":"lens"},{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"5a7924c7-eac0-4573-9199-fecec5b82e9e:panel_5a7924c7-eac0-4573-9199-fecec5b82e9e","type":"lens"},{"id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","name":"f8f49591-f071-4a96-b1ed-cd65daff5648:panel_f8f49591-f071-4a96-b1ed-cd65daff5648","type":"lens"},{"id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","name":"9f357f47-c2a0-421f-a456-9583c40837ab:panel_9f357f47-c2a0-421f-a456-9583c40837ab","type":"lens"},{"id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","name":"6cb383e9-1e80-44f9-80d5-7b8c585668db:panel_6cb383e9-1e80-44f9-80d5-7b8c585668db","type":"lens"},{"id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","name":"57f5f0bf-6610-4599-aad4-37484640b5e2:panel_57f5f0bf-6610-4599-aad4-37484640b5e2","type":"lens"},{"id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","name":"32d3ab66-52e1-44e3-8c1f-1dccff3c5692:panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692","type":"lens"},{"id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","name":"dd1718fd-74ee-4032-851b-db97e893825d:panel_dd1718fd-74ee-4032-851b-db97e893825d","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd","type":"index-pattern"},{"id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","name":"62a0f0b0-3589-4cef-807b-b1b4258b7a9b:panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b","type":"lens"},{"id":"0c5974f0-be5c-11eb-9520-1b4c3ca6a781","name":"dcc0defa-3376-465c-9b5b-2ba69528848c:panel_dcc0defa-3376-465c-9b5b-2ba69528848c","type":"map"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,590],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODUsNF0="} -{"attributes":{"fieldAttrs":"{}","fields":"[]","runtimeFieldMap":"{}","title":".kibana"},"coreMigrationVersion":"7.13.2","id":"1773aa90-be66-11eb-9520-1b4c3ca6a781","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1623693556928,591],"type":"index-pattern","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODYsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"shakespeare_areachart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"shakespeare_areachart\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"stacked\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"data\":{\"id\":\"2\",\"label\":\"Count\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"play_name\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"2\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"play_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"2\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"185283c0-619e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,593],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODcsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"by_reference_logstash","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"by_reference_logstash\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{},\"style\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"},\"style\":{}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"radiusRatio\":0,\"addTooltip\":true,\"detailedTooltip\":true,\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2014-07-15T12:33:21.084Z\",\"to\":\"2019-01-28T03:18:12.440Z\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"response.raw\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"group\"}]}"},"coreMigrationVersion":"7.13.2","id":"1885abb0-ca2b-11eb-bf5e-3de94e83d4f0","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623415891791,140],"type":"visualization","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0MzgsNF0="} -{"attributes":{"color":"#f44fcf","description":"","name":"shakespeare"},"coreMigrationVersion":"7.13.2","id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","references":[],"sort":[1623693556928,594],"type":"tag","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODgsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"3338dd55-4007-4be5-908d-25722b6174cb":{"columnOrder":["6c83b0c2-5834-4619-888c-9e8a08e47d42","b25e7497-c188-4c25-b002-1fd5bd69e76d"],"columns":{"6c83b0c2-5834-4619-888c-9e8a08e47d42":{"dataType":"string","isBucketed":true,"label":"Top values of speaker","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"b25e7497-c188-4c25-b002-1fd5bd69e76d","type":"column"},"orderDirection":"desc","otherBucket":false,"size":90},"scale":"ordinal","sourceField":"speaker"},"b25e7497-c188-4c25-b002-1fd5bd69e76d":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["6c83b0c2-5834-4619-888c-9e8a08e47d42","6c83b0c2-5834-4619-888c-9e8a08e47d42","6c83b0c2-5834-4619-888c-9e8a08e47d42"],"layerId":"3338dd55-4007-4be5-908d-25722b6174cb","legendDisplay":"default","metric":"b25e7497-c188-4c25-b002-1fd5bd69e76d","nestedLegend":false,"numberDisplay":"percent"}],"palette":{"name":"complimentary","type":"palette"},"shape":"treemap"}},"title":"lens_shakespeare_treemap","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.2","id":"31e9f2f0-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-3338dd55-4007-4be5-908d-25722b6174cb","type":"index-pattern"},{"id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","name":"tag-ref-42b4cec0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,598],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2ODksNF0="} -{"attributes":{"accessCount":0,"accessDate":1622059178542,"createDate":1622059178542,"url":"/app/dashboards#/view/73398a90-619e-11eb-aebf-c306684b328d?embed=true&_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:%272015-09-20T01:56:56.132Z%27,to:%272015-09-21T11:18:20.471Z%27))&_a=(description:%27%27,filters:!(),fullScreenMode:!f,options:(darkTheme:!f,hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(enhancements:()),gridData:(h:15,i:%271%27,w:24,x:0,y:0),id:%27185283c0-619e-11eb-aebf-c306684b328d%27,panelIndex:%271%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%272%27,w:24,x:24,y:0),id:%2733736660-619e-11eb-aebf-c306684b328d%27,panelIndex:%272%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%273%27,w:24,x:0,y:15),id:%27622ac7f0-619e-11eb-aebf-c306684b328d%27,panelIndex:%273%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%274%27,w:24,x:24,y:15),id:%27712ebbe0-619d-11eb-aebf-c306684b328d%27,panelIndex:%274%27,type:search,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%275%27,w:24,x:0,y:30),id:ddacc820-619d-11eb-aebf-c306684b328d,panelIndex:%275%27,type:search,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%276%27,w:24,x:24,y:30),id:f852d570-619d-11eb-aebf-c306684b328d,panelIndex:%276%27,type:search,version:%277.13.1%27)),query:(language:kuery,query:%27%27),tags:!(),timeRestore:!f,title:shakespeare_dashboard,viewMode:view)"},"coreMigrationVersion":"7.13.2","id":"32a03249ec3a048108d4b5a427a37fc8","references":[],"sort":[1623693556928,599],"type":"url","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTAsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"shakespeare_piechart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"shakespeare_piechart\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false,\"labels\":{\"show\":true,\"values\":true,\"last_level\":true,\"truncate\":100}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"play_name\",\"size\":15,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"33736660-619e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,601],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTEsNF0="} -{"attributes":{"color":"#7b01cf","description":"","name":"By reference"},"coreMigrationVersion":"7.13.2","id":"39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","references":[],"sort":[1623415891791,147],"type":"tag","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NDIsNF0="} -{"attributes":{"fieldAttrs":"{}","fields":"[]","runtimeFieldMap":"{}","title":"shakespeare"},"coreMigrationVersion":"7.13.2","id":"39d52f60-ca27-11eb-bf5e-3de94e83d4f0","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1623415891791,148],"type":"index-pattern","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NDMsNF0="} -{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"phrase\",\"key\":\"ip\",\"params\":{\"query\":\"57.237.11.219\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match_phrase\":{\"ip\":\"57.237.11.219\"}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"drilldown_saved_search","version":1},"coreMigrationVersion":"7.13.2","id":"4acce030-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1623415891791,151],"type":"search","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NDQsNF0="} -{"attributes":{"description":"","layerListJSON":"[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"e0d51731-2bb3-4fed-92af-65f93c3e7e58\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"},{\"sourceDescriptor\":{\"geoField\":\"geo.coordinates\",\"filterByMapBounds\":true,\"scalingType\":\"CLUSTERS\",\"topHitsSplitField\":\"\",\"topHitsSize\":1,\"id\":\"142e0a6b-53c9-4f66-a65d-fced755318de\",\"type\":\"ES_SEARCH\",\"applyGlobalQuery\":true,\"applyGlobalTime\":true,\"tooltipProperties\":[],\"sortField\":\"\",\"sortOrder\":\"desc\",\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"id\":\"ca96ce4a-4e73-46a5-bcc8-99a39d227030\",\"label\":null,\"minZoom\":9,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#CA8EAE\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#934193\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"type\":\"BLENDED_VECTOR\",\"joins\":[]}]","mapStateJSON":"{\"zoom\":1.38,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"2014-07-15T12:33:21.084Z\",\"to\":\"2019-01-28T03:18:12.440Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"Logstash_map_by_reference","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"7.13.2","id":"a53a2db0-ca2b-11eb-bf5e-3de94e83d4f0","migrationVersion":{"map":"7.12.0"},"references":[{"id":"39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","name":"tag-ref-39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","type":"tag"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"layer_1_source_index_pattern","type":"index-pattern"}],"sort":[1623415891791,154],"type":"map","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NDUsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.12.1\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"7c29a321-2a9a-412b-9ed1-1d0a1f66ea63\"},\"panelIndex\":\"7c29a321-2a9a-412b-9ed1-1d0a1f66ea63\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_0\"},{\"version\":\"7.12.1\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"f2d1feb1-d807-46b1-90ac-96d4a9edb6b1\"},\"panelIndex\":\"f2d1feb1-d807-46b1-90ac-96d4a9edb6b1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.12.1\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"a3530107-8b1c-4e94-8f99-e239fa40a09c\"},\"panelIndex\":\"a3530107-8b1c-4e94-8f99-e239fa40a09c\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"b14188e0-53d6-433e-874f-b1be7c97487c\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"by_reference_going_to_value\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}},{\"eventId\":\"60cba413-1793-4dd3-b072-9d53655d5522\",\"triggers\":[\"SELECT_RANGE_TRIGGER\"],\"action\":{\"name\":\"Goto_Discover\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/b3288100-ca2c-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:geo.dest,negate:!f,params:(query:US),type:phrase),query:(match_phrase:(geo.dest:US)))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}}]}}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.12.1\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"77245314-9495-4625-9f53-0946150e26d4\"},\"panelIndex\":\"77245314-9495-4625-9f53-0946150e26d4\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.38},\"mapBuffer\":{\"minLon\":-214.7723,\"minLat\":-74.644155,\"maxLon\":214.7723,\"maxLat\":102.864625},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9b61b9d4-20a3-4bca-9697-1097c524a943\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"By_reference_to_value\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}},\"panelRefName\":\"panel_3\"}]","timeRestore":false,"title":"by_reference_drilldown","version":1},"coreMigrationVersion":"7.13.2","id":"3b844220-ca2b-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","name":"drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b14188e0-53d6-433e-874f-b1be7c97487c:dashboardId","type":"dashboard"},{"id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","name":"drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9b61b9d4-20a3-4bca-9697-1097c524a943:dashboardId","type":"dashboard"},{"id":"4acce030-ca2a-11eb-bf5e-3de94e83d4f0","name":"panel_0","type":"search"},{"id":"0abce1c0-ca2a-11eb-bf5e-3de94e83d4f0","name":"panel_1","type":"search"},{"id":"1885abb0-ca2b-11eb-bf5e-3de94e83d4f0","name":"panel_2","type":"visualization"},{"id":"a53a2db0-ca2b-11eb-bf5e-3de94e83d4f0","name":"panel_3","type":"map"},{"id":"39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","name":"tag-39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1623415891791,162],"type":"dashboard","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NDYsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"a7a8f2fb-066e-4023-9755-821e84560b4a":{"columnOrder":["ee46f645-0af0-4b5d-8ed3-2557c98c9c12","91859a54-9b88-4478-8c80-0779fe165fba","62a4dea1-fab9-45ff-93e0-b99cfff719d5"],"columns":{"62a4dea1-fab9-45ff-93e0-b99cfff719d5":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"91859a54-9b88-4478-8c80-0779fe165fba":{"dataType":"string","isBucketed":true,"label":"Top values of play_name","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"62a4dea1-fab9-45ff-93e0-b99cfff719d5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"play_name"},"ee46f645-0af0-4b5d-8ed3-2557c98c9c12":{"dataType":"string","isBucketed":true,"label":"Top values of speaker","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"62a4dea1-fab9-45ff-93e0-b99cfff719d5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":25},"scale":"ordinal","sourceField":"speaker"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["ee46f645-0af0-4b5d-8ed3-2557c98c9c12","ee46f645-0af0-4b5d-8ed3-2557c98c9c12","ee46f645-0af0-4b5d-8ed3-2557c98c9c12","ee46f645-0af0-4b5d-8ed3-2557c98c9c12","91859a54-9b88-4478-8c80-0779fe165fba"],"layerId":"a7a8f2fb-066e-4023-9755-821e84560b4a","legendDisplay":"default","metric":"62a4dea1-fab9-45ff-93e0-b99cfff719d5","nestedLegend":false,"numberDisplay":"percent"}],"palette":{"name":"kibana_palette","type":"palette"},"shape":"pie"}},"title":"lens_shakespeare_piechart","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.2","id":"b5bd5050-be31-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-a7a8f2fb-066e-4023-9755-821e84560b4a","type":"index-pattern"},{"id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","name":"tag-ref-42b4cec0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,605],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTIsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"c4b1daae-a3af-4136-969e-8485d4ba53f9\"},\"panelIndex\":\"c4b1daae-a3af-4136-969e-8485d4ba53f9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_c4b1daae-a3af-4136-969e-8485d4ba53f9\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"f092b002-182e-49b8-bcc4-58f5233e041b\"},\"panelIndex\":\"f092b002-182e-49b8-bcc4-58f5233e041b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f092b002-182e-49b8-bcc4-58f5233e041b\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_shakespeare_dashboard","version":1},"coreMigrationVersion":"7.13.2","id":"43fae350-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"b5bd5050-be31-11eb-9520-1b4c3ca6a781","name":"c4b1daae-a3af-4136-969e-8485d4ba53f9:panel_c4b1daae-a3af-4136-969e-8485d4ba53f9","type":"lens"},{"id":"31e9f2f0-be32-11eb-9520-1b4c3ca6a781","name":"f092b002-182e-49b8-bcc4-58f5233e041b:panel_f092b002-182e-49b8-bcc4-58f5233e041b","type":"lens"},{"id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","name":"tag-42b4cec0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,609],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTMsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"7\",\"w\":24,\"x\":0,\"y\":45},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"8\",\"w\":24,\"x\":24,\"y\":45},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"9\",\"w\":24,\"x\":0,\"y\":60},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"10\",\"w\":24,\"x\":24,\"y\":60},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"11\",\"w\":24,\"x\":0,\"y\":75},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"12\",\"w\":24,\"x\":24,\"y\":75},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"13\",\"w\":24,\"x\":0,\"y\":90},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"14\",\"w\":24,\"x\":24,\"y\":90},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"15\",\"w\":24,\"x\":0,\"y\":105},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"16\",\"w\":24,\"x\":24,\"y\":105},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"17\",\"w\":24,\"x\":0,\"y\":120},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"18\",\"w\":24,\"x\":24,\"y\":120},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"19\",\"w\":24,\"x\":0,\"y\":135},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"20\",\"w\":24,\"x\":24,\"y\":135},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"}]","timeRestore":false,"title":"logstash_dashboard_withouttime","version":1},"coreMigrationVersion":"7.13.2","id":"5d3410c0-6249-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"36b91810-6239-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"0a274320-61cc-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"e4aef350-623d-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"f92e5630-623e-11eb-aebf-c306684b328d","name":"4:panel_4","type":"visualization"},{"id":"9853d4d0-623d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"visualization"},{"id":"6ecb33b0-623d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"visualization"},{"id":"b8e35c80-623c-11eb-aebf-c306684b328d","name":"7:panel_7","type":"visualization"},{"id":"f1bc75d0-6239-11eb-aebf-c306684b328d","name":"8:panel_8","type":"visualization"},{"id":"0d8a8860-623a-11eb-aebf-c306684b328d","name":"9:panel_9","type":"visualization"},{"id":"d79fe3d0-6239-11eb-aebf-c306684b328d","name":"10:panel_10","type":"visualization"},{"id":"318375a0-6240-11eb-aebf-c306684b328d","name":"11:panel_11","type":"visualization"},{"id":"e461eb20-6245-11eb-aebf-c306684b328d","name":"12:panel_12","type":"visualization"},{"id":"25bdc750-6242-11eb-aebf-c306684b328d","name":"13:panel_13","type":"visualization"},{"id":"71dd7bc0-6248-11eb-aebf-c306684b328d","name":"14:panel_14","type":"visualization"},{"id":"6aea48a0-6240-11eb-aebf-c306684b328d","name":"15:panel_15","type":"visualization"},{"id":"32b681f0-6241-11eb-aebf-c306684b328d","name":"16:panel_16","type":"visualization"},{"id":"ccca99e0-6244-11eb-aebf-c306684b328d","name":"17:panel_17","type":"visualization"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"18:panel_18","type":"visualization"},{"id":"c94d8440-6248-11eb-aebf-c306684b328d","name":"19:panel_19","type":"visualization"},{"id":"db6226f0-61c0-11eb-aebf-c306684b328d","name":"20:panel_20","type":"search"}],"sort":[1623693556928,630],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTQsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"shakespeare_tag_cloud","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"shakespeare_tag_cloud\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"multiple\",\"minFontSize\":59,\"maxFontSize\":100,\"showLabel\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"type.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.2","id":"622ac7f0-619e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,632],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTUsNF0="} -{"attributes":{"numLinks":4,"numVertices":5,"title":"logstash_graph","version":1,"wsState":"\"{\\\"selectedFields\\\":[{\\\"name\\\":\\\"machine.os.raw\\\",\\\"hopSize\\\":5,\\\"lastValidHopSize\\\":5,\\\"color\\\":\\\"#B9A888\\\",\\\"selected\\\":true,\\\"iconClass\\\":\\\"fa-folder-open-o\\\"},{\\\"name\\\":\\\"response.raw\\\",\\\"hopSize\\\":5,\\\"lastValidHopSize\\\":5,\\\"color\\\":\\\"#D6BF57\\\",\\\"selected\\\":true,\\\"iconClass\\\":\\\"fa-folder-open-o\\\"}],\\\"blocklist\\\":[],\\\"vertices\\\":[{\\\"x\\\":461.96184642905024,\\\"y\\\":284.02313214227325,\\\"label\\\":\\\"osx\\\",\\\"color\\\":\\\"#B9A888\\\",\\\"field\\\":\\\"machine.os.raw\\\",\\\"term\\\":\\\"osx\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":383.946159835112,\\\"y\\\":375.6063135315976,\\\"label\\\":\\\"503\\\",\\\"color\\\":\\\"#D6BF57\\\",\\\"field\\\":\\\"response.raw\\\",\\\"term\\\":\\\"503\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":287.104700756828,\\\"y\\\":324.1245253249895,\\\"label\\\":\\\"win 7\\\",\\\"color\\\":\\\"#B9A888\\\",\\\"field\\\":\\\"machine.os.raw\\\",\\\"term\\\":\\\"win 7\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":487.9986107998273,\\\"y\\\":407.07546535764254,\\\"label\\\":\\\"ios\\\",\\\"color\\\":\\\"#B9A888\\\",\\\"field\\\":\\\"machine.os.raw\\\",\\\"term\\\":\\\"ios\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":302.35059551806023,\\\"y\\\":211.66825720913607,\\\"label\\\":\\\"200\\\",\\\"color\\\":\\\"#D6BF57\\\",\\\"field\\\":\\\"response.raw\\\",\\\"term\\\":\\\"200\\\",\\\"parent\\\":null,\\\"size\\\":15}],\\\"links\\\":[{\\\"weight\\\":0.000881324009872165,\\\"width\\\":7.983523640193488,\\\"source\\\":4,\\\"target\\\":2},{\\\"weight\\\":0.000023386835221992895,\\\"width\\\":2,\\\"source\\\":1,\\\"target\\\":0},{\\\"weight\\\":0.0011039286029480653,\\\"width\\\":2,\\\"source\\\":1,\\\"target\\\":2},{\\\"weight\\\":0.000045596928960694605,\\\"width\\\":2,\\\"source\\\":1,\\\"target\\\":3}],\\\"urlTemplates\\\":[{\\\"url\\\":\\\"/app/discover#/?_a=(columns%3A!(_source)%2Cindex%3A%2756b34100-619d-11eb-aebf-c306684b328d%27%2Cinterval%3Aauto%2Cquery%3A(language%3Akuery%2Cquery%3A{{gquery}})%2Csort%3A!(_score%2Cdesc))\\\",\\\"description\\\":\\\"Machine OS win 7\\\",\\\"isDefault\\\":false,\\\"encoderID\\\":\\\"kql\\\",\\\"iconClass\\\":\\\"fa-share-alt\\\"}],\\\"exploreControls\\\":{\\\"useSignificance\\\":true,\\\"sampleSize\\\":2000,\\\"timeoutMillis\\\":5000,\\\"maxValuesPerDoc\\\":1,\\\"minDocCount\\\":3},\\\"indexPatternRefName\\\":\\\"indexPattern_0\\\"}\""},"coreMigrationVersion":"7.13.2","id":"6afc4b40-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"graph-workspace":"7.11.0"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexPattern_0","type":"index-pattern"}],"sort":[1623693556928,634],"type":"graph-workspace","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTYsNF0="} -{"attributes":{"buildNum":39457,"defaultIndex":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0"},"coreMigrationVersion":"7.13.2","id":"7.12.1","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1623415891791,170],"type":"config","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NTAsNF0="} -{"attributes":{"accessibility:disableAnimations":true,"buildNum":null,"dateFormat:tz":"UTC","defaultIndex":"56b34100-619d-11eb-aebf-c306684b328d","visualization:visualize:legacyChartsLibrary":true},"coreMigrationVersion":"7.13.2","id":"7.13.1","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1623693556928,635],"type":"config","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTcsNF0="} -{"attributes":{"buildNum":40943,"defaultIndex":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0"},"coreMigrationVersion":"7.13.2","id":"7.13.2","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1623693652730,748],"type":"config","updated_at":"2021-06-14T18:00:52.730Z","version":"WzE3MjQsNF0="} -{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"negate\":false,\"type\":\"phrase\",\"key\":\"text_entry\",\"value\":\"Christendom.\",\"params\":{\"query\":\"Christendom.\",\"type\":\"phrase\"},\"disabled\":false,\"alias\":null,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"text_entry\":{\"query\":\"Christendom.\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["_score","desc"]],"title":"shakespeare_saved_search","version":1},"coreMigrationVersion":"7.13.2","id":"712ebbe0-619d-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1623693556928,638],"type":"search","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTgsNF0="} -{"attributes":{"columns":["play_name","speaker"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"speaker:\\\"GLOUCESTER\\\"\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["_score","desc"]],"title":"shakespeare_saved_lucene_search","version":1},"coreMigrationVersion":"7.13.2","id":"ddacc820-619d-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,640],"type":"search","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE2OTksNF0="} -{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"text_entry :\\\"MORDAKE THE EARL OF FIFE, AND ELDEST SON\\\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["_score","desc"]],"title":"shakespeare_saved_kql_search","version":1},"coreMigrationVersion":"7.13.2","id":"f852d570-619d-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623693556928,642],"type":"search","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDAsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"}]","timeRestore":false,"title":"shakespeare_dashboard","version":1},"coreMigrationVersion":"7.13.2","id":"73398a90-619e-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"185283c0-619e-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"33736660-619e-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"622ac7f0-619e-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"712ebbe0-619d-11eb-aebf-c306684b328d","name":"4:panel_4","type":"search"},{"id":"ddacc820-619d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"search"},{"id":"f852d570-619d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"search"}],"sort":[1623693556928,649],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDEsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"geo.srcdest\",\"value\":\"IN:US\",\"params\":{\"query\":\"IN:US\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"geo.srcdest\":{\"query\":\"IN:US\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"7\",\"w\":24,\"x\":0,\"y\":45},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"8\",\"w\":24,\"x\":24,\"y\":45},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"9\",\"w\":24,\"x\":0,\"y\":60},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"10\",\"w\":24,\"x\":24,\"y\":60},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"11\",\"w\":24,\"x\":0,\"y\":75},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"12\",\"w\":24,\"x\":24,\"y\":75},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"13\",\"w\":24,\"x\":0,\"y\":90},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"14\",\"w\":24,\"x\":24,\"y\":90},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"15\",\"w\":24,\"x\":0,\"y\":105},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"16\",\"w\":24,\"x\":24,\"y\":105},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"17\",\"w\":24,\"x\":0,\"y\":120},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"18\",\"w\":24,\"x\":24,\"y\":120},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"19\",\"w\":24,\"x\":0,\"y\":135},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"20\",\"w\":24,\"x\":24,\"y\":135},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"}]","timeRestore":false,"title":"logstash_dashboardwithfilters","version":1},"coreMigrationVersion":"7.13.2","id":"79794f20-6249-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"},{"id":"36b91810-6239-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"0a274320-61cc-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"e4aef350-623d-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"f92e5630-623e-11eb-aebf-c306684b328d","name":"4:panel_4","type":"visualization"},{"id":"9853d4d0-623d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"visualization"},{"id":"6ecb33b0-623d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"visualization"},{"id":"b8e35c80-623c-11eb-aebf-c306684b328d","name":"7:panel_7","type":"visualization"},{"id":"f1bc75d0-6239-11eb-aebf-c306684b328d","name":"8:panel_8","type":"visualization"},{"id":"0d8a8860-623a-11eb-aebf-c306684b328d","name":"9:panel_9","type":"visualization"},{"id":"d79fe3d0-6239-11eb-aebf-c306684b328d","name":"10:panel_10","type":"visualization"},{"id":"318375a0-6240-11eb-aebf-c306684b328d","name":"11:panel_11","type":"visualization"},{"id":"e461eb20-6245-11eb-aebf-c306684b328d","name":"12:panel_12","type":"visualization"},{"id":"25bdc750-6242-11eb-aebf-c306684b328d","name":"13:panel_13","type":"visualization"},{"id":"71dd7bc0-6248-11eb-aebf-c306684b328d","name":"14:panel_14","type":"visualization"},{"id":"6aea48a0-6240-11eb-aebf-c306684b328d","name":"15:panel_15","type":"visualization"},{"id":"32b681f0-6241-11eb-aebf-c306684b328d","name":"16:panel_16","type":"visualization"},{"id":"ccca99e0-6244-11eb-aebf-c306684b328d","name":"17:panel_17","type":"visualization"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"18:panel_18","type":"visualization"},{"id":"c94d8440-6248-11eb-aebf-c306684b328d","name":"19:panel_19","type":"visualization"},{"id":"db6226f0-61c0-11eb-aebf-c306684b328d","name":"20:panel_20","type":"search"}],"sort":[1623693556928,671],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDIsNF0="} -{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"037b7937-790b-4d2d-94a5-7f5837a6ef05":{"columnOrder":["b3d46616-75e0-419e-97ea-91148961ef94","025a0fb3-dc44-4f5c-b517-2d71d3f26f14","c476db14-0cc1-40ec-863e-d2779256a407"],"columns":{"025a0fb3-dc44-4f5c-b517-2d71d3f26f14":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"b3d46616-75e0-419e-97ea-91148961ef94":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c476db14-0cc1-40ec-863e-d2779256a407","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"geo.srcdest"},"c476db14-0cc1-40ec-863e-d2779256a407":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"lucene","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c476db14-0cc1-40ec-863e-d2779256a407"],"layerId":"037b7937-790b-4d2d-94a5-7f5837a6ef05","position":"top","seriesType":"bar_stacked","showGridlines":false,"splitAccessor":"b3d46616-75e0-419e-97ea-91148961ef94","xAccessor":"025a0fb3-dc44-4f5c-b517-2d71d3f26f14"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_verticalstacked","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.2","id":"8dc19b50-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,675],"type":"lens","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDMsNF0="} -{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"phrase\",\"key\":\"geo.dest\",\"params\":{\"query\":\"US\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match_phrase\":{\"geo.dest\":\"US\"}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"drilldown_logstash","version":1},"coreMigrationVersion":"7.13.2","id":"b3288100-ca2c-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1623415891791,216],"type":"search","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NjMsNF0="} -{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{}"},"title":"logstash_timelion_panel","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_timelion_panel\",\"type\":\"timelion\",\"aggs\":[],\"params\":{\"expression\":\".es(index=logstash-*, \\\"sum:bytes\\\")\",\"interval\":\"auto\"}}"},"coreMigrationVersion":"7.13.2","id":"b3a44cd0-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1623693556928,677],"type":"visualization","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDUsNF0="} -{"attributes":{"color":"#9170B8","description":"","name":"alltogether"},"coreMigrationVersion":"7.13.2","id":"be808cb0-be32-11eb-9520-1b4c3ca6a781","references":[],"sort":[1623693556928,678],"type":"tag","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDYsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"4d9e9a01-cdb8-4aef-afcb-50db52247bb1\"},\"panelIndex\":\"4d9e9a01-cdb8-4aef-afcb-50db52247bb1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4d9e9a01-cdb8-4aef-afcb-50db52247bb1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"d9cab9c8-667e-4d34-821b-cbb070891956\"},\"panelIndex\":\"d9cab9c8-667e-4d34-821b-cbb070891956\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_d9cab9c8-667e-4d34-821b-cbb070891956\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_combined_dashboard","version":1},"coreMigrationVersion":"7.13.2","id":"bfb3dc90-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"8dc19b50-be32-11eb-9520-1b4c3ca6a781","name":"4d9e9a01-cdb8-4aef-afcb-50db52247bb1:panel_4d9e9a01-cdb8-4aef-afcb-50db52247bb1","type":"lens"},{"id":"b5bd5050-be31-11eb-9520-1b4c3ca6a781","name":"d9cab9c8-667e-4d34-821b-cbb070891956:panel_d9cab9c8-667e-4d34-821b-cbb070891956","type":"lens"},{"id":"be808cb0-be32-11eb-9520-1b4c3ca6a781","name":"tag-be808cb0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,682],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDcsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\"},\"panelIndex\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"26e2cf99-d931-4320-9e15-9dbc148f3534\":{\"columns\":{\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\":{\"label\":\"Top values of url.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"url.raw\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"beb72af1-239c-46d8-823b-b00d1e2ace43\":{\"label\":\"Unique count of geo.srcdest\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":false}},\"columnOrder\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"beb72af1-239c-46d8-823b-b00d1e2ace43\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"26e2cf99-d931-4320-9e15-9dbc148f3534\",\"groups\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\"],\"metric\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534\"}]},\"enhancements\":{},\"type\":\"lens\"},\"panelRefName\":\"panel_2e80716f-c1b6-46f2-be2b-35db744b5031\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"da8843e0-6789-4aae-bcd0-81f270538719\"},\"panelIndex\":\"da8843e0-6789-4aae-bcd0-81f270538719\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_da8843e0-6789-4aae-bcd0-81f270538719\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},\"panelIndex\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"869754a7-edf0-478f-a7f1-80374f63108a\"},\"panelIndex\":\"869754a7-edf0-478f-a7f1-80374f63108a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_869754a7-edf0-478f-a7f1-80374f63108a\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"67111cf4-338e-453f-8621-e8dea64082d1\"},\"panelIndex\":\"67111cf4-338e-453f-8621-e8dea64082d1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_67111cf4-338e-453f-8621-e8dea64082d1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},\"panelIndex\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\"},\"panelIndex\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_88847944-ae1b-45fd-b102-3b45f9bea04b\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\"},\"panelIndex\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5a7924c7-eac0-4573-9199-fecec5b82e9e\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\"},\"panelIndex\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f8f49591-f071-4a96-b1ed-cd65daff5648\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9f357f47-c2a0-421f-a456-9583c40837ab\"},\"panelIndex\":\"9f357f47-c2a0-421f-a456-9583c40837ab\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9f357f47-c2a0-421f-a456-9583c40837ab\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\"},\"panelIndex\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cb383e9-1e80-44f9-80d5-7b8c585668db\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\"},\"panelIndex\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_57f5f0bf-6610-4599-aad4-37484640b5e2\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},\"panelIndex\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"dd1718fd-74ee-4032-851b-db97e893825d\"},\"panelIndex\":\"dd1718fd-74ee-4032-851b-db97e893825d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd1718fd-74ee-4032-851b-db97e893825d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"98a556ee-078b-4e03-93a8-29996133cdcb\"},\"panelIndex\":\"98a556ee-078b-4e03-93a8-29996133cdcb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\":{\"columns\":{\"ce9117a2-773c-474c-8fb1-18940cf58b38\":{\"label\":\"Top values of type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"type\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"a3d10552-e352-40d0-a156-e86112c0501a\":{\"label\":\"Top values of _type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"_type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"9c5db2f3-9eb0-4667-9a74-3318301de251\":{\"label\":\"Sum of bytes\",\"dataType\":\"number\",\"operationType\":\"sum\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"a3d10552-e352-40d0-a156-e86112c0501a\",\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\",\"accessors\":[\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"splitAccessor\":\"a3d10552-e352-40d0-a156-e86112c0501a\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},\"panelIndex\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},{\"version\":\"7.13.1\",\"type\":\"map\",\"gridData\":{\"x\":0,\"y\":120,\"w\":24,\"h\":15,\"i\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\"},\"panelIndex\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.56},\"mapBuffer\":{\"minLon\":-210.32666,\"minLat\":-64.8435,\"maxLon\":210.32666,\"maxLat\":95.13806},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{}},\"panelRefName\":\"panel_dcc0defa-3376-465c-9b5b-2ba69528848c\"},{\"version\":\"7.13.1\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":120,\"w\":24,\"h\":15,\"i\":\"dd21a674-ae3a-40f6-9d68-4e01361ea5e2\"},\"panelIndex\":\"dd21a674-ae3a-40f6-9d68-4e01361ea5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd21a674-ae3a-40f6-9d68-4e01361ea5e2\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"timelion_lens_maps_dashboard_logstash","version":1},"coreMigrationVersion":"7.13.2","id":"c4ab2030-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:panel_2e80716f-c1b6-46f2-be2b-35db744b5031","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","name":"da8843e0-6789-4aae-bcd0-81f270538719:panel_da8843e0-6789-4aae-bcd0-81f270538719","type":"lens"},{"id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","name":"adcd4418-7299-4efa-b369-5f71a7b4ebe0:panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0","type":"lens"},{"id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","name":"869754a7-edf0-478f-a7f1-80374f63108a:panel_869754a7-edf0-478f-a7f1-80374f63108a","type":"lens"},{"id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","name":"67111cf4-338e-453f-8621-e8dea64082d1:panel_67111cf4-338e-453f-8621-e8dea64082d1","type":"lens"},{"id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","name":"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d:panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d","type":"lens"},{"id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","name":"88847944-ae1b-45fd-b102-3b45f9bea04b:panel_88847944-ae1b-45fd-b102-3b45f9bea04b","type":"lens"},{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"5a7924c7-eac0-4573-9199-fecec5b82e9e:panel_5a7924c7-eac0-4573-9199-fecec5b82e9e","type":"lens"},{"id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","name":"f8f49591-f071-4a96-b1ed-cd65daff5648:panel_f8f49591-f071-4a96-b1ed-cd65daff5648","type":"lens"},{"id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","name":"9f357f47-c2a0-421f-a456-9583c40837ab:panel_9f357f47-c2a0-421f-a456-9583c40837ab","type":"lens"},{"id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","name":"6cb383e9-1e80-44f9-80d5-7b8c585668db:panel_6cb383e9-1e80-44f9-80d5-7b8c585668db","type":"lens"},{"id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","name":"57f5f0bf-6610-4599-aad4-37484640b5e2:panel_57f5f0bf-6610-4599-aad4-37484640b5e2","type":"lens"},{"id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","name":"32d3ab66-52e1-44e3-8c1f-1dccff3c5692:panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692","type":"lens"},{"id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","name":"dd1718fd-74ee-4032-851b-db97e893825d:panel_dd1718fd-74ee-4032-851b-db97e893825d","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd","type":"index-pattern"},{"id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","name":"62a0f0b0-3589-4cef-807b-b1b4258b7a9b:panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b","type":"lens"},{"id":"0c5974f0-be5c-11eb-9520-1b4c3ca6a781","name":"dcc0defa-3376-465c-9b5b-2ba69528848c:panel_dcc0defa-3376-465c-9b5b-2ba69528848c","type":"map"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"dd21a674-ae3a-40f6-9d68-4e01361ea5e2:panel_dd21a674-ae3a-40f6-9d68-4e01361ea5e2","type":"visualization"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,705],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDgsNF0="} -{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"speaker :\\\"DUKE VINCENTIO\\\" \",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[],"title":"drilldown_shakes","version":1},"coreMigrationVersion":"7.13.2","id":"c4b9cc00-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"39d52f60-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1623415891791,218],"type":"search","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NjQsNF0="} -{"attributes":{"@created":"2021-05-27T19:45:29.712Z","@timestamp":"2021-05-27T19:45:29.712Z","content":"{\"selectedNodes\":[{\"id\":\"element-56d2ba72-f227-4d04-9478-a1d6f0c7e601\",\"position\":{\"left\":20,\"top\":20,\"width\":500,\"height\":300,\"angle\":0,\"parent\":\"group-499b5982-25f4-4894-9540-1874a27d78e7\",\"type\":\"element\"},\"expression\":\"savedLens id=\\\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\\\" timerange={timerange from=\\\"now-15y\\\" to=\\\"now\\\"}\\n| render\",\"filter\":null,\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"savedLens\",\"arguments\":{\"id\":[\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\"],\"timerange\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"timerange\",\"arguments\":{\"from\":[\"now-15y\"],\"to\":[\"now\"]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-afbaa26e-10e7-47d4-bb41-b061dfdced2b\",\"position\":{\"left\":527,\"top\":20,\"width\":500,\"height\":300,\"angle\":0,\"parent\":\"group-499b5982-25f4-4894-9540-1874a27d78e7\",\"type\":\"element\"},\"expression\":\"savedVisualization id=\\\"0d8a8860-623a-11eb-aebf-c306684b328d\\\" timerange={timerange from=\\\"now-15y\\\" to=\\\"now\\\"}\\n| render\",\"filter\":null,\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"savedVisualization\",\"arguments\":{\"id\":[\"0d8a8860-623a-11eb-aebf-c306684b328d\"],\"timerange\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"timerange\",\"arguments\":{\"from\":[\"now-15y\"],\"to\":[\"now\"]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}","displayName":"element_canvas","help":"","image":"","name":"elementCanvas"},"coreMigrationVersion":"7.13.2","id":"custom-element-3bc52277-ee01-4cdc-8d2d-f2db6ade1512","references":[],"sort":[1623693556928,706],"type":"canvas-element","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MDksNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"ced0a5ea-3ec2-4274-8431-6e76d85637f6\"},\"panelIndex\":\"ced0a5ea-3ec2-4274-8431-6e76d85637f6\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3\":{\"columns\":{\"f70668f8-ae97-4b64-867f-b0c9b77914ef\":{\"label\":\"Top values of speaker\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"speaker\",\"isBucketed\":true,\"params\":{\"size\":39,\"orderBy\":{\"type\":\"column\",\"columnId\":\"fbf256d9-cae7-4244-8504-b73a5666e917\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"fbf256d9-cae7-4244-8504-b73a5666e917\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"}},\"columnOrder\":[\"f70668f8-ae97-4b64-867f-b0c9b77914ef\",\"fbf256d9-cae7-4244-8504-b73a5666e917\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_horizontal_percentage_stacked\",\"layers\":[{\"layerId\":\"6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3\",\"accessors\":[\"fbf256d9-cae7-4244-8504-b73a5666e917\"],\"position\":\"top\",\"seriesType\":\"bar_horizontal_percentage_stacked\",\"showGridlines\":false,\"splitAccessor\":\"f70668f8-ae97-4b64-867f-b0c9b77914ef\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"39d52f60-ca27-11eb-bf5e-3de94e83d4f0\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"39d52f60-ca27-11eb-bf5e-3de94e83d4f0\",\"name\":\"indexpattern-datasource-layer-6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"2b9a2bad-d6aa-4d3b-a692-fd96c3fb0ac1\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"We_like_lens\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"5e4cf03a-13bb-4aa7-8326-b47a19e88968\"},\"panelIndex\":\"5e4cf03a-13bb-4aa7-8326-b47a19e88968\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100}},\"uiState\":{},\"data\":{\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"play_name\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":788,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"segment\"}],\"searchSource\":{\"index\":\"39d52f60-ca27-11eb-bf5e-3de94e83d4f0\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"c5e2a416-2985-4f44-a6b6-70bb95d3bcdd\",\"triggers\":[\"CONTEXT_MENU_TRIGGER\"],\"action\":{\"name\":\"shakespeare_discover\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/c4b9cc00-ca2a-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(),index:'39d52f60-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:'speaker%20:%22DUKE%20VINCENTIO%22%20'),sort:!())\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}},{\"eventId\":\"de71a757-6401-4b05-9d8d-475fedc0cd47\",\"triggers\":[\"VALUE_CLICK_TRIGGER\"],\"action\":{\"name\":\"drilldown_timebased\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/b3288100-ca2c-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:geo.dest,negate:!f,params:(query:US),type:phrase),query:(match_phrase:(geo.dest:US)))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}}]}},\"type\":\"visualization\"}}]","timeRestore":false,"title":"nontimebased_shakespeare_drilldown","version":1},"coreMigrationVersion":"7.13.2","id":"e9eb20f0-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"39d52f60-ca27-11eb-bf5e-3de94e83d4f0","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"39d52f60-ca27-11eb-bf5e-3de94e83d4f0","name":"indexpattern-datasource-layer-6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3","type":"index-pattern"},{"id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","name":"drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:2b9a2bad-d6aa-4d3b-a692-fd96c3fb0ac1:dashboardId","type":"dashboard"},{"id":"39d52f60-ca27-11eb-bf5e-3de94e83d4f0","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","name":"tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1623415891791,224],"type":"dashboard","updated_at":"2021-06-11T12:51:31.791Z","version":"WzE0NjUsNF0="} -{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\"},\"panelIndex\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"26e2cf99-d931-4320-9e15-9dbc148f3534\":{\"columns\":{\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\":{\"label\":\"Top values of url.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"url.raw\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"beb72af1-239c-46d8-823b-b00d1e2ace43\":{\"label\":\"Unique count of geo.srcdest\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":false}},\"columnOrder\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"beb72af1-239c-46d8-823b-b00d1e2ace43\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"26e2cf99-d931-4320-9e15-9dbc148f3534\",\"groups\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\"],\"metric\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534\"}]},\"enhancements\":{},\"type\":\"lens\"},\"panelRefName\":\"panel_2e80716f-c1b6-46f2-be2b-35db744b5031\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"da8843e0-6789-4aae-bcd0-81f270538719\"},\"panelIndex\":\"da8843e0-6789-4aae-bcd0-81f270538719\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_da8843e0-6789-4aae-bcd0-81f270538719\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},\"panelIndex\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"869754a7-edf0-478f-a7f1-80374f63108a\"},\"panelIndex\":\"869754a7-edf0-478f-a7f1-80374f63108a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_869754a7-edf0-478f-a7f1-80374f63108a\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"67111cf4-338e-453f-8621-e8dea64082d1\"},\"panelIndex\":\"67111cf4-338e-453f-8621-e8dea64082d1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_67111cf4-338e-453f-8621-e8dea64082d1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},\"panelIndex\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\"},\"panelIndex\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_88847944-ae1b-45fd-b102-3b45f9bea04b\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\"},\"panelIndex\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5a7924c7-eac0-4573-9199-fecec5b82e9e\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\"},\"panelIndex\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f8f49591-f071-4a96-b1ed-cd65daff5648\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9f357f47-c2a0-421f-a456-9583c40837ab\"},\"panelIndex\":\"9f357f47-c2a0-421f-a456-9583c40837ab\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9f357f47-c2a0-421f-a456-9583c40837ab\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\"},\"panelIndex\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cb383e9-1e80-44f9-80d5-7b8c585668db\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\"},\"panelIndex\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_57f5f0bf-6610-4599-aad4-37484640b5e2\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},\"panelIndex\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"dd1718fd-74ee-4032-851b-db97e893825d\"},\"panelIndex\":\"dd1718fd-74ee-4032-851b-db97e893825d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd1718fd-74ee-4032-851b-db97e893825d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"98a556ee-078b-4e03-93a8-29996133cdcb\"},\"panelIndex\":\"98a556ee-078b-4e03-93a8-29996133cdcb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\":{\"columns\":{\"ce9117a2-773c-474c-8fb1-18940cf58b38\":{\"label\":\"Top values of type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"type\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"a3d10552-e352-40d0-a156-e86112c0501a\":{\"label\":\"Top values of _type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"_type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"9c5db2f3-9eb0-4667-9a74-3318301de251\":{\"label\":\"Sum of bytes\",\"dataType\":\"number\",\"operationType\":\"sum\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"a3d10552-e352-40d0-a156-e86112c0501a\",\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\",\"accessors\":[\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"splitAccessor\":\"a3d10552-e352-40d0-a156-e86112c0501a\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},\"panelIndex\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_dashboard_logstash","version":1},"coreMigrationVersion":"7.13.2","id":"f458b9f0-bd9e-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:panel_2e80716f-c1b6-46f2-be2b-35db744b5031","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","name":"da8843e0-6789-4aae-bcd0-81f270538719:panel_da8843e0-6789-4aae-bcd0-81f270538719","type":"lens"},{"id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","name":"adcd4418-7299-4efa-b369-5f71a7b4ebe0:panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0","type":"lens"},{"id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","name":"869754a7-edf0-478f-a7f1-80374f63108a:panel_869754a7-edf0-478f-a7f1-80374f63108a","type":"lens"},{"id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","name":"67111cf4-338e-453f-8621-e8dea64082d1:panel_67111cf4-338e-453f-8621-e8dea64082d1","type":"lens"},{"id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","name":"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d:panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d","type":"lens"},{"id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","name":"88847944-ae1b-45fd-b102-3b45f9bea04b:panel_88847944-ae1b-45fd-b102-3b45f9bea04b","type":"lens"},{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"5a7924c7-eac0-4573-9199-fecec5b82e9e:panel_5a7924c7-eac0-4573-9199-fecec5b82e9e","type":"lens"},{"id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","name":"f8f49591-f071-4a96-b1ed-cd65daff5648:panel_f8f49591-f071-4a96-b1ed-cd65daff5648","type":"lens"},{"id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","name":"9f357f47-c2a0-421f-a456-9583c40837ab:panel_9f357f47-c2a0-421f-a456-9583c40837ab","type":"lens"},{"id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","name":"6cb383e9-1e80-44f9-80d5-7b8c585668db:panel_6cb383e9-1e80-44f9-80d5-7b8c585668db","type":"lens"},{"id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","name":"57f5f0bf-6610-4599-aad4-37484640b5e2:panel_57f5f0bf-6610-4599-aad4-37484640b5e2","type":"lens"},{"id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","name":"32d3ab66-52e1-44e3-8c1f-1dccff3c5692:panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692","type":"lens"},{"id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","name":"dd1718fd-74ee-4032-851b-db97e893825d:panel_dd1718fd-74ee-4032-851b-db97e893825d","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd","type":"index-pattern"},{"id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","name":"62a0f0b0-3589-4cef-807b-b1b4258b7a9b:panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b","type":"lens"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1623693556928,727],"type":"dashboard","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MTAsNF0="} -{"attributes":{"allowNoIndex":true,"fieldFormatMap":"{\"Target.process.parent.pgid\":{\"id\":\"string\"},\"Target.process.parent.pid\":{\"id\":\"string\"},\"Target.process.parent.ppid\":{\"id\":\"string\"},\"Target.process.parent.thread.id\":{\"id\":\"string\"},\"Target.process.pgid\":{\"id\":\"string\"},\"Target.process.pid\":{\"id\":\"string\"},\"Target.process.ppid\":{\"id\":\"string\"},\"Target.process.thread.id\":{\"id\":\"string\"},\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"},\"process.parent.pgid\":{\"id\":\"string\"},\"process.parent.pid\":{\"id\":\"string\"},\"process.parent.ppid\":{\"id\":\"string\"},\"process.parent.thread.id\":{\"id\":\"string\"},\"process.pgid\":{\"id\":\"string\"},\"process.pid\":{\"id\":\"string\"},\"process.ppid\":{\"id\":\"string\"},\"process.thread.id\":{\"id\":\"string\"},\"destination.bytes\":{\"id\":\"bytes\"},\"destination.port\":{\"id\":\"string\"},\"http.request.body.bytes\":{\"id\":\"bytes\"},\"http.request.bytes\":{\"id\":\"bytes\"},\"http.response.body.bytes\":{\"id\":\"bytes\"},\"http.response.bytes\":{\"id\":\"bytes\"},\"http.response.status_code\":{\"id\":\"string\"},\"network.bytes\":{\"id\":\"bytes\"},\"source.bytes\":{\"id\":\"bytes\"},\"source.port\":{\"id\":\"string\"}}","fields":"[{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Endpoint.policy.applied.artifacts.global\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.identifiers\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.identifiers.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.identifiers.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.identifiers\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.identifiers.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.identifiers.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Memory_protection.cross_session\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Memory_protection.feature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Memory_protection.parent_to_child\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Memory_protection.self_injection\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Memory_protection.thread_count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Memory_protection.unique_key_v1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.child_pids\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.feature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.data\",\"type\":\"binary\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Ransomware.files.entropy\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.metrics\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.operation\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.original.extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.original.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.files.score\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.score\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Ransomware.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.compile_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.features\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Target.dll.Ext.malware_classification.features.data.buffer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.features.data.decompressed_size\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.features.data.encoding\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.identifier\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.score\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.threshold\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.upx_packed\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.malware_classification.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.mapped_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.Ext.mapped_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.dll.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.ancestry\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.architecture\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.authentication_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.compile_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.mapped_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.Ext.mapped_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.dll.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.features\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Target.process.Ext.malware_classification.features.data.buffer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.features.data.decompressed_size\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.features.data.encoding\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.identifier\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.score\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.threshold\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.upx_packed\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.malware_classification.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.services\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.session\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.elevation\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.elevation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.impersonation_level\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.integrity_level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.integrity_level_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.is_appcontainer\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.privileges\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.privileges.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.privileges.enabled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.privileges.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.sid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.token.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.Ext.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.args\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.args_count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.command_line\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.command_line.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.command_line.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.entity_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.executable\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.executable.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.executable.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.exit_code\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.name.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.architecture\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.compile_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.mapped_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.Ext.mapped_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.dll.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.real\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.real.pid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.elevation\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.elevation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.impersonation_level\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.integrity_level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.integrity_level_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.is_appcontainer\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.privileges\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.privileges.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.privileges.enabled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.privileges.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.sid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.token.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.Ext.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.args\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.args_count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.command_line\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.command_line.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.command_line.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.entity_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.executable\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.executable.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.executable.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.exit_code\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.name.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pgid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.pid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.ppid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.start\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.thread.id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.thread.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.title.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.working_directory\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.working_directory.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.parent.working_directory.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.pgid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.pid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.ppid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.start\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.call_stack.instruction_pointer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.call_stack.memory_section.address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.call_stack.memory_section.protection\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.call_stack.memory_section.size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.call_stack.module_path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.call_stack.rva\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.call_stack.symbol_info\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.parameter\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.parameter_bytes_compressed\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.parameter_bytes_compressed_present\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.service\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_allocation_offset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_bytes\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_bytes_disasm\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_bytes_disasm_hash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.allocation_base\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.allocation_protection\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.allocation_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.allocation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.bytes_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.bytes_allocation_offset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.bytes_compressed\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.bytes_compressed_present\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.mapped_pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.mapped_pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.mapped_pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.mapped_pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.mapped_pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.mapped_pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.mapped_pe_detected\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.memory_pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.memory_pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.memory_pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.memory_pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.memory_pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.memory_pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.memory_pe_detected\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.region_base\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.region_protection\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.region_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.region_state\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_details.strings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.start_address_module\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.elevation\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.elevation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.impersonation_level\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.integrity_level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.integrity_level_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.is_appcontainer\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.privileges\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.privileges.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.privileges.enabled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.privileges.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.sid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.token.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.Ext.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.thread.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.title.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Target.process.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.working_directory\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.working_directory.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Target.process.working_directory.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"agent.ephemeral_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"data_stream.dataset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"data_stream.namespace\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"data_stream.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.city_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.continent_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_iso_code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.country_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.location\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_iso_code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.geo.region_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.compile_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.features\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"dll.Ext.malware_classification.features.data.buffer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.features.data.decompressed_size\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.features.data.encoding\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.identifier\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.score\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.threshold\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.upx_packed\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.malware_classification.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.mapped_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.mapped_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ecs.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elastic.agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elastic.agent.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.action\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.category\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.created\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.dataset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.hash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.ingested\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.kind\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.module\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.outcome\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.provider\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.sequence\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.severity\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.entry_modified\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.code_page\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.collection\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.collection.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.collection.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.collection.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.collection.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.errors\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.errors.count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.errors.error_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.file_extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.project_file\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.project_file.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.project_file.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.project_file.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.project_file.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream.raw_code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.macro.stream.raw_code_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.features\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"file.Ext.malware_classification.features.data.buffer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.features.data.decompressed_size\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.features.data.encoding\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.identifier\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.score\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.threshold\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.upx_packed\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.malware_classification.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original.gid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original.group\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original.mode\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original.owner\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.original.uid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.quarantine_path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.quarantine_result\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.temp_file_path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.windows\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.windows.zone_identifier\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.accessed\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.attributes\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.created\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.ctime\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.device\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.directory\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.drive_letter\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.extension\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.gid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.group\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.inode\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mime_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mode\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.mtime\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.owner\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.path.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.path.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"file.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.size\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.target_path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.target_path.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.target_path.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"file.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.uid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.Ext.real\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.Ext.real.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.Ext.real.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"group.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.architecture\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.city_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.continent_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_iso_code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.country_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.location\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_iso_code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.geo.region_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.hostname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.mac\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.Ext.variant\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.family\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"host.os.kernel\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"host.os.platform\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.Ext.real\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.Ext.real.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.Ext.real.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.email\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.full_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.full_name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"host.user.group.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.Ext.real\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.Ext.real.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.Ext.real.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.group.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.hash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.user.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.ancestry\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.architecture\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.authentication_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.compile_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.mapped_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.Ext.mapped_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.dll.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.features\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"process.Ext.malware_classification.features.data.buffer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.features.data.decompressed_size\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.features.data.encoding\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.identifier\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.score\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.threshold\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.upx_packed\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.malware_classification.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.services\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.session\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.elevation\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.elevation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.impersonation_level\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.integrity_level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.integrity_level_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.is_appcontainer\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.privileges\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.privileges.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.privileges.enabled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.privileges.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.sid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.token.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.args\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.args_count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.command_line\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.command_line.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.command_line.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.entity_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.executable\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.executable.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.executable.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.exit_code\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.name.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.architecture\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.code_signature\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.compile_time\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.mapped_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.Ext.mapped_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.dll.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.real\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.real.pid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.elevation\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.elevation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.impersonation_level\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.integrity_level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.integrity_level_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.is_appcontainer\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.privileges\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.privileges.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.privileges.enabled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.privileges.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.sid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.token.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.Ext.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.args\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.args_count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.command_line\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.command_line.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.command_line.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.parent.entity_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.executable\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.executable.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.executable.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.parent.exit_code\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.md5\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.sha1\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.hash.sha512\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.name.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pgid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.pid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.ppid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.start\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.thread.id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.thread.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.title.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.parent.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.working_directory\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.working_directory.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.working_directory.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pgid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.pid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.ppid\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.start\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.call_stack.instruction_pointer\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.call_stack.memory_section.address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.call_stack.memory_section.protection\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.call_stack.memory_section.size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.call_stack.module_path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.call_stack.rva\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.call_stack.symbol_info\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.parameter\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.parameter_bytes_compressed\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.parameter_bytes_compressed_present\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.service\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_allocation_offset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_bytes\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_bytes_disasm\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_bytes_disasm_hash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.allocation_base\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.allocation_protection\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.allocation_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.allocation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.bytes_address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.bytes_allocation_offset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.bytes_compressed\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.bytes_compressed_present\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.mapped_pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.mapped_pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.mapped_pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.mapped_pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.mapped_pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.mapped_pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.mapped_pe_detected\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.memory_pe.company\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.memory_pe.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.memory_pe.file_version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.memory_pe.imphash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.memory_pe.original_file_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.memory_pe.product\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.memory_pe_detected\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.region_base\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.region_protection\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.region_size\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.region_state\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_details.strings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.start_address_module\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.elevation\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.elevation_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.impersonation_level\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.integrity_level\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.integrity_level_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.is_appcontainer\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.privileges\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.privileges.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.privileges.enabled\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.privileges.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.sid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.token.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.Ext.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.id\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.thread.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.title\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.title.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"process.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.working_directory\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.working_directory.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.working_directory.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"rule.author\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.category\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.description\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.license\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.reference\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.ruleset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.uuid\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"rule.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.city_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.continent_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_iso_code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.country_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.location\",\"type\":\"geo_point\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_iso_code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.geo.region_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.framework\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.tactic.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.tactic.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.tactic.reference\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"threat.technique.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"threat.technique.reference\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.Ext.real\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.Ext.real.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.Ext.real.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.email\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.full_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.full_name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"user.group.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.Ext.real\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.Ext.real.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.Ext.real.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.group.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.hash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"user.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"event.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.Ext.correlation\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.Ext.correlation.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.entropy\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"file.Ext.header_data\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"file.Ext.monotonic_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.Ext.load_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dll.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.packets\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.port\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.registered_domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"destination.top_level_domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.Ext.options\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.Ext.status\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.registered_domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.subdomain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.top_level_domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.question.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"dns.resolved_ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.content\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.request.body.content.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"http.request.bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.Ext.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.content\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.body.content.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"http.response.bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"http.response.status_code\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.community_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.direction\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.iana_number\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.packets\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.protocol\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.transport\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"network.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.address\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.bytes\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.packets\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.port\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.registered_domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"source.top_level_domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"package.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.Ext.defense_evasions\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.exists\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.subject_name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.trusted\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"process.parent.code_signature.valid\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.data.bytes\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.data.strings\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.hive\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.key\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.path\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"registry.value\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]","timeFieldName":"@timestamp","title":"logs-*"},"coreMigrationVersion":"7.13.2","id":"logs-*","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1623693556928,728],"type":"index-pattern","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MTEsNF0="} -{"attributes":{"description":"this is a logstash saved query","filters":[],"query":{"language":"kuery","query":"extension.raw :\"gif\" and machine.os.raw :\"ios\" "},"timefilter":{"from":"2015-09-20T01:56:56.132Z","refreshInterval":{"pause":true,"value":0},"to":"2015-09-21T11:18:20.471Z"},"title":"logstash_saved_query"},"coreMigrationVersion":"7.13.2","id":"logstash_saved_query","references":[],"sort":[1623693556928,729],"type":"query","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MTIsNF0="} -{"attributes":{"allowNoIndex":true,"fieldFormatMap":"{\"event.sequence\":{\"id\":\"string\"},\"event.severity\":{\"id\":\"string\"}}","fields":"[{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"agent.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"data_stream.dataset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"data_stream.namespace\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"data_stream.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"ecs.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elastic.agent\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"elastic.agent.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.action\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.category\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.code\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.created\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.dataset\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.hash\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.ingested\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.kind\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.module\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.outcome\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.provider\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.sequence\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.severity\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.architecture\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.domain\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.hostname\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.ip\",\"type\":\"ip\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.mac\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.Ext\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.Ext.variant\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.family\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.full.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"host.os.kernel\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name.caseless\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.name.text\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"host.os.platform\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.os.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"host.uptime\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.cpu\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.cpu.endpoint\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.cpu.endpoint.histogram\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.cpu.endpoint.latest\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.cpu.endpoint.mean\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.disks\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Endpoint.metrics.disks.device\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.disks.endpoint_drive\",\"type\":\"boolean\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.disks.free\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.disks.fstype\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.disks.mount\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.disks.total\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.memory\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.memory.endpoint\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.memory.endpoint.private\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.memory.endpoint.private.latest\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.memory.endpoint.private.mean\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.threads\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Endpoint.metrics.uptime\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.uptime.endpoint\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.metrics.uptime.system\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.end\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event.start\",\"type\":\"date\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.actions\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.actions.message\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.actions.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.actions.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Endpoint.policy.applied.artifacts.global\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.identifiers\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.identifiers.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.identifiers.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.global.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.identifiers\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.identifiers.name\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.identifiers.sha256\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.artifacts.user.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Endpoint.policy.applied.configurations.antivirus_registration\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Endpoint.policy.applied.configurations.antivirus_registration.concerned_actions\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.antivirus_registration.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.events\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.events.concerned_actions\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.events.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.logging\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.logging.concerned_actions\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.logging.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.malware\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.malware.concerned_actions\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.malware.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.streaming\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.streaming.concerned_actions\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.configurations.streaming.status\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"Endpoint.policy.applied.response\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"Endpoint.policy.applied.version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"indexed\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]","timeFieldName":"@timestamp","title":"metrics-*"},"coreMigrationVersion":"7.13.2","id":"metrics-*","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1623693556928,730],"type":"index-pattern","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MTMsNF0="} -{"attributes":{"description":"Shakespeare query","filters":[],"query":{"language":"kuery","query":"speaker : \"OTHELLO\" and play_name :\"Othello\" "},"title":"shakespeare_current_query"},"coreMigrationVersion":"7.13.2","id":"shakespeare_current_query","references":[],"sort":[1623693556928,731],"type":"query","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MTQsNF0="} -{"attributes":{"@created":"2021-05-27T18:53:18.432Z","@timestamp":"2021-05-27T19:46:12.539Z","assets":{},"colors":["#37988d","#c19628","#b83c6f","#3f9939","#1785b0","#ca5f35","#45bdb0","#f2bc33","#e74b8b","#4fbf48","#1ea6dc","#fd7643","#72cec3","#f5cc5d","#ec77a8","#7acf74","#4cbce4","#fd986f","#a1ded7","#f8dd91","#f2a4c5","#a6dfa2","#86d2ed","#fdba9f","#000000","#444444","#777777","#BBBBBB","#FFFFFF","rgba(255,255,255,0)"],"css":".canvasPage {\n\n}","height":720,"isWriteable":true,"name":"logstash-canvas-workpad","page":1,"pages":[{"elements":[{"expression":"savedLens id=\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-56d2ba72-f227-4d04-9478-a1d6f0c7e601","position":{"angle":0,"height":300,"left":20,"parent":null,"top":20,"width":500}},{"expression":"savedVisualization id=\"0d8a8860-623a-11eb-aebf-c306684b328d\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-afbaa26e-10e7-47d4-bb41-b061dfdced2b","position":{"angle":0,"height":300,"left":527,"parent":null,"top":20,"width":500}}],"groups":[],"id":"page-0f9ef2da-2868-4c0b-9223-fd3c9e53d6c9","style":{"background":"#FFF"},"transition":{}},{"elements":[{"expression":"image dataurl=null mode=\"contain\"\n| render","id":"element-c5534ef7-68c4-46bc-b35a-9e43a7f118c3","position":{"angle":0,"height":107,"left":20,"parent":null,"top":20,"width":132}},{"expression":"filters\n| essql query=\"SELECT machine.os.raw FROM \\\"logstash-*\\\"\"\n| pointseries x=\"machine.os.raw\" y=\"size(machine.os.raw)\" color=\"machine.os.raw\" size=\"sum(machine.os.raw)\"\n| plot defaultStyle={seriesStyle points=5 fill=1}\n| render","id":"element-5f7a3312-0e77-471c-9b8f-f98cb38075fb","position":{"angle":0,"height":192,"left":221,"parent":null,"top":56,"width":451}},{"expression":"timefilterControl compact=true column=@timestamp\n| render","filter":"timefilter from=\"now-29y\" to=now column=@timestamp","id":"element-6e00dcf4-06fe-4bd9-9315-d32d9d3fac5f","position":{"angle":0,"height":50,"left":221,"parent":null,"top":-1,"width":500}},{"expression":"filters\n| esdocs index=\"logstash-*\" fields=\"@timestamp, response.raw\"\n| pointseries x=\"size(response.raw)\" y=\"@timestamp\" color=\"response.raw\"\n| plot\n| render","id":"element-20281fac-1c3a-4ee3-9132-44379fb60b74","position":{"angle":0,"height":262,"left":51,"parent":null,"top":304,"width":590}},{"expression":"filters\n| timelion query=\".es(index=logstash-*, metric=sum:bytes)\"\n| pointseries x=\"@timestamp\" y=\"sum(value)\"\n| plot defaultStyle={seriesStyle lines=3}\n| render","id":"element-337b0548-5d6d-44cd-a324-eb50d63c7bd0","position":{"angle":0,"height":309,"left":648,"parent":null,"top":290,"width":369}},{"expression":"savedLens id=\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-353e5583-0dbb-4a6b-bac7-3b2a6b305397","position":{"angle":0,"height":181.99999999999997,"left":855,"parent":"group-d2618a19-3982-414e-93df-b2cb165b7c7e","top":15.000000000000014,"width":76.961271102284}},{"expression":"savedVisualization id=\"0d8a8860-623a-11eb-aebf-c306684b328d\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-0e5501a6-9e87-42bc-b539-1e697e62051b","position":{"angle":0,"height":181.99999999999997,"left":933.038728897716,"parent":"group-d2618a19-3982-414e-93df-b2cb165b7c7e","top":15.000000000000014,"width":76.961271102284}}],"groups":[],"id":"page-59c3cf09-1811-4324-995b-7336c1c11ab8","style":{"background":"#FFF"},"transition":{}}],"variables":[],"width":1080},"coreMigrationVersion":"7.13.2","id":"workpad-f2024ca3-e366-447a-b3af-7db4400646ef","migrationVersion":{"canvas-workpad":"7.0.0"},"references":[],"sort":[1623693556928,732],"type":"canvas-workpad","updated_at":"2021-06-14T17:59:16.928Z","version":"WzE3MTUsNF0="} -{"exportedCount":87,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file +{"attributes":{"accessCount":0,"accessDate":1621977234367,"createDate":1621977234367,"url":"/app/dashboards#/view/154944b0-6249-11eb-aebf-c306684b328d?embed=true&_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(description:%27%27,filters:!(),fullScreenMode:!f,options:(darkTheme:!f,hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(enhancements:()),gridData:(h:15,i:%271%27,w:24,x:0,y:0),id:%2736b91810-6239-11eb-aebf-c306684b328d%27,panelIndex:%271%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%272%27,w:24,x:24,y:0),id:%270a274320-61cc-11eb-aebf-c306684b328d%27,panelIndex:%272%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%273%27,w:24,x:0,y:15),id:e4aef350-623d-11eb-aebf-c306684b328d,panelIndex:%273%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%274%27,w:24,x:24,y:15),id:f92e5630-623e-11eb-aebf-c306684b328d,panelIndex:%274%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%275%27,w:24,x:0,y:30),id:%279853d4d0-623d-11eb-aebf-c306684b328d%27,panelIndex:%275%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%276%27,w:24,x:24,y:30),id:%276ecb33b0-623d-11eb-aebf-c306684b328d%27,panelIndex:%276%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:(),vis:!n),gridData:(h:15,i:%277%27,w:24,x:0,y:45),id:b8e35c80-623c-11eb-aebf-c306684b328d,panelIndex:%277%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%278%27,w:24,x:24,y:45),id:f1bc75d0-6239-11eb-aebf-c306684b328d,panelIndex:%278%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%279%27,w:24,x:0,y:60),id:%270d8a8860-623a-11eb-aebf-c306684b328d%27,panelIndex:%279%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2710%27,w:24,x:24,y:60),id:d79fe3d0-6239-11eb-aebf-c306684b328d,panelIndex:%2710%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2711%27,w:24,x:0,y:75),id:%27318375a0-6240-11eb-aebf-c306684b328d%27,panelIndex:%2711%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2712%27,w:24,x:24,y:75),id:e461eb20-6245-11eb-aebf-c306684b328d,panelIndex:%2712%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2713%27,w:24,x:0,y:90),id:%2725bdc750-6242-11eb-aebf-c306684b328d%27,panelIndex:%2713%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2714%27,w:24,x:24,y:90),id:%2771dd7bc0-6248-11eb-aebf-c306684b328d%27,panelIndex:%2714%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2715%27,w:24,x:0,y:105),id:%276aea48a0-6240-11eb-aebf-c306684b328d%27,panelIndex:%2715%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2716%27,w:24,x:24,y:105),id:%2732b681f0-6241-11eb-aebf-c306684b328d%27,panelIndex:%2716%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2717%27,w:24,x:0,y:120),id:ccca99e0-6244-11eb-aebf-c306684b328d,panelIndex:%2717%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2718%27,w:24,x:24,y:120),id:a4d7be80-6245-11eb-aebf-c306684b328d,panelIndex:%2718%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2719%27,w:24,x:0,y:135),id:c94d8440-6248-11eb-aebf-c306684b328d,panelIndex:%2719%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%2720%27,w:24,x:24,y:135),id:db6226f0-61c0-11eb-aebf-c306684b328d,panelIndex:%2720%27,type:search,version:%277.13.1%27)),query:(language:lucene,query:%27%27),tags:!(),timeRestore:!f,title:logstash_dashboardwithtime,viewMode:view)"},"coreMigrationVersion":"7.13.5","id":"058bc10f0578013fc41ddedc9a1dcd1e","references":[],"sort":[1651599812857,5],"type":"url","updated_at":"2022-05-03T17:43:32.857Z","version":"WzE3LDFd"} +{"attributes":{"color":"#ba898f","description":"","name":"By value tag"},"coreMigrationVersion":"7.13.5","id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","references":[],"sort":[1651599812857,6],"type":"tag","updated_at":"2022-05-03T17:43:32.857Z","version":"WzE4LDFd"} +{"attributes":{"fieldAttrs":"{\"machine.os\":{\"count\":1},\"spaces\":{\"count\":1},\"type\":{\"count\":1},\"bytes_scripted\":{\"count\":1}}","fields":"[{\"count\":1,\"script\":\"doc['bytes'].value*1024\",\"lang\":\"painless\",\"name\":\"bytes_scripted\",\"type\":\"number\",\"scripted\":true,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false}]","runtimeFieldMap":"{}","timeFieldName":"@timestamp","title":"logstash-*"},"coreMigrationVersion":"7.13.5","id":"56b34100-619d-11eb-aebf-c306684b328d","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1651599812857,7],"type":"index-pattern","updated_at":"2022-05-03T17:43:32.857Z","version":"WzIyLDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.5\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"60aaea59-d871-4e90-9ff3-78946d6bef90\"},\"panelIndex\":\"60aaea59-d871-4e90-9ff3-78946d6bef90\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\":{\"columns\":{\"65625f0d-e7f1-4370-b939-7db27af74de7\":{\"label\":\"Top values of geo.srcdest\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":true,\"params\":{\"size\":18,\"orderBy\":{\"type\":\"column\",\"columnId\":\"553a353f-dac5-4a52-a25d-52c6e1462597\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"553a353f-dac5-4a52-a25d-52c6e1462597\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"}},\"columnOrder\":[\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"553a353f-dac5-4a52-a25d-52c6e1462597\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\",\"groups\":[\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"65625f0d-e7f1-4370-b939-7db27af74de7\",\"65625f0d-e7f1-4370-b939-7db27af74de7\"],\"metric\":\"553a353f-dac5-4a52-a25d-52c6e1462597\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9ed45b8b-534b-4fac-9fee-436896b90039\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"circular drilldown\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}}}]","timeRestore":false,"title":"lens_panel_drilldown","version":1},"coreMigrationVersion":"7.13.5","id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"60aaea59-d871-4e90-9ff3-78946d6bef90:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"60aaea59-d871-4e90-9ff3-78946d6bef90:indexpattern-datasource-layer-2174c5fe-75d2-43ae-9c79-1a7cc7bbbaea","type":"index-pattern"},{"id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","name":"60aaea59-d871-4e90-9ff3-78946d6bef90:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9ed45b8b-534b-4fac-9fee-436896b90039:dashboardId","type":"dashboard"},{"id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","name":"tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1651613174194,1151],"type":"dashboard","updated_at":"2022-05-03T21:26:14.194Z","version":"WzcxMywxXQ=="} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[{\"meta\":{\"alias\":null,\"disabled\":false,\"key\":\"geo.srcdest\",\"negate\":true,\"params\":[\"CN:CN\",\"IN:CN\",\"CN:IN\",\"IN:IN\",\"CN:US\",\"IN:US\",\"US:IN\",\"US:CN\",\"ID:CN\",\"US:US\",\"CN:ID\",\"PK:CN\",\"BR:CN\",\"CN:PK\",\"BD:CN\",\"CN:BR\",\"IN:PK\",\"NG:CN\"],\"type\":\"phrases\",\"value\":\"CN:CN, IN:CN, CN:IN, IN:IN, CN:US, IN:US, US:IN, US:CN, ID:CN, US:US, CN:ID, PK:CN, BR:CN, CN:PK, BD:CN, CN:BR, IN:PK, NG:CN\",\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"bool\":{\"minimum_should_match\":1,\"should\":[{\"match_phrase\":{\"geo.srcdest\":\"CN:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:IN\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:IN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:US\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:US\"}},{\"match_phrase\":{\"geo.srcdest\":\"US:IN\"}},{\"match_phrase\":{\"geo.srcdest\":\"US:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"ID:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"US:US\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:ID\"}},{\"match_phrase\":{\"geo.srcdest\":\"PK:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"BR:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:PK\"}},{\"match_phrase\":{\"geo.srcdest\":\"BD:CN\"}},{\"match_phrase\":{\"geo.srcdest\":\"CN:BR\"}},{\"match_phrase\":{\"geo.srcdest\":\"IN:PK\"}},{\"match_phrase\":{\"geo.srcdest\":\"NG:CN\"}}]}},\"$state\":{\"store\":\"appState\"}}]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.5\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"095e13b2-d0ac-47db-a62b-0aca28931402\"},\"panelIndex\":\"095e13b2-d0ac-47db-a62b-0aca28931402\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"f61694eb-94ed-495d-9ce8-63592f040b0b\":{\"columns\":{\"75ddcdb4-3050-4545-b401-509384b0d532\":{\"label\":\"Top values of machine.os.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"machine.os.raw\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"273e31ef-7c2d-4d0e-9063-5528f4011a51\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\"}},\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\":{\"label\":\"Average of bytes\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"75ddcdb4-3050-4545-b401-509384b0d532\",\"273e31ef-7c2d-4d0e-9063-5528f4011a51\",\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\",\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"f61694eb-94ed-495d-9ce8-63592f040b0b\",\"accessors\":[\"2f97b0f5-f0ff-40f2-abb0-bb7d1081a126\",\"2eb30654-0ead-40ac-92ab-d8d113e25ac5\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"273e31ef-7c2d-4d0e-9063-5528f4011a51\",\"splitAccessor\":\"75ddcdb4-3050-4545-b401-509384b0d532\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-f61694eb-94ed-495d-9ce8-63592f040b0b\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"da7ad2b6-1e4a-40b5-9123-d0ec2bde858d\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"lens_panel_drilldown\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}}},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"a254a623-a9af-4372-851b-572fa95b0902\"},\"panelIndex\":\"a254a623-a9af-4372-851b-572fa95b0902\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n/*\\n\\nWelcome to Vega visualizations. Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite. In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it. Use help icon to view Vega examples, tutorials, and other docs. Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range. You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n $schema: https://vega.github.io/schema/vega-lite/v4.json\\n title: Event counts from all indexes\\n\\n // Define the data source\\n data: {\\n url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\". They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n // Apply dashboard context filters when set\\n %context%: true\\n // Filter the time picker (upper right corner) with this field\\n %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for : https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n // Which index to search\\n index: _all\\n // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n body: {\\n aggs: {\\n time_buckets: {\\n date_histogram: {\\n // Use date histogram aggregation on @timestamp field\\n field: @timestamp\\n // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n interval: {%autointerval%: true}\\n // Make sure we get an entire range, even if it has no data\\n extended_bounds: {\\n // Use the current time range's start and end\\n min: {%timefilter%: \\\"min\\\"}\\n max: {%timefilter%: \\\"max\\\"}\\n }\\n // Use this for linear (e.g. line, area) graphs. Without it, empty buckets will not show up\\n min_doc_count: 0\\n }\\n }\\n }\\n // Speed up the response by only including aggregation results\\n size: 0\\n }\\n }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n time_buckets: {\\n buckets: [\\n {\\n key_as_string: 2015-11-30T22:00:00.000Z\\n key: 1448920800000\\n doc_count: 0\\n },\\n {\\n key_as_string: 2015-11-30T23:00:00.000Z\\n key: 1448924400000\\n doc_count: 0\\n }\\n ...\\n ]\\n }\\n}\\n\\nFor our graph, we only need the list of bucket values. Use the format.property to discard everything else.\\n*/\\n format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n }\\n\\n // \\\"mark\\\" is the graphics element used to show our data. Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick. See https://vega.github.io/vega-lite/docs/mark.html\\n mark: line\\n\\n // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way. See https://vega.github.io/vega-lite/docs/encoding.html\\n encoding: {\\n x: {\\n // The \\\"key\\\" value is the timestamp in milliseconds. Use it for X axis.\\n field: key\\n type: temporal\\n axis: {title: false} // Customize X axis format\\n }\\n y: {\\n // The \\\"doc_count\\\" is the count per bucket. Use it for Y axis.\\n field: doc_count\\n type: quantitative\\n axis: {title: \\\"Document count\\\"}\\n }\\n }\\n}\\n\"},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"meta\":{\"alias\":null,\"disabled\":false,\"index\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"key\":\"geo.srcdest\",\"negate\":false,\"params\":{\"query\":\"CN:CN\"},\"type\":\"phrase\"},\"query\":{\"match_phrase\":{\"geo.srcdest\":\"CN:CN\"}}}]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"cfd2521d-15a0-4c64-b0ab-d2dc18f396e3\",\"triggers\":[\"CONTEXT_MENU_TRIGGER\"],\"action\":{\"name\":\"URL\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/4acce030-ca2a-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:ip,negate:!f,params:(query:'57.237.11.219'),type:phrase),query:(match_phrase:(ip:'57.237.11.219')))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}}]}}}},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"5de83d82-bbd1-4d30-be61-dd6724f32c07\"},\"panelIndex\":\"5de83d82-bbd1-4d30-be61-dd6724f32c07\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"metrics\",\"params\":{\"annotations\":[{\"fields\":\"response.raw\",\"template\":\"{{response.raw}}\",\"index_pattern\":\"logstash-*\",\"query_string\":{\"query\":\"response.raw :\\\"404\\\" \",\"language\":\"kuery\"},\"color\":\"#F00\",\"icon\":\"fa-bomb\",\"id\":\"37395960-ca28-11eb-9eac-2f3ccefcbeef\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1,\"time_field\":\"@timestamp\"}],\"axis_formatter\":\"number\",\"axis_position\":\"left\",\"axis_scale\":\"normal\",\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"index_pattern\":\"logstash-*\",\"interval\":\"\",\"isModelInvalid\":false,\"series\":[{\"axis_position\":\"right\",\"chart_type\":\"line\",\"color\":\"#68BC00\",\"fill\":0.5,\"formatter\":\"number\",\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"line_width\":1,\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"point_size\":1,\"separate_axis\":0,\"split_color_mode\":\"kibana\",\"split_mode\":\"everything\",\"stacked\":\"none\"}],\"show_grid\":1,\"show_legend\":1,\"time_field\":\"@timestamp\",\"tooltip_mode\":\"show_all\",\"type\":\"timeseries\",\"use_kibana_indexes\":false},\"uiState\":{},\"data\":{\"aggs\":[],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"23d04651-266f-4f0a-8eef-6f190f0a84af\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"dashboard\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}}},{\"version\":\"7.13.5\",\"type\":\"map\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"ac0b1e52-de90-4c93-864b-32ce338fef51\"},\"panelIndex\":\"ac0b1e52-de90-4c93-864b-32ce338fef51\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"layerListJSON\":\"[{\\\"sourceDescriptor\\\":{\\\"type\\\":\\\"EMS_TMS\\\",\\\"isAutoSelect\\\":true},\\\"id\\\":\\\"0965c5ce-6347-43f2-917e-b938ea3862f8\\\",\\\"label\\\":null,\\\"minZoom\\\":0,\\\"maxZoom\\\":24,\\\"alpha\\\":1,\\\"visible\\\":true,\\\"style\\\":{\\\"type\\\":\\\"TILE\\\"},\\\"type\\\":\\\"VECTOR_TILE\\\"},{\\\"sourceDescriptor\\\":{\\\"indexPatternId\\\":\\\"56b34100-619d-11eb-aebf-c306684b328d\\\",\\\"geoField\\\":\\\"geo.coordinates\\\",\\\"filterByMapBounds\\\":true,\\\"scalingType\\\":\\\"CLUSTERS\\\",\\\"id\\\":\\\"8fcc6cc4-919b-418c-9815-5a002cfca117\\\",\\\"type\\\":\\\"ES_SEARCH\\\",\\\"applyGlobalQuery\\\":true,\\\"applyGlobalTime\\\":true,\\\"tooltipProperties\\\":[],\\\"sortField\\\":\\\"\\\",\\\"sortOrder\\\":\\\"desc\\\",\\\"topHitsSplitField\\\":\\\"\\\",\\\"topHitsSize\\\":1},\\\"id\\\":\\\"0b28253c-ed9e-401f-9306-feb0e58d1c0e\\\",\\\"label\\\":\\\"Clustered logstash-*\\\",\\\"minZoom\\\":0,\\\"maxZoom\\\":24,\\\"alpha\\\":0.75,\\\"visible\\\":true,\\\"style\\\":{\\\"type\\\":\\\"VECTOR\\\",\\\"properties\\\":{\\\"icon\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"value\\\":\\\"marker\\\"}},\\\"fillColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#54B399\\\"}},\\\"lineColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#41937c\\\"}},\\\"lineWidth\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":1}},\\\"iconSize\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":6}},\\\"iconOrientation\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"orientation\\\":0}},\\\"labelText\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"value\\\":\\\"\\\"}},\\\"labelColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#000000\\\"}},\\\"labelSize\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"size\\\":14}},\\\"labelBorderColor\\\":{\\\"type\\\":\\\"STATIC\\\",\\\"options\\\":{\\\"color\\\":\\\"#FFFFFF\\\"}},\\\"symbolizeAs\\\":{\\\"options\\\":{\\\"value\\\":\\\"circle\\\"}},\\\"labelBorderSize\\\":{\\\"options\\\":{\\\"size\\\":\\\"SMALL\\\"}}},\\\"isTimeAware\\\":true},\\\"type\\\":\\\"BLENDED_VECTOR\\\",\\\"joins\\\":[]}]\",\"mapStateJSON\":\"{\\\"zoom\\\":1.45,\\\"center\\\":{\\\"lon\\\":0,\\\"lat\\\":19.94277},\\\"timeFilters\\\":{\\\"from\\\":\\\"2015-09-20T01:56:56.132Z\\\",\\\"to\\\":\\\"2015-09-21T11:18:20.471Z\\\"},\\\"refreshConfig\\\":{\\\"isPaused\\\":true,\\\"interval\\\":0},\\\"query\\\":{\\\"query\\\":\\\"\\\",\\\"language\\\":\\\"kuery\\\"},\\\"filters\\\":[],\\\"settings\\\":{\\\"autoFitToDataBounds\\\":false,\\\"backgroundColor\\\":\\\"#ffffff\\\",\\\"disableInteractive\\\":false,\\\"disableTooltipControl\\\":false,\\\"hideToolbarOverlay\\\":false,\\\"hideLayerControl\\\":false,\\\"hideViewControl\\\":false,\\\"initialLocation\\\":\\\"LAST_SAVED_LOCATION\\\",\\\"fixedLocation\\\":{\\\"lat\\\":0,\\\"lon\\\":0,\\\"zoom\\\":2},\\\"browserLocation\\\":{\\\"zoom\\\":2},\\\"maxZoom\\\":24,\\\"minZoom\\\":0,\\\"showScaleControl\\\":false,\\\"showSpatialFilters\\\":true,\\\"spatialFiltersAlpa\\\":0.3,\\\"spatialFiltersFillColor\\\":\\\"#DA8B45\\\",\\\"spatialFiltersLineColor\\\":\\\"#DA8B45\\\"}}\",\"uiStateJSON\":\"{\\\"isLayerTOCOpen\\\":true,\\\"openTOCDetails\\\":[]}\"},\"mapCenter\":{\"lat\":-24.21784,\"lon\":4.3751,\"zoom\":1.45},\"mapBuffer\":{\"minLon\":-222.61538000000002,\"minLat\":-101.36965000000001,\"maxLon\":231.36558,\"maxLat\":65.74483000000001},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{}}},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"147049a3-5826-48e6-9514-17078f94b6bd\"},\"panelIndex\":\"147049a3-5826-48e6-9514-17078f94b6bd\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true},\"uiState\":{},\"data\":{\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"significant_terms\",\"params\":{\"field\":\"geo.srcdest\",\"size\":77},\"schema\":\"segment\"}],\"searchSource\":{\"index\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{}}}]","timeRestore":false,"title":"logstash_by_value_dashboard","version":1},"coreMigrationVersion":"7.13.5","id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"095e13b2-d0ac-47db-a62b-0aca28931402:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"095e13b2-d0ac-47db-a62b-0aca28931402:indexpattern-datasource-layer-f61694eb-94ed-495d-9ce8-63592f040b0b","type":"index-pattern"},{"id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","name":"095e13b2-d0ac-47db-a62b-0aca28931402:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:da7ad2b6-1e4a-40b5-9123-d0ec2bde858d:dashboardId","type":"dashboard"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"a254a623-a9af-4372-851b-572fa95b0902:kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"},{"id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","name":"5de83d82-bbd1-4d30-be61-dd6724f32c07:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:23d04651-266f-4f0a-8eef-6f190f0a84af:dashboardId","type":"dashboard"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"ac0b1e52-de90-4c93-864b-32ce338fef51:layer_1_source_index_pattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"147049a3-5826-48e6-9514-17078f94b6bd:kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","name":"tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1651613469669,1400],"type":"dashboard","updated_at":"2022-05-03T21:31:09.669Z","version":"Wzk2NiwxXQ=="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_scriptedfieldviz","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0 - 100\":\"rgb(0,104,55)\"}}}","version":1,"visState":"{\"title\":\"logstash_scriptedfieldviz\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":true,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes_scripted\",\"ranges\":[{\"from\":0,\"to\":40000},{\"from\":40001,\"to\":20000000}]}}]}"},"coreMigrationVersion":"7.13.5","id":"0a274320-61cc-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,9],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzIzLDFd"} +{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"type\":\"phrases\",\"key\":\"geo.srcdest\",\"value\":\"IN:CN\",\"params\":[\"IN:CN\"],\"alias\":null,\"negate\":false,\"disabled\":false,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"bool\":{\"should\":[{\"match_phrase\":{\"geo.srcdest\":\"IN:CN\"}}],\"minimum_should_match\":1}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"search_saved","version":1},"coreMigrationVersion":"7.13.5","id":"0abce1c0-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1651612922671,997],"type":"search","updated_at":"2022-05-03T21:22:02.671Z","version":"WzU4MCwxXQ=="} +{"attributes":{"color":"#81a93f","description":"","name":"logstash_tag"},"coreMigrationVersion":"7.13.5","id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","references":[],"sort":[1651599812857,262],"type":"tag","updated_at":"2022-05-03T17:43:32.857Z","version":"WzI1LDFd"} +{"attributes":{"description":"","layerListJSON":"[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"4c2394ca-a6a2-4f8d-9631-259eb3a9627f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"},{\"sourceDescriptor\":{\"geoField\":\"geo.coordinates\",\"filterByMapBounds\":true,\"scalingType\":\"CLUSTERS\",\"id\":\"7555324e-e793-4b7d-a9d2-cd63e6b7fe3d\",\"type\":\"ES_SEARCH\",\"applyGlobalQuery\":true,\"applyGlobalTime\":true,\"tooltipProperties\":[\"geo.srcdest\",\"machine.os\",\"type\"],\"sortField\":\"bytes_scripted\",\"sortOrder\":\"desc\",\"topHitsSplitField\":\"\",\"topHitsSize\":1,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"id\":\"6a493d8b-a220-46bc-8906-a1a7569799e0\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"colorCategory\":\"palette_0\",\"field\":{\"name\":\"extension.raw\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3},\"type\":\"CATEGORICAL\"}},\"lineColor\":{\"type\":\"DYNAMIC\",\"options\":{\"color\":\"Blues\",\"colorCategory\":\"palette_0\",\"field\":{\"name\":\"machine.os.raw\",\"origin\":\"source\"},\"fieldMetaOptions\":{\"isEnabled\":true,\"sigma\":3},\"type\":\"CATEGORICAL\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"type\":\"BLENDED_VECTOR\",\"joins\":[]}]","mapStateJSON":"{\"zoom\":1.56,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"now-15y\",\"to\":\"now\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"logstash_maps","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"7.13.5","id":"0c5974f0-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"map":"7.12.0"},"references":[{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"layer_1_source_index_pattern","type":"index-pattern"}],"sort":[1651599812857,265],"type":"map","updated_at":"2022-05-03T17:43:32.857Z","version":"WzI2LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_datatable","uiStateJSON":"{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}","version":1,"visState":"{\"title\":\"logstash_datatable\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":true,\"totalFunc\":\"sum\",\"showToolbar\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"bucket\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"response.raw\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"0d8a8860-623a-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,267],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzI3LDFd"} +{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"35fd070e-5bbc-4906-bf69-8548a213d7a0":{"columnOrder":["2bf7969f-0371-4df2-a398-0a191e428ce5","aab812d6-609b-444d-9990-1e67f85fd85d","e9829e8a-c484-4c9d-b489-f1eb3fb138d2","4fc9fb3b-29a5-4679-ab3c-90d5daaf0661"],"columns":{"2bf7969f-0371-4df2-a398-0a191e428ce5":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"4fc9fb3b-29a5-4679-ab3c-90d5daaf0661":{"dataType":"number","isBucketed":false,"label":"Moving average of Median of bytes","operationType":"moving_average","params":{"window":5},"references":["e9829e8a-c484-4c9d-b489-f1eb3fb138d2"],"scale":"ratio"},"aab812d6-609b-444d-9990-1e67f85fd85d":{"dataType":"number","isBucketed":false,"label":"Average of bytes","operationType":"average","scale":"ratio","sourceField":"bytes"},"e9829e8a-c484-4c9d-b489-f1eb3fb138d2":{"dataType":"number","isBucketed":false,"label":"Median of bytes","operationType":"median","scale":"ratio","sourceField":"bytes"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["aab812d6-609b-444d-9990-1e67f85fd85d","4fc9fb3b-29a5-4679-ab3c-90d5daaf0661"],"layerId":"35fd070e-5bbc-4906-bf69-8548a213d7a0","position":"top","seriesType":"bar_stacked","showGridlines":false,"xAccessor":"2bf7969f-0371-4df2-a398-0a191e428ce5"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barvertical_stacked_average","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-35fd070e-5bbc-4906-bf69-8548a213d7a0","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,16],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzI4LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_area_chart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_area_chart\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2010-01-28T19:25:55.242Z\",\"to\":\"2021-01-28T19:40:55.242Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"machine OS\"}}]}"},"coreMigrationVersion":"7.13.5","id":"36b91810-6239-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,18],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzI5LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_horizontal","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_horizontal\",\"type\":\"horizontal_bar\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":200},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":75,\"filter\":true,\"truncate\":100},\"title\":{\"text\":\"no of documents\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"normal\",\"data\":{\"label\":\"no of documents\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"no of documents\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"agent.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"extension.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"e4aef350-623d-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,20],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzMwLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_linechart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_linechart\",\"type\":\"line\",\"params\":{\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"radiusRatio\":51,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true,\"fittingFunction\":\"zero\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-09-18T06:38:43.311Z\",\"to\":\"2015-09-26T04:02:51.104Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"radius\",\"params\":{\"field\":\"bytes\",\"customLabel\":\"bubbles\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"f92e5630-623e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,22],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzMxLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_heatmap","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0% - 25%\":\"rgb(255,255,204)\",\"25% - 50%\":\"rgb(254,217,118)\",\"50% - 75%\":\"rgb(253,141,60)\",\"75% - 100%\":\"rgb(227,27,28)\"}}}","version":1,"visState":"{\"title\":\"logstash_heatmap\",\"type\":\"heatmap\",\"params\":{\"type\":\"heatmap\",\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Yellow to Red\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":false,\"percentageMode\":true,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"overwriteColor\":false,\"color\":\"#555\"}}],\"row\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"machine.os.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"response.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"9853d4d0-623d-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,24],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzMyLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_goalchart","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0 - 33\":\"rgb(0,104,55)\",\"33 - 67\":\"rgb(255,255,190)\",\"67 - 100\":\"rgb(165,0,38)\"}}}","version":1,"visState":"{\"title\":\"logstash_goalchart\",\"type\":\"goal\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"isDisplayWarning\":false,\"type\":\"gauge\",\"gauge\":{\"verticalSplit\":false,\"autoExtend\":false,\"percentageMode\":true,\"gaugeType\":\"Circle\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000},{\"from\":10001,\"to\":20000},{\"from\":20001,\"to\":30000}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":false,\"labels\":false,\"color\":\"#333\",\"width\":2},\"type\":\"meter\",\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60},\"minAngle\":0,\"maxAngle\":6.283185307179586}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"group\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-07-24T08:58:14.175Z\",\"to\":\"2015-11-11T13:28:17.223Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}}}]}"},"coreMigrationVersion":"7.13.5","id":"6ecb33b0-623d-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,26],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzMzLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_gauge","uiStateJSON":"{\"vis\":{\"defaultColors\":{\"0 - 50\":\"rgb(0,104,55)\",\"50 - 75\":\"rgb(255,255,190)\",\"75 - 100\":\"rgb(165,0,38)\"}}}","version":1,"visState":"{\"title\":\"logstash_gauge\",\"type\":\"gauge\",\"params\":{\"type\":\"gauge\",\"addTooltip\":true,\"addLegend\":true,\"isDisplayWarning\":false,\"gauge\":{\"extendRange\":true,\"percentageMode\":false,\"gaugeType\":\"Arc\",\"gaugeStyle\":\"Full\",\"backStyle\":\"Full\",\"orientation\":\"vertical\",\"colorSchema\":\"Green to Red\",\"gaugeColorMode\":\"Labels\",\"colorsRange\":[{\"from\":0,\"to\":50},{\"from\":50,\"to\":75},{\"from\":75,\"to\":100}],\"invertColors\":false,\"labels\":{\"show\":true,\"color\":\"black\"},\"scale\":{\"show\":true,\"labels\":false,\"color\":\"#333\"},\"type\":\"meter\",\"style\":{\"bgWidth\":0.9,\"width\":0.9,\"mask\":false,\"bgMask\":false,\"maskBars\":50,\"bgFill\":\"#eee\",\"bgColor\":false,\"subText\":\"\",\"fontSize\":60,\"labelColor\":true},\"alignment\":\"horizontal\"}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes\",\"ranges\":[{\"from\":0,\"to\":10001},{\"from\":10002,\"to\":1000000}],\"json\":\"\"}}]}"},"coreMigrationVersion":"7.13.5","id":"b8e35c80-623c-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,28],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzM0LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_coordinatemaps","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_coordinatemaps\",\"type\":\"tile_map\",\"params\":{\"colorSchema\":\"Yellow to Red\",\"mapType\":\"Scaled Circle Markers\",\"isDesaturated\":false,\"addTooltip\":true,\"heatClusterSize\":1.5,\"legendPosition\":\"bottomright\",\"mapZoom\":2,\"mapCenter\":[0,0],\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"selectedTmsLayer\":{\"origin\":\"elastic_maps_service\",\"id\":\"road_map\",\"minZoom\":0,\"maxZoom\":18,\"attribution\":\"

© OpenStreetMap contributors|OpenMapTiles|Elastic Maps Service

\"}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"geohash_grid\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.coordinates\",\"autoPrecision\":true,\"isFilteredByCollar\":true,\"useGeocentroid\":true,\"mapZoom\":2,\"mapCenter\":[0,0],\"precision\":2,\"customLabel\":\"logstash src/dest\"}}]}"},"coreMigrationVersion":"7.13.5","id":"f1bc75d0-6239-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,30],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzM1LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"logstash_inputcontrols","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_inputcontrols\",\"type\":\"input_control_vis\",\"params\":{\"controls\":[{\"id\":\"1611928563867\",\"fieldName\":\"machine.ram\",\"parent\":\"\",\"label\":\"Logstash RAM\",\"type\":\"range\",\"options\":{\"decimalPlaces\":0,\"step\":1024},\"indexPatternRefName\":\"control_0_index_pattern\"},{\"id\":\"1611928586274\",\"fieldName\":\"machine.os.raw\",\"parent\":\"\",\"label\":\"Logstash OS\",\"type\":\"list\",\"options\":{\"type\":\"terms\",\"multiselect\":true,\"dynamicOptions\":true,\"size\":5,\"order\":\"desc\"},\"indexPatternRefName\":\"control_1_index_pattern\"}],\"updateFiltersOnChange\":false,\"useTimeFilter\":false,\"pinFilters\":false},\"aggs\":[]}"},"coreMigrationVersion":"7.13.5","id":"d79fe3d0-6239-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"control_0_index_pattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"control_1_index_pattern","type":"index-pattern"}],"sort":[1651599812857,33],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzM2LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"logstash_markdown","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_markdown\",\"type\":\"markdown\",\"params\":{\"fontSize\":12,\"openLinksInNewTab\":true,\"markdown\":\"Kibana is built with JS https://www.javascript.com/\"},\"aggs\":[]}"},"coreMigrationVersion":"7.13.5","id":"318375a0-6240-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1651599812857,34],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzM3LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"title":"logstash_vegaviz","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_vegaviz\",\"type\":\"vega\",\"params\":{\"spec\":\"{\\n/*\\n\\nWelcome to Vega visualizations. Here you can design your own dataviz from scratch using a declarative language called Vega, or its simpler form Vega-Lite. In Vega, you have the full control of what data is loaded, even from multiple sources, how that data is transformed, and what visual elements are used to show it. Use help icon to view Vega examples, tutorials, and other docs. Use the wrench icon to reformat this text, or to remove comments.\\n\\nThis example graph shows the document count in all indexes in the current time range. You might need to adjust the time filter in the upper right corner.\\n*/\\n\\n $schema: https://vega.github.io/schema/vega-lite/v2.json\\n title: Event counts from all indexes\\n\\n // Define the data source\\n data: {\\n url: {\\n/*\\nAn object instead of a string for the \\\"url\\\" param is treated as an Elasticsearch query. Anything inside this object is not part of the Vega language, but only understood by Kibana and Elasticsearch server. This query counts the number of documents per time interval, assuming you have a @timestamp field in your data.\\n\\nKibana has a special handling for the fields surrounded by \\\"%\\\". They are processed before the the query is sent to Elasticsearch. This way the query becomes context aware, and can use the time range and the dashboard filters.\\n*/\\n\\n // Apply dashboard context filters when set\\n %context%: true\\n // Filter the time picker (upper right corner) with this field\\n %timefield%: @timestamp\\n\\n/*\\nSee .search() documentation for : https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search\\n*/\\n\\n // Which index to search\\n index: logstash-*\\n // Aggregate data by the time field into time buckets, counting the number of documents in each bucket.\\n body: {\\n aggs: {\\n time_buckets: {\\n date_histogram: {\\n // Use date histogram aggregation on @timestamp field\\n field: @timestamp\\n // The interval value will depend on the daterange picker (true), or use an integer to set an approximate bucket count\\n interval: {%autointerval%: true}\\n // Make sure we get an entire range, even if it has no data\\n extended_bounds: {\\n // Use the current time range's start and end\\n min: {%timefilter%: \\\"min\\\"}\\n max: {%timefilter%: \\\"max\\\"}\\n }\\n // Use this for linear (e.g. line, area) graphs. Without it, empty buckets will not show up\\n min_doc_count: 13\\n }\\n }\\n }\\n // Speed up the response by only including aggregation results\\n size: 0\\n }\\n }\\n/*\\nElasticsearch will return results in this format:\\n\\naggregations: {\\n time_buckets: {\\n buckets: [\\n {\\n key_as_string: 2015-11-30T22:00:00.000Z\\n key: 1448920800000\\n doc_count: 0\\n },\\n {\\n key_as_string: 2015-11-30T23:00:00.000Z\\n key: 1448924400000\\n doc_count: 0\\n }\\n ...\\n ]\\n }\\n}\\n\\nFor our graph, we only need the list of bucket values. Use the format.property to discard everything else.\\n*/\\n format: {property: \\\"aggregations.time_buckets.buckets\\\"}\\n }\\n\\n // \\\"mark\\\" is the graphics element used to show our data. Other mark values are: area, bar, circle, line, point, rect, rule, square, text, and tick. See https://vega.github.io/vega-lite/docs/mark.html\\n mark: line\\n\\n // \\\"encoding\\\" tells the \\\"mark\\\" what data to use and in what way. See https://vega.github.io/vega-lite/docs/encoding.html\\n encoding: {\\n x: {\\n // The \\\"key\\\" value is the timestamp in milliseconds. Use it for X axis.\\n field: key\\n type: temporal\\n axis: {title: false} // Customize X axis format\\n }\\n y: {\\n // The \\\"doc_count\\\" is the count per bucket. Use it for Y axis.\\n field: doc_count\\n type: quantitative\\n axis: {title: \\\"Document count\\\"}\\n }\\n }\\n}\\n\"},\"aggs\":[]}"},"coreMigrationVersion":"7.13.5","id":"e461eb20-6245-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1651599812857,35],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzM4LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_regionmap","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_regionmap\",\"type\":\"region_map\",\"params\":{\"addTooltip\":true,\"colorSchema\":\"Yellow to Red\",\"emsHotLink\":\"https://maps.elastic.co/v6.7?locale=en#file/world_countries\",\"isDisplayWarning\":true,\"legendPosition\":\"bottomright\",\"mapCenter\":[0,0],\"mapZoom\":2,\"outlineWeight\":1,\"selectedJoinField\":{\"type\":\"id\",\"name\":\"iso2\",\"description\":\"ISO 3166-1 alpha-2 code\"},\"showAllShapes\":true,\"wms\":{\"enabled\":false,\"options\":{\"format\":\"image/png\",\"transparent\":true},\"selectedTmsLayer\":{\"origin\":\"elastic_maps_service\",\"id\":\"road_map\",\"minZoom\":0,\"maxZoom\":18,\"attribution\":\"

© OpenStreetMap contributors|OpenMapTiles|Elastic Maps Service

\"}},\"selectedLayer\":{\"name\":\"World Countries\",\"origin\":\"elastic_maps_service\",\"id\":\"world_countries\",\"created_at\":\"2017-04-26T17:12:15.978370\",\"attribution\":\"Made with NaturalEarth | Elastic Maps Service\",\"fields\":[{\"type\":\"id\",\"name\":\"iso2\",\"description\":\"ISO 3166-1 alpha-2 code\"},{\"type\":\"id\",\"name\":\"iso3\",\"description\":\"ISO 3166-1 alpha-3 code\"},{\"type\":\"property\",\"name\":\"name\",\"description\":\"name\"}],\"format\":{\"type\":\"geojson\"},\"layerId\":\"elastic_maps_service.World Countries\",\"isEMS\":true}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.dest\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"25bdc750-6242-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,37],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzM5LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_verticalbarchart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_verticalbarchart\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\",\"defaultYExtents\":true},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":true,\"row\":true,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2015-09-18T06:38:43.311Z\",\"to\":\"2015-09-26T04:02:51.104Z\",\"mode\":\"absolute\"},\"useNormalizedEsInterval\":true,\"interval\":\"h\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"scaleMetricValues\":true}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"split\",\"params\":{\"field\":\"response.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Response code\"}}]}"},"coreMigrationVersion":"7.13.5","id":"71dd7bc0-6248-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,39],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQwLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_metricviz","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_metricviz\",\"type\":\"metric\",\"params\":{\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\",\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"range\",\"schema\":\"group\",\"params\":{\"field\":\"bytes_scripted\",\"ranges\":[{\"from\":0,\"to\":10000},{\"from\":10001,\"to\":300000}]}}]}"},"coreMigrationVersion":"7.13.5","id":"6aea48a0-6240-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,41],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQxLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_piechart","uiStateJSON":"{}","version":1,"visState":"{\"aggs\":[{\"enabled\":true,\"id\":\"1\",\"params\":{},\"schema\":\"metric\",\"type\":\"count\"},{\"enabled\":true,\"id\":\"2\",\"params\":{\"field\":\"machine.os.raw\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"size\":5},\"schema\":\"segment\",\"type\":\"terms\"}],\"params\":{\"addLegend\":true,\"addTooltip\":true,\"isDonut\":true,\"labels\":{\"last_level\":true,\"show\":false,\"truncate\":100,\"values\":true},\"legendPosition\":\"right\",\"type\":\"pie\"},\"title\":\"logstash_piechart\",\"type\":\"pie\"}"},"coreMigrationVersion":"7.13.5","id":"32b681f0-6241-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,43],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQyLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"logstash_tagcloud","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_tagcloud\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"log\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"geo.srcdest\",\"size\":23,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"ccca99e0-6244-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,45],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQzLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"title":"logstash_timelion","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_timelion\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(q='machine.os.raw:win xp' , index=logstash-*)\",\"interval\":\"auto\"},\"aggs\":[]}"},"coreMigrationVersion":"7.13.5","id":"a4d7be80-6245-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1651599812857,46],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQ0LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{}"},"title":"logstash_tsvb","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_tsvb\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"everything\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"split_color_mode\":\"gradient\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"show_grid\":1,\"annotations\":[{\"fields\":\"machine.os.raw\",\"template\":\"{{machine.os.raw}}\",\"index_pattern\":\"logstash-*\",\"query_string\":{\"query\":\"machine.os.raw :\\\"win xp\\\" \",\"language\":\"lucene\"},\"id\":\"aa43ceb0-6248-11eb-9a82-ef1c6e6c0265\",\"color\":\"#F00\",\"time_field\":\"@timestamp\",\"icon\":\"fa-tag\",\"ignore_global_filters\":1,\"ignore_panel_filters\":1}],\"use_kibana_indexes\":false},\"aggs\":[]}"},"coreMigrationVersion":"7.13.5","id":"c94d8440-6248-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1651599812857,47],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQ1LDFd"} +{"attributes":{"columns":["bytes_scripted"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"machine.os.raw :\\\"win xp\\\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"logstash_scripted_saved_search","version":1},"coreMigrationVersion":"7.13.5","id":"db6226f0-61c0-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,49],"type":"search","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQ2LDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_2\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_5\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_6\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"7\",\"w\":24,\"x\":0,\"y\":45},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{},\"vis\":null},\"panelRefName\":\"panel_7\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"8\",\"w\":24,\"x\":24,\"y\":45},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"9\",\"w\":24,\"x\":0,\"y\":60},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"10\",\"w\":24,\"x\":24,\"y\":60},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"11\",\"w\":24,\"x\":0,\"y\":75},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"12\",\"w\":24,\"x\":24,\"y\":75},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"13\",\"w\":24,\"x\":0,\"y\":90},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"14\",\"w\":24,\"x\":24,\"y\":90},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"15\",\"w\":24,\"x\":0,\"y\":105},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"16\",\"w\":24,\"x\":24,\"y\":105},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"17\",\"w\":24,\"x\":0,\"y\":120},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"18\",\"w\":24,\"x\":24,\"y\":120},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"19\",\"w\":24,\"x\":0,\"y\":135},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.13.5\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"20\",\"w\":24,\"x\":24,\"y\":135},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"logstash_dashboardwithtime","version":1},"coreMigrationVersion":"7.13.5","id":"154944b0-6249-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"36b91810-6239-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"0a274320-61cc-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"e4aef350-623d-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"f92e5630-623e-11eb-aebf-c306684b328d","name":"4:panel_4","type":"visualization"},{"id":"9853d4d0-623d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"visualization"},{"id":"6ecb33b0-623d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"visualization"},{"id":"b8e35c80-623c-11eb-aebf-c306684b328d","name":"7:panel_7","type":"visualization"},{"id":"f1bc75d0-6239-11eb-aebf-c306684b328d","name":"8:panel_8","type":"visualization"},{"id":"0d8a8860-623a-11eb-aebf-c306684b328d","name":"9:panel_9","type":"visualization"},{"id":"d79fe3d0-6239-11eb-aebf-c306684b328d","name":"10:panel_10","type":"visualization"},{"id":"318375a0-6240-11eb-aebf-c306684b328d","name":"11:panel_11","type":"visualization"},{"id":"e461eb20-6245-11eb-aebf-c306684b328d","name":"12:panel_12","type":"visualization"},{"id":"25bdc750-6242-11eb-aebf-c306684b328d","name":"13:panel_13","type":"visualization"},{"id":"71dd7bc0-6248-11eb-aebf-c306684b328d","name":"14:panel_14","type":"visualization"},{"id":"6aea48a0-6240-11eb-aebf-c306684b328d","name":"15:panel_15","type":"visualization"},{"id":"32b681f0-6241-11eb-aebf-c306684b328d","name":"16:panel_16","type":"visualization"},{"id":"ccca99e0-6244-11eb-aebf-c306684b328d","name":"17:panel_17","type":"visualization"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"18:panel_18","type":"visualization"},{"id":"c94d8440-6248-11eb-aebf-c306684b328d","name":"19:panel_19","type":"visualization"},{"id":"db6226f0-61c0-11eb-aebf-c306684b328d","name":"20:panel_20","type":"search"}],"sort":[1651613667249,1638],"type":"dashboard","updated_at":"2022-05-03T21:34:27.249Z","version":"WzExNDMsMV0="} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"26e2cf99-d931-4320-9e15-9dbc148f3534":{"columnOrder":["6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e","beb72af1-239c-46d8-823b-b00d1e2ace43"],"columns":{"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e":{"dataType":"string","isBucketed":true,"label":"Top values of url.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"beb72af1-239c-46d8-823b-b00d1e2ace43","type":"column"},"orderDirection":"desc","otherBucket":true,"size":20},"scale":"ordinal","sourceField":"url.raw"},"beb72af1-239c-46d8-823b-b00d1e2ace43":{"dataType":"number","isBucketed":false,"label":"Unique count of geo.srcdest","operationType":"unique_count","scale":"ratio","sourceField":"geo.srcdest"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e","6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e","6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e"],"layerId":"26e2cf99-d931-4320-9e15-9dbc148f3534","legendDisplay":"default","metric":"beb72af1-239c-46d8-823b-b00d1e2ace43","nestedLegend":false,"numberDisplay":"percent"}],"shape":"donut"}},"title":"lens_pie_chart","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.5","id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,53],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQ4LDFd"} +{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"a3ac0e3d-63ec-49b2-882a-b34680a967ba":{"columnOrder":["352a2c02-aa6f-4a35-b776-45c3715a6c5e","8ef68cbb-e039-49d6-b15e-be81559f4b55","14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a"],"columns":{"14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"352a2c02-aa6f-4a35-b776-45c3715a6c5e":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a","type":"column"},"orderDirection":"desc","otherBucket":true,"size":67},"scale":"ordinal","sourceField":"geo.srcdest"},"8ef68cbb-e039-49d6-b15e-be81559f4b55":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["14fad6b1-6a7c-4ae8-ae4b-d9569e31e04a"],"layerId":"a3ac0e3d-63ec-49b2-882a-b34680a967ba","position":"top","seriesType":"bar_percentage_stacked","showGridlines":false,"splitAccessor":"352a2c02-aa6f-4a35-b776-45c3715a6c5e","xAccessor":"8ef68cbb-e039-49d6-b15e-be81559f4b55"}],"legend":{"isVisible":true,"position":"top","showSingleSeries":true},"preferredSeriesType":"bar_percentage_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_bar_verticalpercentage","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-a3ac0e3d-63ec-49b2-882a-b34680a967ba","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,57],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzQ5LDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"037b7937-790b-4d2d-94a5-7f5837a6ef05":{"columnOrder":["b3d46616-75e0-419e-97ea-91148961ef94","025a0fb3-dc44-4f5c-b517-2d71d3f26f14","c476db14-0cc1-40ec-863e-d2779256a407"],"columns":{"025a0fb3-dc44-4f5c-b517-2d71d3f26f14":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"b3d46616-75e0-419e-97ea-91148961ef94":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c476db14-0cc1-40ec-863e-d2779256a407","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"geo.srcdest"},"c476db14-0cc1-40ec-863e-d2779256a407":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"lucene","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c476db14-0cc1-40ec-863e-d2779256a407"],"layerId":"037b7937-790b-4d2d-94a5-7f5837a6ef05","position":"top","seriesType":"bar_stacked","showGridlines":false,"splitAccessor":"b3d46616-75e0-419e-97ea-91148961ef94","xAccessor":"025a0fb3-dc44-4f5c-b517-2d71d3f26f14"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barchart_vertical","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,61],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzUwLDFd"} +{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"212688dc-e7d7-4875-a221-09e6191bdcf7":{"columnOrder":["05410186-83c4-460a-82bf-dd7e9d998c9f","e8659feb-1db4-4706-9147-ac1fd513a1ba","c9a32fd0-a465-44fb-8adc-b957fb72cad5"],"columns":{"05410186-83c4-460a-82bf-dd7e9d998c9f":{"dataType":"string","isBucketed":true,"label":"Top values of extension.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c9a32fd0-a465-44fb-8adc-b957fb72cad5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"extension.raw"},"c9a32fd0-a465-44fb-8adc-b957fb72cad5":{"dataType":"number","isBucketed":false,"label":"Average of bytes","operationType":"average","scale":"ratio","sourceField":"bytes"},"e8659feb-1db4-4706-9147-ac1fd513a1ba":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c9a32fd0-a465-44fb-8adc-b957fb72cad5"],"layerId":"212688dc-e7d7-4875-a221-09e6191bdcf7","position":"top","seriesType":"bar_horizontal_stacked","showGridlines":false,"splitAccessor":"05410186-83c4-460a-82bf-dd7e9d998c9f","xAccessor":"e8659feb-1db4-4706-9147-ac1fd513a1ba"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_horizontal_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barhorizontal_stacked","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-212688dc-e7d7-4875-a221-09e6191bdcf7","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,65],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzUxLDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"7ab04fd4-04da-4023-8899-d94620193607":{"columnOrder":["0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7","9eb851dd-31f6-481a-84d1-9ecce53a6ad2","f6b271a7-509b-4c37-b7b6-ac5be4bcb49a"],"columns":{"0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7":{"dataType":"string","isBucketed":true,"label":"Top values of request.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"f6b271a7-509b-4c37-b7b6-ac5be4bcb49a","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"request.raw"},"9eb851dd-31f6-481a-84d1-9ecce53a6ad2":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"f6b271a7-509b-4c37-b7b6-ac5be4bcb49a":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["f6b271a7-509b-4c37-b7b6-ac5be4bcb49a"],"layerId":"7ab04fd4-04da-4023-8899-d94620193607","position":"top","seriesType":"bar_horizontal_percentage_stacked","showGridlines":false,"splitAccessor":"0ab2d5f8-11f0-4b25-b8bb-3127a3b8d4c7","xAccessor":"9eb851dd-31f6-481a-84d1-9ecce53a6ad2"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_horizontal_percentage_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_barhorizontalpercentage","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-7ab04fd4-04da-4023-8899-d94620193607","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,69],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzUyLDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"037b7937-790b-4d2d-94a5-7f5837a6ef05":{"columnOrder":["b3d46616-75e0-419e-97ea-91148961ef94","025a0fb3-dc44-4f5c-b517-2d71d3f26f14","c476db14-0cc1-40ec-863e-d2779256a407"],"columns":{"025a0fb3-dc44-4f5c-b517-2d71d3f26f14":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"b3d46616-75e0-419e-97ea-91148961ef94":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c476db14-0cc1-40ec-863e-d2779256a407","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"geo.srcdest"},"c476db14-0cc1-40ec-863e-d2779256a407":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"lucene","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c476db14-0cc1-40ec-863e-d2779256a407"],"layerId":"037b7937-790b-4d2d-94a5-7f5837a6ef05","position":"top","seriesType":"bar_stacked","showGridlines":false,"splitAccessor":"b3d46616-75e0-419e-97ea-91148961ef94","xAccessor":"025a0fb3-dc44-4f5c-b517-2d71d3f26f14"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_visualization","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651612765795,977],"type":"lens","updated_at":"2022-05-03T21:19:25.795Z","version":"WzU1NSwxXQ=="} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"72783e5f-aa7b-4b8a-b26c-a3e4d051340e":{"columnOrder":["0f619652-9ff1-453b-ae1f-7371baa82f55"],"columns":{"0f619652-9ff1-453b-ae1f-7371baa82f55":{"dataType":"number","isBucketed":false,"label":"Average of phpmemory","operationType":"average","params":{"format":{"id":"percent","params":{"decimals":10}}},"scale":"ratio","sourceField":"phpmemory"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"accessor":"0f619652-9ff1-453b-ae1f-7371baa82f55","layerId":"72783e5f-aa7b-4b8a-b26c-a3e4d051340e"}},"title":"lens_metric","visualizationType":"lnsMetric"},"coreMigrationVersion":"7.13.5","id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-72783e5f-aa7b-4b8a-b26c-a3e4d051340e","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,73],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzU0LDFd"} +{"attributes":{"description":null,"state":{"datasourceStates":{"indexpattern":{"layers":{"bb478774-f9e8-4380-bf3a-f4a89a4d79b5":{"columnOrder":["4573ae8f-8f9d-4918-b496-c08f7102c6e1","cebdc6c5-3587-4f57-879c-dd63ea99cf03"],"columns":{"4573ae8f-8f9d-4918-b496-c08f7102c6e1":{"dataType":"string","isBucketed":true,"label":"Top values of machine.os.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"cebdc6c5-3587-4f57-879c-dd63ea99cf03","type":"column"},"orderDirection":"desc","otherBucket":true,"size":5},"scale":"ordinal","sourceField":"machine.os.raw"},"cebdc6c5-3587-4f57-879c-dd63ea99cf03":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["4573ae8f-8f9d-4918-b496-c08f7102c6e1"],"layerId":"bb478774-f9e8-4380-bf3a-f4a89a4d79b5","legendDisplay":"default","metric":"cebdc6c5-3587-4f57-879c-dd63ea99cf03","nestedLegend":false,"numberDisplay":"percent"}],"shape":"pie"}},"title":"lens_piechart","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.5","id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-bb478774-f9e8-4380-bf3a-f4a89a4d79b5","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,77],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzU1LDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"a1b85651-db29-441f-8f08-cf1b9b6f7bf1":{"columnOrder":["2b3bdc32-0be0-49dc-993d-4630b0bd1185","b85cc0a7-0b18-4b08-b7f0-c617f80cf903","03203126-8286-444d-b5b3-4f399eaf2c26","44305317-61e8-4600-9f3c-ac4070e0c529"],"columns":{"03203126-8286-444d-b5b3-4f399eaf2c26":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"2b3bdc32-0be0-49dc-993d-4630b0bd1185":{"dataType":"string","isBucketed":true,"label":"Top values of extension.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"44305317-61e8-4600-9f3c-ac4070e0c529","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"extension.raw"},"44305317-61e8-4600-9f3c-ac4070e0c529":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"b85cc0a7-0b18-4b08-b7f0-c617f80cf903":{"dataType":"string","isBucketed":true,"label":"Top values of machine.os.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"44305317-61e8-4600-9f3c-ac4070e0c529","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"machine.os.raw"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"columns":[{"columnId":"2b3bdc32-0be0-49dc-993d-4630b0bd1185","isTransposed":false},{"columnId":"b85cc0a7-0b18-4b08-b7f0-c617f80cf903","isTransposed":false},{"columnId":"03203126-8286-444d-b5b3-4f399eaf2c26","isTransposed":false},{"columnId":"44305317-61e8-4600-9f3c-ac4070e0c529","isTransposed":false}],"layerId":"a1b85651-db29-441f-8f08-cf1b9b6f7bf1"}},"title":"lens_table","visualizationType":"lnsDatatable"},"coreMigrationVersion":"7.13.5","id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-a1b85651-db29-441f-8f08-cf1b9b6f7bf1","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,81],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzU2LDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9":{"columnOrder":["08a1af05-743d-480e-9056-3405b1bdda7d","bae35990-75c2-487f-94eb-d8e03d2eda33"],"columns":{"08a1af05-743d-480e-9056-3405b1bdda7d":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"bae35990-75c2-487f-94eb-d8e03d2eda33","type":"column"},"orderDirection":"desc","otherBucket":true,"size":25},"scale":"ordinal","sourceField":"geo.srcdest"},"bae35990-75c2-487f-94eb-d8e03d2eda33":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["08a1af05-743d-480e-9056-3405b1bdda7d","08a1af05-743d-480e-9056-3405b1bdda7d","08a1af05-743d-480e-9056-3405b1bdda7d"],"layerId":"4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9","legendDisplay":"default","metric":"bae35990-75c2-487f-94eb-d8e03d2eda33","nestedLegend":false,"numberDisplay":"percent"}],"shape":"treemap"}},"title":"lens_treemap","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.5","id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-4fbb51e9-1f99-4b5e-b59d-60fcb547b1d9","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,85],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzU3LDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"e84503c1-4dbd-4ac6-9ac9-ad938654680f":{"columnOrder":["38c73fd4-6330-4162-8a7b-1a059f005da8","e8d4dad2-ac30-4741-aca0-904eb1fc8455","70433aa7-3c2c-4e6c-b8cf-4218c995cff5"],"columns":{"38c73fd4-6330-4162-8a7b-1a059f005da8":{"dataType":"string","isBucketed":true,"label":"Top values of url.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"70433aa7-3c2c-4e6c-b8cf-4218c995cff5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"url.raw"},"70433aa7-3c2c-4e6c-b8cf-4218c995cff5":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"e8d4dad2-ac30-4741-aca0-904eb1fc8455":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["70433aa7-3c2c-4e6c-b8cf-4218c995cff5"],"layerId":"e84503c1-4dbd-4ac6-9ac9-ad938654680f","position":"top","seriesType":"line","showGridlines":false,"splitAccessor":"38c73fd4-6330-4162-8a7b-1a059f005da8","xAccessor":"e8d4dad2-ac30-4741-aca0-904eb1fc8455"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"line","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_line_chart","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-e84503c1-4dbd-4ac6-9ac9-ad938654680f","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,89],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzU4LDFd"} +{"attributes":{"fieldAttrs":"{\"speaker\":{\"count\":1},\"text_entry\":{\"count\":6},\"type\":{\"count\":3}}","fields":"[]","runtimeFieldMap":"{}","title":"shakespeare"},"coreMigrationVersion":"7.13.5","id":"4e937b20-619d-11eb-aebf-c306684b328d","migrationVersion":{"index-pattern":"7.11.0"},"references":[],"sort":[1651599812857,90],"type":"index-pattern","updated_at":"2022-05-03T17:43:32.857Z","version":"WzU5LDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"d35680ce-c285-4fae-89d6-1245671bbc78":{"columnOrder":["2bcbffbe-c24d-4e74-8a03-9a6da7db70c0","6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff","8319857d-a03b-4158-bdf1-2a788e510445"],"columns":{"2bcbffbe-c24d-4e74-8a03-9a6da7db70c0":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff":{"dataType":"number","isBucketed":false,"label":"Average of bytes","operationType":"average","scale":"ratio","sourceField":"bytes"},"8319857d-a03b-4158-bdf1-2a788e510445":{"dataType":"number","isBucketed":false,"label":"Sum of bytes_scripted","operationType":"sum","params":{"format":{"id":"number","params":{"decimals":2}}},"scale":"ratio","sourceField":"bytes_scripted"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["6b00fde6-bfaa-4da1-beeb-bfd85a4cb2ff","8319857d-a03b-4158-bdf1-2a788e510445"],"layerId":"d35680ce-c285-4fae-89d6-1245671bbc78","position":"top","seriesType":"area","showGridlines":false,"xAccessor":"2bcbffbe-c24d-4e74-8a03-9a6da7db70c0","yConfig":[{"axisMode":"auto","forAccessor":"8319857d-a03b-4158-bdf1-2a788e510445"}]}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"area","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_area_chart","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-d35680ce-c285-4fae-89d6-1245671bbc78","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,94],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzYwLDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"70bd567e-8e67-4696-a406-313b06344fa9":{"columnOrder":["96ddedfb-043b-479e-a746-600e72ab546e","d325b7da-4266-4035-9b13-5f853615149a","2fc1391b-17d1-4c49-9ddc-06ff307e3520","1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3"],"columns":{"1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3":{"dataType":"number","isBucketed":false,"label":"Average of machine.ram","operationType":"average","scale":"ratio","sourceField":"machine.ram"},"2fc1391b-17d1-4c49-9ddc-06ff307e3520":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"96ddedfb-043b-479e-a746-600e72ab546e":{"dataType":"string","isBucketed":true,"label":"Top values of machine.os.raw","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"2fc1391b-17d1-4c49-9ddc-06ff307e3520","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"machine.os.raw"},"d325b7da-4266-4035-9b13-5f853615149a":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["2fc1391b-17d1-4c49-9ddc-06ff307e3520","1cc6f19c-cbcb-4abd-b56d-1a2f9deae5f3"],"layerId":"70bd567e-8e67-4696-a406-313b06344fa9","position":"top","seriesType":"area_stacked","showGridlines":false,"splitAccessor":"96ddedfb-043b-479e-a746-600e72ab546e","xAccessor":"d325b7da-4266-4035-9b13-5f853615149a"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"area_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_area_stacked","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-70bd567e-8e67-4696-a406-313b06344fa9","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,98],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzYxLDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\"},\"panelIndex\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"26e2cf99-d931-4320-9e15-9dbc148f3534\":{\"columns\":{\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\":{\"label\":\"Top values of url.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"url.raw\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"beb72af1-239c-46d8-823b-b00d1e2ace43\":{\"label\":\"Unique count of geo.srcdest\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":false}},\"columnOrder\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"beb72af1-239c-46d8-823b-b00d1e2ace43\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"26e2cf99-d931-4320-9e15-9dbc148f3534\",\"groups\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\"],\"metric\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534\"}]},\"enhancements\":{},\"type\":\"lens\"},\"panelRefName\":\"panel_2e80716f-c1b6-46f2-be2b-35db744b5031\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"da8843e0-6789-4aae-bcd0-81f270538719\"},\"panelIndex\":\"da8843e0-6789-4aae-bcd0-81f270538719\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_da8843e0-6789-4aae-bcd0-81f270538719\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},\"panelIndex\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"869754a7-edf0-478f-a7f1-80374f63108a\"},\"panelIndex\":\"869754a7-edf0-478f-a7f1-80374f63108a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_869754a7-edf0-478f-a7f1-80374f63108a\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"67111cf4-338e-453f-8621-e8dea64082d1\"},\"panelIndex\":\"67111cf4-338e-453f-8621-e8dea64082d1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_67111cf4-338e-453f-8621-e8dea64082d1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},\"panelIndex\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\"},\"panelIndex\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_88847944-ae1b-45fd-b102-3b45f9bea04b\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\"},\"panelIndex\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5a7924c7-eac0-4573-9199-fecec5b82e9e\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\"},\"panelIndex\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f8f49591-f071-4a96-b1ed-cd65daff5648\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9f357f47-c2a0-421f-a456-9583c40837ab\"},\"panelIndex\":\"9f357f47-c2a0-421f-a456-9583c40837ab\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9f357f47-c2a0-421f-a456-9583c40837ab\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\"},\"panelIndex\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cb383e9-1e80-44f9-80d5-7b8c585668db\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\"},\"panelIndex\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_57f5f0bf-6610-4599-aad4-37484640b5e2\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},\"panelIndex\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"dd1718fd-74ee-4032-851b-db97e893825d\"},\"panelIndex\":\"dd1718fd-74ee-4032-851b-db97e893825d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd1718fd-74ee-4032-851b-db97e893825d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"98a556ee-078b-4e03-93a8-29996133cdcb\"},\"panelIndex\":\"98a556ee-078b-4e03-93a8-29996133cdcb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\":{\"columns\":{\"ce9117a2-773c-474c-8fb1-18940cf58b38\":{\"label\":\"Top values of type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"type\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"a3d10552-e352-40d0-a156-e86112c0501a\":{\"label\":\"Top values of _type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"_type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"9c5db2f3-9eb0-4667-9a74-3318301de251\":{\"label\":\"Sum of bytes\",\"dataType\":\"number\",\"operationType\":\"sum\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"a3d10552-e352-40d0-a156-e86112c0501a\",\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\",\"accessors\":[\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"splitAccessor\":\"a3d10552-e352-40d0-a156-e86112c0501a\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},\"panelIndex\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},{\"version\":\"7.13.1\",\"type\":\"map\",\"gridData\":{\"x\":0,\"y\":120,\"w\":24,\"h\":15,\"i\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\"},\"panelIndex\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.56},\"mapBuffer\":{\"minLon\":-210.32666,\"minLat\":-64.8435,\"maxLon\":210.32666,\"maxLat\":95.13806},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{}},\"panelRefName\":\"panel_dcc0defa-3376-465c-9b5b-2ba69528848c\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_maps_dashboard_logstash","version":1},"coreMigrationVersion":"7.13.5","id":"16d86080-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:panel_2e80716f-c1b6-46f2-be2b-35db744b5031","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","name":"da8843e0-6789-4aae-bcd0-81f270538719:panel_da8843e0-6789-4aae-bcd0-81f270538719","type":"lens"},{"id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","name":"adcd4418-7299-4efa-b369-5f71a7b4ebe0:panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0","type":"lens"},{"id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","name":"869754a7-edf0-478f-a7f1-80374f63108a:panel_869754a7-edf0-478f-a7f1-80374f63108a","type":"lens"},{"id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","name":"67111cf4-338e-453f-8621-e8dea64082d1:panel_67111cf4-338e-453f-8621-e8dea64082d1","type":"lens"},{"id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","name":"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d:panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d","type":"lens"},{"id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","name":"88847944-ae1b-45fd-b102-3b45f9bea04b:panel_88847944-ae1b-45fd-b102-3b45f9bea04b","type":"lens"},{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"5a7924c7-eac0-4573-9199-fecec5b82e9e:panel_5a7924c7-eac0-4573-9199-fecec5b82e9e","type":"lens"},{"id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","name":"f8f49591-f071-4a96-b1ed-cd65daff5648:panel_f8f49591-f071-4a96-b1ed-cd65daff5648","type":"lens"},{"id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","name":"9f357f47-c2a0-421f-a456-9583c40837ab:panel_9f357f47-c2a0-421f-a456-9583c40837ab","type":"lens"},{"id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","name":"6cb383e9-1e80-44f9-80d5-7b8c585668db:panel_6cb383e9-1e80-44f9-80d5-7b8c585668db","type":"lens"},{"id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","name":"57f5f0bf-6610-4599-aad4-37484640b5e2:panel_57f5f0bf-6610-4599-aad4-37484640b5e2","type":"lens"},{"id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","name":"32d3ab66-52e1-44e3-8c1f-1dccff3c5692:panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692","type":"lens"},{"id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","name":"dd1718fd-74ee-4032-851b-db97e893825d:panel_dd1718fd-74ee-4032-851b-db97e893825d","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd","type":"index-pattern"},{"id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","name":"62a0f0b0-3589-4cef-807b-b1b4258b7a9b:panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b","type":"lens"},{"id":"0c5974f0-be5c-11eb-9520-1b4c3ca6a781","name":"dcc0defa-3376-465c-9b5b-2ba69528848c:panel_dcc0defa-3376-465c-9b5b-2ba69528848c","type":"map"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,120],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"WzYyLDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"shakespeare_areachart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"shakespeare_areachart\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"filter\":true},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"stacked\",\"type\":\"histogram\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"data\":{\"id\":\"2\",\"label\":\"Count\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"palette\":{\"type\":\"palette\",\"name\":\"kibana_palette\"},\"isVislibVis\":true,\"detailedTooltip\":true},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"play_name\",\"size\":20,\"order\":\"desc\",\"orderBy\":\"2\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"play_name\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"2\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"185283c0-619e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,122],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzY0LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"by_reference_logstash","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"by_reference_logstash\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{},\"style\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"},\"style\":{}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"lineWidth\":2,\"showCircles\":true}],\"radiusRatio\":0,\"addTooltip\":true,\"detailedTooltip\":true,\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false,\"labels\":{\"show\":false},\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"@timestamp\",\"timeRange\":{\"from\":\"2014-07-15T12:33:21.084Z\",\"to\":\"2019-01-28T03:18:12.440Z\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"response.raw\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"group\"}]}"},"coreMigrationVersion":"7.13.5","id":"1885abb0-ca2b-11eb-bf5e-3de94e83d4f0","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651612828183,981],"type":"visualization","updated_at":"2022-05-03T21:20:28.183Z","version":"WzU1OSwxXQ=="} +{"attributes":{"color":"#f44fcf","description":"","name":"shakespeare"},"coreMigrationVersion":"7.13.5","id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","references":[],"sort":[1651599812857,123],"type":"tag","updated_at":"2022-05-03T17:43:32.857Z","version":"WzY2LDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"3338dd55-4007-4be5-908d-25722b6174cb":{"columnOrder":["6c83b0c2-5834-4619-888c-9e8a08e47d42","b25e7497-c188-4c25-b002-1fd5bd69e76d"],"columns":{"6c83b0c2-5834-4619-888c-9e8a08e47d42":{"dataType":"string","isBucketed":true,"label":"Top values of speaker","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"b25e7497-c188-4c25-b002-1fd5bd69e76d","type":"column"},"orderDirection":"desc","otherBucket":false,"size":90},"scale":"ordinal","sourceField":"speaker"},"b25e7497-c188-4c25-b002-1fd5bd69e76d":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["6c83b0c2-5834-4619-888c-9e8a08e47d42","6c83b0c2-5834-4619-888c-9e8a08e47d42","6c83b0c2-5834-4619-888c-9e8a08e47d42"],"layerId":"3338dd55-4007-4be5-908d-25722b6174cb","legendDisplay":"default","metric":"b25e7497-c188-4c25-b002-1fd5bd69e76d","nestedLegend":false,"numberDisplay":"percent"}],"palette":{"name":"complimentary","type":"palette"},"shape":"treemap"}},"title":"lens_shakespeare_treemap","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.5","id":"31e9f2f0-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-3338dd55-4007-4be5-908d-25722b6174cb","type":"index-pattern"},{"id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","name":"tag-ref-42b4cec0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,127],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"WzY3LDFd"} +{"attributes":{"accessCount":0,"accessDate":1622059178542,"createDate":1622059178542,"url":"/app/dashboards#/view/73398a90-619e-11eb-aebf-c306684b328d?embed=true&_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:%272015-09-20T01:56:56.132Z%27,to:%272015-09-21T11:18:20.471Z%27))&_a=(description:%27%27,filters:!(),fullScreenMode:!f,options:(darkTheme:!f,hidePanelTitles:!f,useMargins:!t),panels:!((embeddableConfig:(enhancements:()),gridData:(h:15,i:%271%27,w:24,x:0,y:0),id:%27185283c0-619e-11eb-aebf-c306684b328d%27,panelIndex:%271%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%272%27,w:24,x:24,y:0),id:%2733736660-619e-11eb-aebf-c306684b328d%27,panelIndex:%272%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%273%27,w:24,x:0,y:15),id:%27622ac7f0-619e-11eb-aebf-c306684b328d%27,panelIndex:%273%27,type:visualization,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%274%27,w:24,x:24,y:15),id:%27712ebbe0-619d-11eb-aebf-c306684b328d%27,panelIndex:%274%27,type:search,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%275%27,w:24,x:0,y:30),id:ddacc820-619d-11eb-aebf-c306684b328d,panelIndex:%275%27,type:search,version:%277.13.1%27),(embeddableConfig:(enhancements:()),gridData:(h:15,i:%276%27,w:24,x:24,y:30),id:f852d570-619d-11eb-aebf-c306684b328d,panelIndex:%276%27,type:search,version:%277.13.1%27)),query:(language:kuery,query:%27%27),tags:!(),timeRestore:!f,title:shakespeare_dashboard,viewMode:view)"},"coreMigrationVersion":"7.13.5","id":"32a03249ec3a048108d4b5a427a37fc8","references":[],"sort":[1651599812857,128],"type":"url","updated_at":"2022-05-03T17:43:32.857Z","version":"WzY4LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"shakespeare_piechart","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"shakespeare_piechart\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false,\"labels\":{\"show\":true,\"values\":true,\"last_level\":true,\"truncate\":100}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"play_name\",\"size\":15,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"33736660-619e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,130],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzY5LDFd"} +{"attributes":{"color":"#7b01cf","description":"","name":"By reference"},"coreMigrationVersion":"7.13.5","id":"39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","references":[],"sort":[1651599812857,131],"type":"tag","updated_at":"2022-05-03T17:43:32.857Z","version":"WzcwLDFd"} +{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"phrase\",\"key\":\"ip\",\"params\":{\"query\":\"57.237.11.219\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match_phrase\":{\"ip\":\"57.237.11.219\"}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"drilldown_saved_search","version":1},"coreMigrationVersion":"7.13.5","id":"4acce030-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1651612879859,1007],"type":"search","updated_at":"2022-05-03T21:21:19.859Z","version":"WzU2NywxXQ=="} +{"attributes":{"description":"","layerListJSON":"[{\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"isAutoSelect\":true},\"id\":\"e0d51731-2bb3-4fed-92af-65f93c3e7e58\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":1,\"visible\":true,\"style\":{\"type\":\"TILE\"},\"type\":\"VECTOR_TILE\"},{\"sourceDescriptor\":{\"geoField\":\"geo.coordinates\",\"filterByMapBounds\":true,\"scalingType\":\"CLUSTERS\",\"topHitsSplitField\":\"\",\"topHitsSize\":1,\"id\":\"142e0a6b-53c9-4f66-a65d-fced755318de\",\"type\":\"ES_SEARCH\",\"applyGlobalQuery\":true,\"applyGlobalTime\":true,\"tooltipProperties\":[],\"sortField\":\"\",\"sortOrder\":\"desc\",\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"id\":\"ca96ce4a-4e73-46a5-bcc8-99a39d227030\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"alpha\":0.75,\"visible\":true,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"marker\"}},\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#CA8EAE\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#934193\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":6}},\"iconOrientation\":{\"type\":\"STATIC\",\"options\":{\"orientation\":0}},\"labelText\":{\"type\":\"STATIC\",\"options\":{\"value\":\"\"}},\"labelColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#000000\"}},\"labelSize\":{\"type\":\"STATIC\",\"options\":{\"size\":14}},\"labelBorderColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"labelBorderSize\":{\"options\":{\"size\":\"SMALL\"}}},\"isTimeAware\":true},\"type\":\"BLENDED_VECTOR\",\"joins\":[]}]","mapStateJSON":"{\"zoom\":1.38,\"center\":{\"lon\":0,\"lat\":19.94277},\"timeFilters\":{\"from\":\"2014-07-15T12:33:21.084Z\",\"to\":\"2019-01-28T03:18:12.440Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":0},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"settings\":{\"autoFitToDataBounds\":false,\"backgroundColor\":\"#ffffff\",\"disableInteractive\":false,\"disableTooltipControl\":false,\"hideToolbarOverlay\":false,\"hideLayerControl\":false,\"hideViewControl\":false,\"initialLocation\":\"LAST_SAVED_LOCATION\",\"fixedLocation\":{\"lat\":0,\"lon\":0,\"zoom\":2},\"browserLocation\":{\"zoom\":2},\"maxZoom\":24,\"minZoom\":0,\"showScaleControl\":false,\"showSpatialFilters\":true,\"spatialFiltersAlpa\":0.3,\"spatialFiltersFillColor\":\"#DA8B45\",\"spatialFiltersLineColor\":\"#DA8B45\"}}","title":"Logstash_map_by_reference","uiStateJSON":"{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}"},"coreMigrationVersion":"7.13.5","id":"a53a2db0-ca2b-11eb-bf5e-3de94e83d4f0","migrationVersion":{"map":"7.12.0"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"layer_1_source_index_pattern","type":"index-pattern"}],"sort":[1651612954243,1037],"type":"map","updated_at":"2022-05-03T21:22:34.243Z","version":"WzYwOSwxXQ=="} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.5\",\"type\":\"search\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"7c29a321-2a9a-412b-9ed1-1d0a1f66ea63\"},\"panelIndex\":\"7c29a321-2a9a-412b-9ed1-1d0a1f66ea63\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7c29a321-2a9a-412b-9ed1-1d0a1f66ea63\"},{\"version\":\"7.13.5\",\"type\":\"search\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"f2d1feb1-d807-46b1-90ac-96d4a9edb6b1\"},\"panelIndex\":\"f2d1feb1-d807-46b1-90ac-96d4a9edb6b1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f2d1feb1-d807-46b1-90ac-96d4a9edb6b1\"},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"a3530107-8b1c-4e94-8f99-e239fa40a09c\"},\"panelIndex\":\"a3530107-8b1c-4e94-8f99-e239fa40a09c\",\"embeddableConfig\":{\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"b14188e0-53d6-433e-874f-b1be7c97487c\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"by_reference_going_to_value\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}},{\"eventId\":\"60cba413-1793-4dd3-b072-9d53655d5522\",\"triggers\":[\"SELECT_RANGE_TRIGGER\"],\"action\":{\"name\":\"Goto_Discover\",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/b3288100-ca2c-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:geo.dest,negate:!f,params:(query:US),type:phrase),query:(match_phrase:(geo.dest:US)))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true},\"factoryId\":\"URL_DRILLDOWN\"}}]}}},\"panelRefName\":\"panel_a3530107-8b1c-4e94-8f99-e239fa40a09c\"},{\"version\":\"7.13.5\",\"type\":\"map\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"77245314-9495-4625-9f53-0946150e26d4\"},\"panelIndex\":\"77245314-9495-4625-9f53-0946150e26d4\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.38},\"mapBuffer\":{\"minLon\":-238.27568,\"minLat\":-74.644155,\"maxLon\":238.27568,\"maxLat\":102.864625},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"9b61b9d4-20a3-4bca-9697-1097c524a943\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"By_reference_to_value\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}},\"panelRefName\":\"panel_77245314-9495-4625-9f53-0946150e26d4\"}]","timeRestore":false,"title":"by_reference_drilldown","version":1},"coreMigrationVersion":"7.13.5","id":"3b844220-ca2b-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"4acce030-ca2a-11eb-bf5e-3de94e83d4f0","name":"7c29a321-2a9a-412b-9ed1-1d0a1f66ea63:panel_7c29a321-2a9a-412b-9ed1-1d0a1f66ea63","type":"search"},{"id":"0abce1c0-ca2a-11eb-bf5e-3de94e83d4f0","name":"f2d1feb1-d807-46b1-90ac-96d4a9edb6b1:panel_f2d1feb1-d807-46b1-90ac-96d4a9edb6b1","type":"search"},{"id":"1885abb0-ca2b-11eb-bf5e-3de94e83d4f0","name":"a3530107-8b1c-4e94-8f99-e239fa40a09c:panel_a3530107-8b1c-4e94-8f99-e239fa40a09c","type":"visualization"},{"id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","name":"a3530107-8b1c-4e94-8f99-e239fa40a09c:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:b14188e0-53d6-433e-874f-b1be7c97487c:dashboardId","type":"dashboard"},{"id":"a53a2db0-ca2b-11eb-bf5e-3de94e83d4f0","name":"77245314-9495-4625-9f53-0946150e26d4:panel_77245314-9495-4625-9f53-0946150e26d4","type":"map"},{"id":"35ce3b30-ca29-11eb-bf5e-3de94e83d4f0","name":"77245314-9495-4625-9f53-0946150e26d4:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:9b61b9d4-20a3-4bca-9697-1097c524a943:dashboardId","type":"dashboard"},{"id":"39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","name":"tag-39d2c190-ca2b-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1651612956152,1046],"type":"dashboard","updated_at":"2022-05-03T21:22:36.152Z","version":"WzYxNSwxXQ=="} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"a7a8f2fb-066e-4023-9755-821e84560b4a":{"columnOrder":["ee46f645-0af0-4b5d-8ed3-2557c98c9c12","91859a54-9b88-4478-8c80-0779fe165fba","62a4dea1-fab9-45ff-93e0-b99cfff719d5"],"columns":{"62a4dea1-fab9-45ff-93e0-b99cfff719d5":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"},"91859a54-9b88-4478-8c80-0779fe165fba":{"dataType":"string","isBucketed":true,"label":"Top values of play_name","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"62a4dea1-fab9-45ff-93e0-b99cfff719d5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"play_name"},"ee46f645-0af0-4b5d-8ed3-2557c98c9c12":{"dataType":"string","isBucketed":true,"label":"Top values of speaker","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"62a4dea1-fab9-45ff-93e0-b99cfff719d5","type":"column"},"orderDirection":"desc","otherBucket":true,"size":25},"scale":"ordinal","sourceField":"speaker"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"kuery","query":""},"visualization":{"layers":[{"categoryDisplay":"default","groups":["ee46f645-0af0-4b5d-8ed3-2557c98c9c12","ee46f645-0af0-4b5d-8ed3-2557c98c9c12","ee46f645-0af0-4b5d-8ed3-2557c98c9c12","ee46f645-0af0-4b5d-8ed3-2557c98c9c12","91859a54-9b88-4478-8c80-0779fe165fba"],"layerId":"a7a8f2fb-066e-4023-9755-821e84560b4a","legendDisplay":"default","metric":"62a4dea1-fab9-45ff-93e0-b99cfff719d5","nestedLegend":false,"numberDisplay":"percent"}],"palette":{"name":"kibana_palette","type":"palette"},"shape":"pie"}},"title":"lens_shakespeare_piechart","visualizationType":"lnsPie"},"coreMigrationVersion":"7.13.5","id":"b5bd5050-be31-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-a7a8f2fb-066e-4023-9755-821e84560b4a","type":"index-pattern"},{"id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","name":"tag-ref-42b4cec0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,135],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzc1LDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"c4b1daae-a3af-4136-969e-8485d4ba53f9\"},\"panelIndex\":\"c4b1daae-a3af-4136-969e-8485d4ba53f9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_c4b1daae-a3af-4136-969e-8485d4ba53f9\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"f092b002-182e-49b8-bcc4-58f5233e041b\"},\"panelIndex\":\"f092b002-182e-49b8-bcc4-58f5233e041b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f092b002-182e-49b8-bcc4-58f5233e041b\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_shakespeare_dashboard","version":1},"coreMigrationVersion":"7.13.5","id":"43fae350-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"b5bd5050-be31-11eb-9520-1b4c3ca6a781","name":"c4b1daae-a3af-4136-969e-8485d4ba53f9:panel_c4b1daae-a3af-4136-969e-8485d4ba53f9","type":"lens"},{"id":"31e9f2f0-be32-11eb-9520-1b4c3ca6a781","name":"f092b002-182e-49b8-bcc4-58f5233e041b:panel_f092b002-182e-49b8-bcc4-58f5233e041b","type":"lens"},{"id":"42b4cec0-be32-11eb-9520-1b4c3ca6a781","name":"tag-42b4cec0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,139],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzc2LDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"7\",\"w\":24,\"x\":0,\"y\":45},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"8\",\"w\":24,\"x\":24,\"y\":45},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"9\",\"w\":24,\"x\":0,\"y\":60},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"10\",\"w\":24,\"x\":24,\"y\":60},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"11\",\"w\":24,\"x\":0,\"y\":75},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"12\",\"w\":24,\"x\":24,\"y\":75},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"13\",\"w\":24,\"x\":0,\"y\":90},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"14\",\"w\":24,\"x\":24,\"y\":90},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"15\",\"w\":24,\"x\":0,\"y\":105},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"16\",\"w\":24,\"x\":24,\"y\":105},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"17\",\"w\":24,\"x\":0,\"y\":120},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"18\",\"w\":24,\"x\":24,\"y\":120},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"19\",\"w\":24,\"x\":0,\"y\":135},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"20\",\"w\":24,\"x\":24,\"y\":135},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"}]","timeRestore":false,"title":"logstash_dashboard_withouttime","version":1},"coreMigrationVersion":"7.13.5","id":"5d3410c0-6249-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"36b91810-6239-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"0a274320-61cc-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"e4aef350-623d-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"f92e5630-623e-11eb-aebf-c306684b328d","name":"4:panel_4","type":"visualization"},{"id":"9853d4d0-623d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"visualization"},{"id":"6ecb33b0-623d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"visualization"},{"id":"b8e35c80-623c-11eb-aebf-c306684b328d","name":"7:panel_7","type":"visualization"},{"id":"f1bc75d0-6239-11eb-aebf-c306684b328d","name":"8:panel_8","type":"visualization"},{"id":"0d8a8860-623a-11eb-aebf-c306684b328d","name":"9:panel_9","type":"visualization"},{"id":"d79fe3d0-6239-11eb-aebf-c306684b328d","name":"10:panel_10","type":"visualization"},{"id":"318375a0-6240-11eb-aebf-c306684b328d","name":"11:panel_11","type":"visualization"},{"id":"e461eb20-6245-11eb-aebf-c306684b328d","name":"12:panel_12","type":"visualization"},{"id":"25bdc750-6242-11eb-aebf-c306684b328d","name":"13:panel_13","type":"visualization"},{"id":"71dd7bc0-6248-11eb-aebf-c306684b328d","name":"14:panel_14","type":"visualization"},{"id":"6aea48a0-6240-11eb-aebf-c306684b328d","name":"15:panel_15","type":"visualization"},{"id":"32b681f0-6241-11eb-aebf-c306684b328d","name":"16:panel_16","type":"visualization"},{"id":"ccca99e0-6244-11eb-aebf-c306684b328d","name":"17:panel_17","type":"visualization"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"18:panel_18","type":"visualization"},{"id":"c94d8440-6248-11eb-aebf-c306684b328d","name":"19:panel_19","type":"visualization"},{"id":"db6226f0-61c0-11eb-aebf-c306684b328d","name":"20:panel_20","type":"search"}],"sort":[1651599812857,160],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzc3LDFd"} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"shakespeare_tag_cloud","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"shakespeare_tag_cloud\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"multiple\",\"minFontSize\":59,\"maxFontSize\":100,\"showLabel\":true},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"type.keyword\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"}}]}"},"coreMigrationVersion":"7.13.5","id":"622ac7f0-619e-11eb-aebf-c306684b328d","migrationVersion":{"visualization":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,162],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzc4LDFd"} +{"attributes":{"numLinks":4,"numVertices":5,"title":"logstash_graph","version":1,"wsState":"\"{\\\"selectedFields\\\":[{\\\"name\\\":\\\"machine.os.raw\\\",\\\"hopSize\\\":5,\\\"lastValidHopSize\\\":5,\\\"color\\\":\\\"#B9A888\\\",\\\"selected\\\":true,\\\"iconClass\\\":\\\"fa-folder-open-o\\\"},{\\\"name\\\":\\\"response.raw\\\",\\\"hopSize\\\":5,\\\"lastValidHopSize\\\":5,\\\"color\\\":\\\"#D6BF57\\\",\\\"selected\\\":true,\\\"iconClass\\\":\\\"fa-folder-open-o\\\"}],\\\"blocklist\\\":[],\\\"vertices\\\":[{\\\"x\\\":461.96184642905024,\\\"y\\\":284.02313214227325,\\\"label\\\":\\\"osx\\\",\\\"color\\\":\\\"#B9A888\\\",\\\"field\\\":\\\"machine.os.raw\\\",\\\"term\\\":\\\"osx\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":383.946159835112,\\\"y\\\":375.6063135315976,\\\"label\\\":\\\"503\\\",\\\"color\\\":\\\"#D6BF57\\\",\\\"field\\\":\\\"response.raw\\\",\\\"term\\\":\\\"503\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":287.104700756828,\\\"y\\\":324.1245253249895,\\\"label\\\":\\\"win 7\\\",\\\"color\\\":\\\"#B9A888\\\",\\\"field\\\":\\\"machine.os.raw\\\",\\\"term\\\":\\\"win 7\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":487.9986107998273,\\\"y\\\":407.07546535764254,\\\"label\\\":\\\"ios\\\",\\\"color\\\":\\\"#B9A888\\\",\\\"field\\\":\\\"machine.os.raw\\\",\\\"term\\\":\\\"ios\\\",\\\"parent\\\":null,\\\"size\\\":15},{\\\"x\\\":302.35059551806023,\\\"y\\\":211.66825720913607,\\\"label\\\":\\\"200\\\",\\\"color\\\":\\\"#D6BF57\\\",\\\"field\\\":\\\"response.raw\\\",\\\"term\\\":\\\"200\\\",\\\"parent\\\":null,\\\"size\\\":15}],\\\"links\\\":[{\\\"weight\\\":0.000881324009872165,\\\"width\\\":7.983523640193488,\\\"source\\\":4,\\\"target\\\":2},{\\\"weight\\\":0.000023386835221992895,\\\"width\\\":2,\\\"source\\\":1,\\\"target\\\":0},{\\\"weight\\\":0.0011039286029480653,\\\"width\\\":2,\\\"source\\\":1,\\\"target\\\":2},{\\\"weight\\\":0.000045596928960694605,\\\"width\\\":2,\\\"source\\\":1,\\\"target\\\":3}],\\\"urlTemplates\\\":[{\\\"url\\\":\\\"/app/discover#/?_a=(columns%3A!(_source)%2Cindex%3A%2756b34100-619d-11eb-aebf-c306684b328d%27%2Cinterval%3Aauto%2Cquery%3A(language%3Akuery%2Cquery%3A{{gquery}})%2Csort%3A!(_score%2Cdesc))\\\",\\\"description\\\":\\\"Machine OS win 7\\\",\\\"isDefault\\\":false,\\\"encoderID\\\":\\\"kql\\\",\\\"iconClass\\\":\\\"fa-share-alt\\\"}],\\\"exploreControls\\\":{\\\"useSignificance\\\":true,\\\"sampleSize\\\":2000,\\\"timeoutMillis\\\":5000,\\\"maxValuesPerDoc\\\":1,\\\"minDocCount\\\":3},\\\"indexPatternRefName\\\":\\\"indexPattern_0\\\"}\""},"coreMigrationVersion":"7.13.5","id":"6afc4b40-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"graph-workspace":"7.11.0"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexPattern_0","type":"index-pattern"}],"sort":[1651599812857,164],"type":"graph-workspace","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzc5LDFd"} +{"attributes":{"buildNum":39457,"defaultIndex":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0"},"coreMigrationVersion":"7.13.5","id":"7.12.1","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1651599812857,165],"type":"config","updated_at":"2022-05-03T17:43:32.857Z","version":"WzgwLDFd"} +{"attributes":{"accessibility:disableAnimations":true,"buildNum":null,"dateFormat:tz":"UTC","defaultIndex":"56b34100-619d-11eb-aebf-c306684b328d","visualization:visualize:legacyChartsLibrary":true},"coreMigrationVersion":"7.13.5","id":"7.13.1","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1651599812857,166],"type":"config","updated_at":"2022-05-03T17:43:32.857Z","version":"WzgxLDFd"} +{"attributes":{"buildNum":40943,"defaultIndex":"43fcac20-ca27-11eb-bf5e-3de94e83d4f0"},"coreMigrationVersion":"7.13.5","id":"7.13.2","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1651599812857,167],"type":"config","updated_at":"2022-05-03T17:43:32.857Z","version":"WzgyLDFd"} +{"attributes":{"buildNum":9007199254740991,"defaultIndex":"56b34100-619d-11eb-aebf-c306684b328d"},"coreMigrationVersion":"7.13.5","id":"7.13.5","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1651613092912,1086],"type":"config","updated_at":"2022-05-03T21:24:52.912Z","version":"WzYzOCwxXQ=="} +{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[{\"meta\":{\"negate\":false,\"type\":\"phrase\",\"key\":\"text_entry\",\"value\":\"Christendom.\",\"params\":{\"query\":\"Christendom.\",\"type\":\"phrase\"},\"disabled\":false,\"alias\":null,\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"text_entry\":{\"query\":\"Christendom.\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["_score","desc"]],"title":"shakespeare_saved_search","version":1},"coreMigrationVersion":"7.13.5","id":"712ebbe0-619d-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1651599812857,170],"type":"search","updated_at":"2022-05-03T17:43:32.857Z","version":"WzgzLDFd"} +{"attributes":{"columns":["play_name","speaker"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"speaker:\\\"GLOUCESTER\\\"\",\"language\":\"lucene\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["_score","desc"]],"title":"shakespeare_saved_lucene_search","version":1},"coreMigrationVersion":"7.13.5","id":"ddacc820-619d-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,172],"type":"search","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzg0LDFd"} +{"attributes":{"columns":["_source"],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"text_entry :\\\"MORDAKE THE EARL OF FIFE, AND ELDEST SON\\\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["_score","desc"]],"title":"shakespeare_saved_kql_search","version":1},"coreMigrationVersion":"7.13.5","id":"f852d570-619d-11eb-aebf-c306684b328d","migrationVersion":{"search":"7.9.3"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651599812857,174],"type":"search","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzg1LDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"}]","timeRestore":false,"title":"shakespeare_dashboard","version":1},"coreMigrationVersion":"7.13.5","id":"73398a90-619e-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"185283c0-619e-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"33736660-619e-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"622ac7f0-619e-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"712ebbe0-619d-11eb-aebf-c306684b328d","name":"4:panel_4","type":"search"},{"id":"ddacc820-619d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"search"},{"id":"f852d570-619d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"search"}],"sort":[1651599812857,181],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzg2LDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[{\"meta\":{\"negate\":false,\"disabled\":false,\"alias\":null,\"type\":\"phrase\",\"key\":\"geo.srcdest\",\"value\":\"IN:US\",\"params\":{\"query\":\"IN:US\",\"type\":\"phrase\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match\":{\"geo.srcdest\":{\"query\":\"IN:US\",\"type\":\"phrase\"}}},\"$state\":{\"store\":\"appState\"}}]}"},"optionsJSON":"{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"1\",\"w\":24,\"x\":0,\"y\":0},\"panelIndex\":\"1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_1\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"2\",\"w\":24,\"x\":24,\"y\":0},\"panelIndex\":\"2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_2\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"3\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"3\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_3\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"4\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"4\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"5\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"5\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"6\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"6\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"7\",\"w\":24,\"x\":0,\"y\":45},\"panelIndex\":\"7\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_7\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"8\",\"w\":24,\"x\":24,\"y\":45},\"panelIndex\":\"8\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_8\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"9\",\"w\":24,\"x\":0,\"y\":60},\"panelIndex\":\"9\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"10\",\"w\":24,\"x\":24,\"y\":60},\"panelIndex\":\"10\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_10\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"11\",\"w\":24,\"x\":0,\"y\":75},\"panelIndex\":\"11\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_11\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"12\",\"w\":24,\"x\":24,\"y\":75},\"panelIndex\":\"12\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_12\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"13\",\"w\":24,\"x\":0,\"y\":90},\"panelIndex\":\"13\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"14\",\"w\":24,\"x\":24,\"y\":90},\"panelIndex\":\"14\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_14\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"15\",\"w\":24,\"x\":0,\"y\":105},\"panelIndex\":\"15\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_15\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"16\",\"w\":24,\"x\":24,\"y\":105},\"panelIndex\":\"16\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_16\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"17\",\"w\":24,\"x\":0,\"y\":120},\"panelIndex\":\"17\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_17\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"18\",\"w\":24,\"x\":24,\"y\":120},\"panelIndex\":\"18\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_18\"},{\"version\":\"7.3.0\",\"type\":\"visualization\",\"gridData\":{\"h\":15,\"i\":\"19\",\"w\":24,\"x\":0,\"y\":135},\"panelIndex\":\"19\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_19\"},{\"version\":\"7.3.0\",\"type\":\"search\",\"gridData\":{\"h\":15,\"i\":\"20\",\"w\":24,\"x\":24,\"y\":135},\"panelIndex\":\"20\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_20\"}]","timeRestore":false,"title":"logstash_dashboardwithfilters","version":1},"coreMigrationVersion":"7.13.5","id":"79794f20-6249-11eb-aebf-c306684b328d","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"},{"id":"36b91810-6239-11eb-aebf-c306684b328d","name":"1:panel_1","type":"visualization"},{"id":"0a274320-61cc-11eb-aebf-c306684b328d","name":"2:panel_2","type":"visualization"},{"id":"e4aef350-623d-11eb-aebf-c306684b328d","name":"3:panel_3","type":"visualization"},{"id":"f92e5630-623e-11eb-aebf-c306684b328d","name":"4:panel_4","type":"visualization"},{"id":"9853d4d0-623d-11eb-aebf-c306684b328d","name":"5:panel_5","type":"visualization"},{"id":"6ecb33b0-623d-11eb-aebf-c306684b328d","name":"6:panel_6","type":"visualization"},{"id":"b8e35c80-623c-11eb-aebf-c306684b328d","name":"7:panel_7","type":"visualization"},{"id":"f1bc75d0-6239-11eb-aebf-c306684b328d","name":"8:panel_8","type":"visualization"},{"id":"0d8a8860-623a-11eb-aebf-c306684b328d","name":"9:panel_9","type":"visualization"},{"id":"d79fe3d0-6239-11eb-aebf-c306684b328d","name":"10:panel_10","type":"visualization"},{"id":"318375a0-6240-11eb-aebf-c306684b328d","name":"11:panel_11","type":"visualization"},{"id":"e461eb20-6245-11eb-aebf-c306684b328d","name":"12:panel_12","type":"visualization"},{"id":"25bdc750-6242-11eb-aebf-c306684b328d","name":"13:panel_13","type":"visualization"},{"id":"71dd7bc0-6248-11eb-aebf-c306684b328d","name":"14:panel_14","type":"visualization"},{"id":"6aea48a0-6240-11eb-aebf-c306684b328d","name":"15:panel_15","type":"visualization"},{"id":"32b681f0-6241-11eb-aebf-c306684b328d","name":"16:panel_16","type":"visualization"},{"id":"ccca99e0-6244-11eb-aebf-c306684b328d","name":"17:panel_17","type":"visualization"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"18:panel_18","type":"visualization"},{"id":"c94d8440-6248-11eb-aebf-c306684b328d","name":"19:panel_19","type":"visualization"},{"id":"db6226f0-61c0-11eb-aebf-c306684b328d","name":"20:panel_20","type":"search"}],"sort":[1651599812857,203],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzg3LDFd"} +{"attributes":{"description":"","state":{"datasourceStates":{"indexpattern":{"layers":{"037b7937-790b-4d2d-94a5-7f5837a6ef05":{"columnOrder":["b3d46616-75e0-419e-97ea-91148961ef94","025a0fb3-dc44-4f5c-b517-2d71d3f26f14","c476db14-0cc1-40ec-863e-d2779256a407"],"columns":{"025a0fb3-dc44-4f5c-b517-2d71d3f26f14":{"dataType":"date","isBucketed":true,"label":"@timestamp","operationType":"date_histogram","params":{"interval":"auto"},"scale":"interval","sourceField":"@timestamp"},"b3d46616-75e0-419e-97ea-91148961ef94":{"dataType":"string","isBucketed":true,"label":"Top values of geo.srcdest","operationType":"terms","params":{"missingBucket":false,"orderBy":{"columnId":"c476db14-0cc1-40ec-863e-d2779256a407","type":"column"},"orderDirection":"desc","otherBucket":true,"size":3},"scale":"ordinal","sourceField":"geo.srcdest"},"c476db14-0cc1-40ec-863e-d2779256a407":{"dataType":"number","isBucketed":false,"label":"Count of records","operationType":"count","scale":"ratio","sourceField":"Records"}},"incompleteColumns":{}}}}},"filters":[],"query":{"language":"lucene","query":""},"visualization":{"axisTitlesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"fittingFunction":"None","gridlinesVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"layers":[{"accessors":["c476db14-0cc1-40ec-863e-d2779256a407"],"layerId":"037b7937-790b-4d2d-94a5-7f5837a6ef05","position":"top","seriesType":"bar_stacked","showGridlines":false,"splitAccessor":"b3d46616-75e0-419e-97ea-91148961ef94","xAccessor":"025a0fb3-dc44-4f5c-b517-2d71d3f26f14"}],"legend":{"isVisible":true,"position":"right"},"preferredSeriesType":"bar_stacked","tickLabelsVisibilitySettings":{"x":true,"yLeft":true,"yRight":true},"valueLabels":"hide"}},"title":"lens_verticalstacked","visualizationType":"lnsXY"},"coreMigrationVersion":"7.13.5","id":"8dc19b50-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"lens":"7.13.1"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"indexpattern-datasource-layer-037b7937-790b-4d2d-94a5-7f5837a6ef05","type":"index-pattern"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-ref-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,207],"type":"lens","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzg4LDFd"} +{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[{\"meta\":{\"alias\":null,\"negate\":false,\"disabled\":false,\"type\":\"phrase\",\"key\":\"geo.dest\",\"params\":{\"query\":\"US\"},\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index\"},\"query\":{\"match_phrase\":{\"geo.dest\":\"US\"}},\"$state\":{\"store\":\"appState\"}}],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[["@timestamp","desc"]],"title":"drilldown_logstash","version":1},"coreMigrationVersion":"7.13.5","id":"b3288100-ca2c-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index","type":"index-pattern"}],"sort":[1651612907652,1002],"type":"search","updated_at":"2022-05-03T21:21:47.652Z","version":"WzU3NiwxXQ=="} +{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{}"},"title":"logstash_timelion_panel","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"logstash_timelion_panel\",\"type\":\"timelion\",\"aggs\":[],\"params\":{\"expression\":\".es(index=logstash-*, \\\"sum:bytes\\\")\",\"interval\":\"auto\"}}"},"coreMigrationVersion":"7.13.5","id":"b3a44cd0-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"visualization":"7.13.1"},"references":[],"sort":[1651599812857,208],"type":"visualization","updated_at":"2022-05-03T17:43:32.857Z","version":"WzkwLDFd"} +{"attributes":{"color":"#9170B8","description":"","name":"alltogether"},"coreMigrationVersion":"7.13.5","id":"be808cb0-be32-11eb-9520-1b4c3ca6a781","references":[],"sort":[1651599812857,209],"type":"tag","updated_at":"2022-05-03T17:43:32.857Z","version":"WzkxLDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"4d9e9a01-cdb8-4aef-afcb-50db52247bb1\"},\"panelIndex\":\"4d9e9a01-cdb8-4aef-afcb-50db52247bb1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_4d9e9a01-cdb8-4aef-afcb-50db52247bb1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"d9cab9c8-667e-4d34-821b-cbb070891956\"},\"panelIndex\":\"d9cab9c8-667e-4d34-821b-cbb070891956\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_d9cab9c8-667e-4d34-821b-cbb070891956\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_combined_dashboard","version":1},"coreMigrationVersion":"7.13.5","id":"bfb3dc90-be32-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"8dc19b50-be32-11eb-9520-1b4c3ca6a781","name":"4d9e9a01-cdb8-4aef-afcb-50db52247bb1:panel_4d9e9a01-cdb8-4aef-afcb-50db52247bb1","type":"lens"},{"id":"b5bd5050-be31-11eb-9520-1b4c3ca6a781","name":"d9cab9c8-667e-4d34-821b-cbb070891956:panel_d9cab9c8-667e-4d34-821b-cbb070891956","type":"lens"},{"id":"be808cb0-be32-11eb-9520-1b4c3ca6a781","name":"tag-be808cb0-be32-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,213],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"WzkyLDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\"},\"panelIndex\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"26e2cf99-d931-4320-9e15-9dbc148f3534\":{\"columns\":{\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\":{\"label\":\"Top values of url.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"url.raw\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"beb72af1-239c-46d8-823b-b00d1e2ace43\":{\"label\":\"Unique count of geo.srcdest\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":false}},\"columnOrder\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"beb72af1-239c-46d8-823b-b00d1e2ace43\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"26e2cf99-d931-4320-9e15-9dbc148f3534\",\"groups\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\"],\"metric\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534\"}]},\"enhancements\":{},\"type\":\"lens\"},\"panelRefName\":\"panel_2e80716f-c1b6-46f2-be2b-35db744b5031\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"da8843e0-6789-4aae-bcd0-81f270538719\"},\"panelIndex\":\"da8843e0-6789-4aae-bcd0-81f270538719\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_da8843e0-6789-4aae-bcd0-81f270538719\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},\"panelIndex\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"869754a7-edf0-478f-a7f1-80374f63108a\"},\"panelIndex\":\"869754a7-edf0-478f-a7f1-80374f63108a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_869754a7-edf0-478f-a7f1-80374f63108a\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"67111cf4-338e-453f-8621-e8dea64082d1\"},\"panelIndex\":\"67111cf4-338e-453f-8621-e8dea64082d1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_67111cf4-338e-453f-8621-e8dea64082d1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},\"panelIndex\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\"},\"panelIndex\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_88847944-ae1b-45fd-b102-3b45f9bea04b\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\"},\"panelIndex\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5a7924c7-eac0-4573-9199-fecec5b82e9e\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\"},\"panelIndex\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f8f49591-f071-4a96-b1ed-cd65daff5648\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9f357f47-c2a0-421f-a456-9583c40837ab\"},\"panelIndex\":\"9f357f47-c2a0-421f-a456-9583c40837ab\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9f357f47-c2a0-421f-a456-9583c40837ab\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\"},\"panelIndex\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cb383e9-1e80-44f9-80d5-7b8c585668db\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\"},\"panelIndex\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_57f5f0bf-6610-4599-aad4-37484640b5e2\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},\"panelIndex\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"dd1718fd-74ee-4032-851b-db97e893825d\"},\"panelIndex\":\"dd1718fd-74ee-4032-851b-db97e893825d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd1718fd-74ee-4032-851b-db97e893825d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"98a556ee-078b-4e03-93a8-29996133cdcb\"},\"panelIndex\":\"98a556ee-078b-4e03-93a8-29996133cdcb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\":{\"columns\":{\"ce9117a2-773c-474c-8fb1-18940cf58b38\":{\"label\":\"Top values of type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"type\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"a3d10552-e352-40d0-a156-e86112c0501a\":{\"label\":\"Top values of _type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"_type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"9c5db2f3-9eb0-4667-9a74-3318301de251\":{\"label\":\"Sum of bytes\",\"dataType\":\"number\",\"operationType\":\"sum\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"a3d10552-e352-40d0-a156-e86112c0501a\",\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\",\"accessors\":[\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"splitAccessor\":\"a3d10552-e352-40d0-a156-e86112c0501a\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},\"panelIndex\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},{\"version\":\"7.13.1\",\"type\":\"map\",\"gridData\":{\"x\":0,\"y\":120,\"w\":24,\"h\":15,\"i\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\"},\"panelIndex\":\"dcc0defa-3376-465c-9b5b-2ba69528848c\",\"embeddableConfig\":{\"mapCenter\":{\"lat\":19.94277,\"lon\":0,\"zoom\":1.56},\"mapBuffer\":{\"minLon\":-210.32666,\"minLat\":-64.8435,\"maxLon\":210.32666,\"maxLat\":95.13806},\"isLayerTOCOpen\":true,\"openTOCDetails\":[],\"hiddenLayers\":[],\"enhancements\":{}},\"panelRefName\":\"panel_dcc0defa-3376-465c-9b5b-2ba69528848c\"},{\"version\":\"7.13.1\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":120,\"w\":24,\"h\":15,\"i\":\"dd21a674-ae3a-40f6-9d68-4e01361ea5e2\"},\"panelIndex\":\"dd21a674-ae3a-40f6-9d68-4e01361ea5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd21a674-ae3a-40f6-9d68-4e01361ea5e2\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"timelion_lens_maps_dashboard_logstash","version":1},"coreMigrationVersion":"7.13.5","id":"c4ab2030-be5c-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:panel_2e80716f-c1b6-46f2-be2b-35db744b5031","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","name":"da8843e0-6789-4aae-bcd0-81f270538719:panel_da8843e0-6789-4aae-bcd0-81f270538719","type":"lens"},{"id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","name":"adcd4418-7299-4efa-b369-5f71a7b4ebe0:panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0","type":"lens"},{"id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","name":"869754a7-edf0-478f-a7f1-80374f63108a:panel_869754a7-edf0-478f-a7f1-80374f63108a","type":"lens"},{"id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","name":"67111cf4-338e-453f-8621-e8dea64082d1:panel_67111cf4-338e-453f-8621-e8dea64082d1","type":"lens"},{"id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","name":"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d:panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d","type":"lens"},{"id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","name":"88847944-ae1b-45fd-b102-3b45f9bea04b:panel_88847944-ae1b-45fd-b102-3b45f9bea04b","type":"lens"},{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"5a7924c7-eac0-4573-9199-fecec5b82e9e:panel_5a7924c7-eac0-4573-9199-fecec5b82e9e","type":"lens"},{"id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","name":"f8f49591-f071-4a96-b1ed-cd65daff5648:panel_f8f49591-f071-4a96-b1ed-cd65daff5648","type":"lens"},{"id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","name":"9f357f47-c2a0-421f-a456-9583c40837ab:panel_9f357f47-c2a0-421f-a456-9583c40837ab","type":"lens"},{"id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","name":"6cb383e9-1e80-44f9-80d5-7b8c585668db:panel_6cb383e9-1e80-44f9-80d5-7b8c585668db","type":"lens"},{"id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","name":"57f5f0bf-6610-4599-aad4-37484640b5e2:panel_57f5f0bf-6610-4599-aad4-37484640b5e2","type":"lens"},{"id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","name":"32d3ab66-52e1-44e3-8c1f-1dccff3c5692:panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692","type":"lens"},{"id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","name":"dd1718fd-74ee-4032-851b-db97e893825d:panel_dd1718fd-74ee-4032-851b-db97e893825d","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd","type":"index-pattern"},{"id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","name":"62a0f0b0-3589-4cef-807b-b1b4258b7a9b:panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b","type":"lens"},{"id":"0c5974f0-be5c-11eb-9520-1b4c3ca6a781","name":"dcc0defa-3376-465c-9b5b-2ba69528848c:panel_dcc0defa-3376-465c-9b5b-2ba69528848c","type":"map"},{"id":"a4d7be80-6245-11eb-aebf-c306684b328d","name":"dd21a674-ae3a-40f6-9d68-4e01361ea5e2:panel_dd21a674-ae3a-40f6-9d68-4e01361ea5e2","type":"visualization"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,236],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"WzkzLDFd"} +{"attributes":{"columns":[],"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"speaker :\\\"DUKE VINCENTIO\\\" \",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"sort":[],"title":"drilldown_shakes","version":1},"coreMigrationVersion":"7.13.5","id":"c4b9cc00-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"search":"7.9.3"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"sort":[1651611630398,283],"type":"search","updated_at":"2022-05-03T21:00:30.398Z","version":"WzE1MCwxXQ=="} +{"attributes":{"@created":"2021-05-27T19:45:29.712Z","@timestamp":"2021-05-27T19:45:29.712Z","content":"{\"selectedNodes\":[{\"id\":\"element-56d2ba72-f227-4d04-9478-a1d6f0c7e601\",\"position\":{\"left\":20,\"top\":20,\"width\":500,\"height\":300,\"angle\":0,\"parent\":\"group-499b5982-25f4-4894-9540-1874a27d78e7\",\"type\":\"element\"},\"expression\":\"savedLens id=\\\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\\\" timerange={timerange from=\\\"now-15y\\\" to=\\\"now\\\"}\\n| render\",\"filter\":null,\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"savedLens\",\"arguments\":{\"id\":[\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\"],\"timerange\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"timerange\",\"arguments\":{\"from\":[\"now-15y\"],\"to\":[\"now\"]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-afbaa26e-10e7-47d4-bb41-b061dfdced2b\",\"position\":{\"left\":527,\"top\":20,\"width\":500,\"height\":300,\"angle\":0,\"parent\":\"group-499b5982-25f4-4894-9540-1874a27d78e7\",\"type\":\"element\"},\"expression\":\"savedVisualization id=\\\"0d8a8860-623a-11eb-aebf-c306684b328d\\\" timerange={timerange from=\\\"now-15y\\\" to=\\\"now\\\"}\\n| render\",\"filter\":null,\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"savedVisualization\",\"arguments\":{\"id\":[\"0d8a8860-623a-11eb-aebf-c306684b328d\"],\"timerange\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"timerange\",\"arguments\":{\"from\":[\"now-15y\"],\"to\":[\"now\"]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}","displayName":"element_canvas","help":"","image":"","name":"elementCanvas"},"coreMigrationVersion":"7.13.5","id":"custom-element-3bc52277-ee01-4cdc-8d2d-f2db6ade1512","references":[],"sort":[1651599812857,237],"type":"canvas-element","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzk1LDFd"} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.5\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"ced0a5ea-3ec2-4274-8431-6e76d85637f6\"},\"panelIndex\":\"ced0a5ea-3ec2-4274-8431-6e76d85637f6\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3\":{\"columns\":{\"f70668f8-ae97-4b64-867f-b0c9b77914ef\":{\"label\":\"Top values of speaker\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"speaker\",\"isBucketed\":true,\"params\":{\"size\":39,\"orderBy\":{\"type\":\"column\",\"columnId\":\"fbf256d9-cae7-4244-8504-b73a5666e917\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"fbf256d9-cae7-4244-8504-b73a5666e917\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"}},\"columnOrder\":[\"f70668f8-ae97-4b64-867f-b0c9b77914ef\",\"fbf256d9-cae7-4244-8504-b73a5666e917\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_horizontal_percentage_stacked\",\"layers\":[{\"layerId\":\"6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3\",\"accessors\":[\"fbf256d9-cae7-4244-8504-b73a5666e917\"],\"position\":\"top\",\"seriesType\":\"bar_horizontal_percentage_stacked\",\"showGridlines\":false,\"splitAccessor\":\"f70668f8-ae97-4b64-867f-b0c9b77914ef\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"4e937b20-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"4e937b20-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3\"}]},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"2b9a2bad-d6aa-4d3b-a692-fd96c3fb0ac1\",\"triggers\":[\"FILTER_TRIGGER\"],\"action\":{\"name\":\"We_like_lens\",\"config\":{\"useCurrentFilters\":true,\"useCurrentDateRange\":true},\"factoryId\":\"DASHBOARD_TO_DASHBOARD_DRILLDOWN\"}}]}}}},{\"version\":\"7.13.5\",\"type\":\"visualization\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"e51c2a40-5849-47c9-9ae2-a6373d68154b\"},\"panelIndex\":\"e51c2a40-5849-47c9-9ae2-a6373d68154b\",\"embeddableConfig\":{\"savedVis\":{\"title\":\"\",\"description\":\"\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100}},\"uiState\":{},\"data\":{\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"play_name\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":788,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\"},\"schema\":\"segment\"}],\"searchSource\":{\"index\":\"4e937b20-619d-11eb-aebf-c306684b328d\",\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}}},\"enhancements\":{\"dynamicActions\":{\"events\":[{\"eventId\":\"3775f69f-ad03-476d-bbf8-99ab9628a55d\",\"triggers\":[\"VALUE_CLICK_TRIGGER\"],\"action\":{\"factoryId\":\"URL_DRILLDOWN\",\"name\":\"drilldown_timebased \",\"config\":{\"url\":{\"template\":\"http://localhost:5601/app/discover#/view/b3288100-ca2c-11eb-bf5e-3de94e83d4f0?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-15y,to:now))&_a=(columns:!(),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',key:geo.dest,negate:!f,params:(query:US),type:phrase),query:(match_phrase:(geo.dest:US)))),index:'43fcac20-ca27-11eb-bf5e-3de94e83d4f0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))\"},\"openInNewTab\":true,\"encodeUrl\":true}}}]}}}}]","timeRestore":false,"title":"nontimebased_shakespeare_drilldown","version":1},"coreMigrationVersion":"7.13.5","id":"e9eb20f0-ca2a-11eb-bf5e-3de94e83d4f0","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"ced0a5ea-3ec2-4274-8431-6e76d85637f6:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"ced0a5ea-3ec2-4274-8431-6e76d85637f6:indexpattern-datasource-layer-6a3b206a-4ac3-4d67-b2b9-c6b543a11ea3","type":"index-pattern"},{"id":"08dec860-ca29-11eb-bf5e-3de94e83d4f0","name":"ced0a5ea-3ec2-4274-8431-6e76d85637f6:drilldown:DASHBOARD_TO_DASHBOARD_DRILLDOWN:2b9a2bad-d6aa-4d3b-a692-fd96c3fb0ac1:dashboardId","type":"dashboard"},{"id":"4e937b20-619d-11eb-aebf-c306684b328d","name":"e51c2a40-5849-47c9-9ae2-a6373d68154b:kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"07f48f70-ca29-11eb-bf5e-3de94e83d4f0","name":"tag-07f48f70-ca29-11eb-bf5e-3de94e83d4f0","type":"tag"}],"sort":[1651612119207,862],"type":"dashboard","updated_at":"2022-05-03T21:08:39.207Z","version":"WzQ1MywxXQ=="} +{"attributes":{"description":"","hits":0,"kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"},"optionsJSON":"{\"hidePanelTitles\":false,\"useMargins\":true}","panelsJSON":"[{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":15,\"i\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\"},\"panelIndex\":\"2e80716f-c1b6-46f2-be2b-35db744b5031\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsPie\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"26e2cf99-d931-4320-9e15-9dbc148f3534\":{\"columns\":{\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\":{\"label\":\"Top values of url.raw\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"url.raw\",\"isBucketed\":true,\"params\":{\"size\":20,\"orderBy\":{\"type\":\"column\",\"columnId\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"beb72af1-239c-46d8-823b-b00d1e2ace43\":{\"label\":\"Unique count of geo.srcdest\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"geo.srcdest\",\"isBucketed\":false}},\"columnOrder\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"beb72af1-239c-46d8-823b-b00d1e2ace43\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"26e2cf99-d931-4320-9e15-9dbc148f3534\",\"groups\":[\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\",\"6adde1a2-4c6f-47eb-95cc-5c6a9d863a6e\"],\"metric\":\"beb72af1-239c-46d8-823b-b00d1e2ace43\",\"numberDisplay\":\"percent\",\"categoryDisplay\":\"default\",\"legendDisplay\":\"default\",\"nestedLegend\":false}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534\"}]},\"enhancements\":{},\"type\":\"lens\"},\"panelRefName\":\"panel_2e80716f-c1b6-46f2-be2b-35db744b5031\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"da8843e0-6789-4aae-bcd0-81f270538719\"},\"panelIndex\":\"da8843e0-6789-4aae-bcd0-81f270538719\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_da8843e0-6789-4aae-bcd0-81f270538719\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":15,\"w\":24,\"h\":15,\"i\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},\"panelIndex\":\"adcd4418-7299-4efa-b369-5f71a7b4ebe0\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":24,\"h\":15,\"i\":\"869754a7-edf0-478f-a7f1-80374f63108a\"},\"panelIndex\":\"869754a7-edf0-478f-a7f1-80374f63108a\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_869754a7-edf0-478f-a7f1-80374f63108a\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":30,\"w\":24,\"h\":15,\"i\":\"67111cf4-338e-453f-8621-e8dea64082d1\"},\"panelIndex\":\"67111cf4-338e-453f-8621-e8dea64082d1\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_67111cf4-338e-453f-8621-e8dea64082d1\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":30,\"w\":24,\"h\":15,\"i\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},\"panelIndex\":\"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":45,\"w\":24,\"h\":15,\"i\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\"},\"panelIndex\":\"88847944-ae1b-45fd-b102-3b45f9bea04b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_88847944-ae1b-45fd-b102-3b45f9bea04b\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":45,\"w\":24,\"h\":15,\"i\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\"},\"panelIndex\":\"5a7924c7-eac0-4573-9199-fecec5b82e9e\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_5a7924c7-eac0-4573-9199-fecec5b82e9e\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":60,\"w\":24,\"h\":15,\"i\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\"},\"panelIndex\":\"f8f49591-f071-4a96-b1ed-cd65daff5648\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_f8f49591-f071-4a96-b1ed-cd65daff5648\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":60,\"w\":24,\"h\":15,\"i\":\"9f357f47-c2a0-421f-a456-9583c40837ab\"},\"panelIndex\":\"9f357f47-c2a0-421f-a456-9583c40837ab\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_9f357f47-c2a0-421f-a456-9583c40837ab\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":75,\"w\":24,\"h\":15,\"i\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\"},\"panelIndex\":\"6cb383e9-1e80-44f9-80d5-7b8c585668db\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_6cb383e9-1e80-44f9-80d5-7b8c585668db\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":75,\"w\":24,\"h\":15,\"i\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\"},\"panelIndex\":\"57f5f0bf-6610-4599-aad4-37484640b5e2\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_57f5f0bf-6610-4599-aad4-37484640b5e2\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":90,\"w\":24,\"h\":15,\"i\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},\"panelIndex\":\"32d3ab66-52e1-44e3-8c1f-1dccff3c5692\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":90,\"w\":24,\"h\":15,\"i\":\"dd1718fd-74ee-4032-851b-db97e893825d\"},\"panelIndex\":\"dd1718fd-74ee-4032-851b-db97e893825d\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_dd1718fd-74ee-4032-851b-db97e893825d\"},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":105,\"w\":24,\"h\":15,\"i\":\"98a556ee-078b-4e03-93a8-29996133cdcb\"},\"panelIndex\":\"98a556ee-078b-4e03-93a8-29996133cdcb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"type\":\"lens\",\"visualizationType\":\"lnsXY\",\"state\":{\"datasourceStates\":{\"indexpattern\":{\"layers\":{\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\":{\"columns\":{\"ce9117a2-773c-474c-8fb1-18940cf58b38\":{\"label\":\"Top values of type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"type\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false}},\"a3d10552-e352-40d0-a156-e86112c0501a\":{\"label\":\"Top values of _type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"_type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false}},\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"Records\"},\"9c5db2f3-9eb0-4667-9a74-3318301de251\":{\"label\":\"Sum of bytes\",\"dataType\":\"number\",\"operationType\":\"sum\",\"sourceField\":\"bytes\",\"isBucketed\":false,\"scale\":\"ratio\"}},\"columnOrder\":[\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"a3d10552-e352-40d0-a156-e86112c0501a\",\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"incompleteColumns\":{}}}}},\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"999a2d60-cb2a-451c-8d71-80d7e92e70fd\",\"accessors\":[\"cf07d1f1-d3fd-41f7-812c-d8587ec75959\",\"9c5db2f3-9eb0-4667-9a74-3318301de251\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"xAccessor\":\"ce9117a2-773c-474c-8fb1-18940cf58b38\",\"splitAccessor\":\"a3d10552-e352-40d0-a156-e86112c0501a\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]},\"references\":[{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-current-indexpattern\"},{\"type\":\"index-pattern\",\"id\":\"56b34100-619d-11eb-aebf-c306684b328d\",\"name\":\"indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd\"}]},\"enhancements\":{},\"type\":\"lens\"}},{\"version\":\"7.13.1\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":105,\"w\":24,\"h\":15,\"i\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"},\"panelIndex\":\"62a0f0b0-3589-4cef-807b-b1b4258b7a9b\",\"embeddableConfig\":{\"enhancements\":{}},\"panelRefName\":\"panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b\"}]","refreshInterval":{"pause":true,"value":0},"timeFrom":"2015-09-20T01:56:56.132Z","timeRestore":true,"timeTo":"2015-09-21T11:18:20.471Z","title":"lens_dashboard_logstash","version":1},"coreMigrationVersion":"7.13.5","id":"f458b9f0-bd9e-11eb-9520-1b4c3ca6a781","migrationVersion":{"dashboard":"7.13.1"},"references":[{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:panel_2e80716f-c1b6-46f2-be2b-35db744b5031","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"2e80716f-c1b6-46f2-be2b-35db744b5031:indexpattern-datasource-layer-26e2cf99-d931-4320-9e15-9dbc148f3534","type":"index-pattern"},{"id":"aa4b8da0-bd9f-11eb-9520-1b4c3ca6a781","name":"da8843e0-6789-4aae-bcd0-81f270538719:panel_da8843e0-6789-4aae-bcd0-81f270538719","type":"lens"},{"id":"2d3f1250-bd9f-11eb-9520-1b4c3ca6a781","name":"adcd4418-7299-4efa-b369-5f71a7b4ebe0:panel_adcd4418-7299-4efa-b369-5f71a7b4ebe0","type":"lens"},{"id":"edd5a560-bda4-11eb-9520-1b4c3ca6a781","name":"869754a7-edf0-478f-a7f1-80374f63108a:panel_869754a7-edf0-478f-a7f1-80374f63108a","type":"lens"},{"id":"2c25a450-bda5-11eb-9520-1b4c3ca6a781","name":"67111cf4-338e-453f-8621-e8dea64082d1:panel_67111cf4-338e-453f-8621-e8dea64082d1","type":"lens"},{"id":"e79116e0-bd9e-11eb-9520-1b4c3ca6a781","name":"13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d:panel_13f21ad2-9b2d-4aa2-a908-b62e1bdedc1d","type":"lens"},{"id":"974fb950-bda5-11eb-9520-1b4c3ca6a781","name":"88847944-ae1b-45fd-b102-3b45f9bea04b:panel_88847944-ae1b-45fd-b102-3b45f9bea04b","type":"lens"},{"id":"21905950-bd9f-11eb-9520-1b4c3ca6a781","name":"5a7924c7-eac0-4573-9199-fecec5b82e9e:panel_5a7924c7-eac0-4573-9199-fecec5b82e9e","type":"lens"},{"id":"51b63040-bda5-11eb-9520-1b4c3ca6a781","name":"f8f49591-f071-4a96-b1ed-cd65daff5648:panel_f8f49591-f071-4a96-b1ed-cd65daff5648","type":"lens"},{"id":"b00679c0-bda5-11eb-9520-1b4c3ca6a781","name":"9f357f47-c2a0-421f-a456-9583c40837ab:panel_9f357f47-c2a0-421f-a456-9583c40837ab","type":"lens"},{"id":"652ade10-bd9f-11eb-9520-1b4c3ca6a781","name":"6cb383e9-1e80-44f9-80d5-7b8c585668db:panel_6cb383e9-1e80-44f9-80d5-7b8c585668db","type":"lens"},{"id":"7f3b5fb0-be2f-11eb-9520-1b4c3ca6a781","name":"57f5f0bf-6610-4599-aad4-37484640b5e2:panel_57f5f0bf-6610-4599-aad4-37484640b5e2","type":"lens"},{"id":"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781","name":"32d3ab66-52e1-44e3-8c1f-1dccff3c5692:panel_32d3ab66-52e1-44e3-8c1f-1dccff3c5692","type":"lens"},{"id":"dd315430-be2f-11eb-9520-1b4c3ca6a781","name":"dd1718fd-74ee-4032-851b-db97e893825d:panel_dd1718fd-74ee-4032-851b-db97e893825d","type":"lens"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-current-indexpattern","type":"index-pattern"},{"id":"56b34100-619d-11eb-aebf-c306684b328d","name":"98a556ee-078b-4e03-93a8-29996133cdcb:indexpattern-datasource-layer-999a2d60-cb2a-451c-8d71-80d7e92e70fd","type":"index-pattern"},{"id":"0dbbf8b0-be3c-11eb-9520-1b4c3ca6a781","name":"62a0f0b0-3589-4cef-807b-b1b4258b7a9b:panel_62a0f0b0-3589-4cef-807b-b1b4258b7a9b","type":"lens"},{"id":"e6994960-bd9e-11eb-9520-1b4c3ca6a781","name":"tag-e6994960-bd9e-11eb-9520-1b4c3ca6a781","type":"tag"}],"sort":[1651599812857,258],"type":"dashboard","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzk3LDFd"} +{"attributes":{"description":"this is a logstash saved query","filters":[],"query":{"language":"kuery","query":"extension.raw :\"gif\" and machine.os.raw :\"ios\" "},"timefilter":{"from":"2015-09-20T01:56:56.132Z","refreshInterval":{"pause":true,"value":0},"to":"2015-09-21T11:18:20.471Z"},"title":"logstash_saved_query"},"coreMigrationVersion":"7.13.5","id":"logstash_saved_query","references":[],"sort":[1651599812857,259],"type":"query","updated_at":"2022-05-03T17:43:32.857Z","version":"Wzk5LDFd"} +{"attributes":{"description":"Shakespeare query","filters":[],"query":{"language":"kuery","query":"speaker : \"OTHELLO\" and play_name :\"Othello\" "},"title":"shakespeare_current_query"},"coreMigrationVersion":"7.13.5","id":"shakespeare_current_query","references":[],"sort":[1651599812857,260],"type":"query","updated_at":"2022-05-03T17:43:32.857Z","version":"WzEwMSwxXQ=="} +{"attributes":{"@created":"2021-05-27T18:53:18.432Z","@timestamp":"2021-05-27T19:46:12.539Z","assets":{},"colors":["#37988d","#c19628","#b83c6f","#3f9939","#1785b0","#ca5f35","#45bdb0","#f2bc33","#e74b8b","#4fbf48","#1ea6dc","#fd7643","#72cec3","#f5cc5d","#ec77a8","#7acf74","#4cbce4","#fd986f","#a1ded7","#f8dd91","#f2a4c5","#a6dfa2","#86d2ed","#fdba9f","#000000","#444444","#777777","#BBBBBB","#FFFFFF","rgba(255,255,255,0)"],"css":".canvasPage {\n\n}","height":720,"isWriteable":true,"name":"logstash-canvas-workpad","page":1,"pages":[{"elements":[{"expression":"savedLens id=\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-56d2ba72-f227-4d04-9478-a1d6f0c7e601","position":{"angle":0,"height":300,"left":20,"parent":null,"top":20,"width":500}},{"expression":"savedVisualization id=\"0d8a8860-623a-11eb-aebf-c306684b328d\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-afbaa26e-10e7-47d4-bb41-b061dfdced2b","position":{"angle":0,"height":300,"left":527,"parent":null,"top":20,"width":500}}],"groups":[],"id":"page-0f9ef2da-2868-4c0b-9223-fd3c9e53d6c9","style":{"background":"#FFF"},"transition":{}},{"elements":[{"expression":"image dataurl=null mode=\"contain\"\n| render","id":"element-c5534ef7-68c4-46bc-b35a-9e43a7f118c3","position":{"angle":0,"height":107,"left":20,"parent":null,"top":20,"width":132}},{"expression":"filters\n| essql query=\"SELECT machine.os.raw FROM \\\"logstash-*\\\"\"\n| pointseries x=\"machine.os.raw\" y=\"size(machine.os.raw)\" color=\"machine.os.raw\" size=\"sum(machine.os.raw)\"\n| plot defaultStyle={seriesStyle points=5 fill=1}\n| render","id":"element-5f7a3312-0e77-471c-9b8f-f98cb38075fb","position":{"angle":0,"height":192,"left":221,"parent":null,"top":56,"width":451}},{"expression":"timefilterControl compact=true column=@timestamp\n| render","filter":"timefilter from=\"now-29y\" to=now column=@timestamp","id":"element-6e00dcf4-06fe-4bd9-9315-d32d9d3fac5f","position":{"angle":0,"height":50,"left":221,"parent":null,"top":-1,"width":500}},{"expression":"filters\n| esdocs index=\"logstash-*\" fields=\"@timestamp, response.raw\"\n| pointseries x=\"size(response.raw)\" y=\"@timestamp\" color=\"response.raw\"\n| plot\n| render","id":"element-20281fac-1c3a-4ee3-9132-44379fb60b74","position":{"angle":0,"height":262,"left":51,"parent":null,"top":304,"width":590}},{"expression":"filters\n| timelion query=\".es(index=logstash-*, metric=sum:bytes)\"\n| pointseries x=\"@timestamp\" y=\"sum(value)\"\n| plot defaultStyle={seriesStyle lines=3}\n| render","id":"element-337b0548-5d6d-44cd-a324-eb50d63c7bd0","position":{"angle":0,"height":309,"left":648,"parent":null,"top":290,"width":369}},{"expression":"savedLens id=\"bb9e5bb0-be2f-11eb-9520-1b4c3ca6a781\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-353e5583-0dbb-4a6b-bac7-3b2a6b305397","position":{"angle":0,"height":181.99999999999997,"left":855,"parent":"group-d2618a19-3982-414e-93df-b2cb165b7c7e","top":15.000000000000014,"width":76.961271102284}},{"expression":"savedVisualization id=\"0d8a8860-623a-11eb-aebf-c306684b328d\" timerange={timerange from=\"now-15y\" to=\"now\"}\n| render","filter":null,"id":"element-0e5501a6-9e87-42bc-b539-1e697e62051b","position":{"angle":0,"height":181.99999999999997,"left":933.038728897716,"parent":"group-d2618a19-3982-414e-93df-b2cb165b7c7e","top":15.000000000000014,"width":76.961271102284}}],"groups":[],"id":"page-59c3cf09-1811-4324-995b-7336c1c11ab8","style":{"background":"#FFF"},"transition":{}}],"variables":[],"width":1080},"coreMigrationVersion":"7.13.5","id":"workpad-f2024ca3-e366-447a-b3af-7db4400646ef","migrationVersion":{"canvas-workpad":"7.0.0"},"references":[],"sort":[1651599812857,261],"type":"canvas-workpad","updated_at":"2022-05-03T17:43:32.857Z","version":"WzEwMiwxXQ=="} +{"exportedCount":82,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file diff --git a/x-pack/test/functional/apps/saved_objects_management/import_saved_objects_between_versions.ts b/x-pack/test/functional/apps/saved_objects_management/import_saved_objects_between_versions.ts index 168a2fd8d8aec..8716b10150d79 100644 --- a/x-pack/test/functional/apps/saved_objects_management/import_saved_objects_between_versions.ts +++ b/x-pack/test/functional/apps/saved_objects_management/import_saved_objects_between_versions.ts @@ -56,7 +56,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.savedObjects.clickImportDone(); await PageObjects.savedObjects.waitTableIsLoaded(); const newObjectCount = await PageObjects.savedObjects.getExportCount(); - expect(newObjectCount - initialObjectCount).to.eql(86); + expect(newObjectCount - initialObjectCount).to.eql(82); // logstash by reference dashboard with drilldowns await PageObjects.common.navigateToApp('dashboard'); From 0c969148372e30f3693a677834a95d7d3f89eee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Wed, 4 May 2022 10:41:26 -0400 Subject: [PATCH 28/68] [APM] Fixing service overview test (#131454) * skipping flaky test * Fix environment suggestion test * removing comment Co-authored-by: Kate Patticha --- .../service_overview/service_overview.spec.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts index edb1b8a82f6dd..caeac36b7cba8 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/integration/read_only_user/service_overview/service_overview.spec.ts @@ -220,14 +220,18 @@ describe('Service Overview', () => { 'suggestionsRequest' ); - cy.get('[data-test-subj="environmentFilter"]').type('pro').click(); + cy.get('[data-test-subj="environmentFilter"]').type('production'); cy.expectAPIsToHaveBeenCalledWith({ apisIntercepted: ['@suggestionsRequest'], - value: 'fieldValue=pro', + value: 'fieldValue=production', }); - cy.contains('button', 'production').click(); + cy.get( + '[data-test-subj="comboBoxOptionsList environmentFilter-optionsList"]' + ) + .contains('production') + .click({ force: true }); cy.expectAPIsToHaveBeenCalledWith({ apisIntercepted: aliasNames, From 4f88950bdec818a9433ffe16f96cced483f679e6 Mon Sep 17 00:00:00 2001 From: Gayathri R Date: Wed, 4 May 2022 20:13:11 +0530 Subject: [PATCH 29/68] [APM] ellipsis truncation issue - dependencies and service section (#122203) * Added ellipsis truncation to apm dependency * Added ellipsis truncation to apm service * Removed un-used variable * Added ellipsis truncation * removing unused import * modified css classname * created a new component for truncation without tooltip * using text truncate styling and removed truncatewithouttooltip component * restored styledlink --- x-pack/plugins/apm/public/components/shared/backend_link.tsx | 4 +++- x-pack/plugins/apm/public/components/shared/service_link.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/apm/public/components/shared/backend_link.tsx b/x-pack/plugins/apm/public/components/shared/backend_link.tsx index 6dde4e269ec54..ac93228c76bcd 100644 --- a/x-pack/plugins/apm/public/components/shared/backend_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/backend_link.tsx @@ -42,7 +42,9 @@ export function BackendLink({ - {query.backendName} + + {query.backendName} +
); diff --git a/x-pack/plugins/apm/public/components/shared/service_link.tsx b/x-pack/plugins/apm/public/components/shared/service_link.tsx index dc4f56ac57053..00a360f3fdebb 100644 --- a/x-pack/plugins/apm/public/components/shared/service_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/service_link.tsx @@ -42,7 +42,9 @@ export function ServiceLink({ - {serviceName} + + {serviceName} +
); From 94b87e71e93ba8e9ca6b7a40c251f59984c0faf4 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Wed, 4 May 2022 12:01:24 -0300 Subject: [PATCH 30/68] [Session View] Alert UI Fixes (#131356) * adding missing color to use eui theme hook * button and spacing refactor * updating colors and spacing on alerts * adding custom components for nbsp and split text * updating test to match nbsp instead of white space * update process tree node to match design spec --- .../__snapshots__/index.test.tsx.snap | 8 ++-- .../components/process_tree_alert/index.tsx | 4 +- .../components/process_tree_alert/styles.ts | 21 +++++--- .../components/process_tree_alerts/styles.ts | 2 +- .../process_tree_node/index.test.tsx | 4 +- .../components/process_tree_node/index.tsx | 37 +++++++++----- .../components/process_tree_node/nbsp.tsx | 19 ++++++++ .../process_tree_node/split_text.test.tsx | 28 +++++++++++ .../process_tree_node/split_text.tsx | 39 +++++++++++++++ .../components/process_tree_node/styles.ts | 48 +++++++++++++++---- .../process_tree_node/use_button_styles.ts | 6 ++- .../public/hooks/use_eui_theme.ts | 2 + 12 files changed, 180 insertions(+), 38 deletions(-) create mode 100644 x-pack/plugins/session_view/public/components/process_tree_node/nbsp.tsx create mode 100644 x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx create mode 100644 x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx diff --git a/x-pack/plugins/session_view/public/components/process_tree_alert/__snapshots__/index.test.tsx.snap b/x-pack/plugins/session_view/public/components/process_tree_alert/__snapshots__/index.test.tsx.snap index 9614bb1267ea5..b26778c8f8eea 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_alert/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/session_view/public/components/process_tree_alert/__snapshots__/index.test.tsx.snap @@ -6,7 +6,7 @@ Object { "baseElement":
@@ -28,7 +28,7 @@ Object { data-euiicon-type="alert" />
cmd test alert
@@ -52,7 +52,7 @@ Object { , "container":
@@ -74,7 +74,7 @@ Object { data-euiicon-type="alert" />
cmd test alert
diff --git a/x-pack/plugins/session_view/public/components/process_tree_alert/index.tsx b/x-pack/plugins/session_view/public/components/process_tree_alert/index.tsx index 954492782ab93..f01f08f8e3095 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_alert/index.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_alert/index.tsx @@ -73,7 +73,9 @@ export const ProcessTreeAlert = ({ onClick={handleExpandClick} /> - {dataOrDash(name)} + + {dataOrDash(name)} + {dataOrDash(status)} diff --git a/x-pack/plugins/session_view/public/components/process_tree_alert/styles.ts b/x-pack/plugins/session_view/public/components/process_tree_alert/styles.ts index db06be06cc2aa..e8d3b0374c978 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_alert/styles.ts +++ b/x-pack/plugins/session_view/public/components/process_tree_alert/styles.ts @@ -6,8 +6,9 @@ */ import { useMemo } from 'react'; -import { useEuiTheme, transparentize } from '@elastic/eui'; +import { transparentize } from '@elastic/eui'; import { CSSObject } from '@emotion/react'; +import { useEuiTheme } from '../../hooks'; interface StylesDeps { isInvestigated: boolean; @@ -15,7 +16,7 @@ interface StylesDeps { } export const useStyles = ({ isInvestigated, isSelected }: StylesDeps) => { - const { euiTheme } = useEuiTheme(); + const { euiTheme, euiVars } = useEuiTheme(); const cached = useMemo(() => { const { size, colors, font } = euiTheme; @@ -45,8 +46,7 @@ export const useStyles = ({ isInvestigated, isSelected }: StylesDeps) => { display: 'flex', gap: size.s, alignItems: 'center', - minHeight: '20px', - padding: `${size.xs} ${size.base}`, + padding: `0 ${size.base}`, boxSizing: 'content-box', cursor: 'pointer', '&:not(:last-child)': { @@ -56,9 +56,12 @@ export const useStyles = ({ isInvestigated, isSelected }: StylesDeps) => { '&:hover': { background: hoverBgColor, }, - button: { + '&& button': { flexShrink: 0, marginRight: size.s, + '&:hover, &:focus, &:focus-within': { + backgroundColor: transparentize(euiVars.buttonsBackgroundNormalDefaultPrimary, 0.2), + }, }, }; @@ -66,11 +69,17 @@ export const useStyles = ({ isInvestigated, isSelected }: StylesDeps) => { textTransform: 'capitalize', }; + const alertName: CSSObject = { + padding: `${size.xs} 0`, + color: colors.title, + }; + return { alert, alertStatus, + alertName, }; - }, [euiTheme, isInvestigated, isSelected]); + }, [euiTheme, isInvestigated, isSelected, euiVars]); return cached; }; diff --git a/x-pack/plugins/session_view/public/components/process_tree_alerts/styles.ts b/x-pack/plugins/session_view/public/components/process_tree_alerts/styles.ts index bd95d87258178..a82a2253f4b2f 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_alerts/styles.ts +++ b/x-pack/plugins/session_view/public/components/process_tree_alerts/styles.ts @@ -16,7 +16,7 @@ export const useStyles = () => { const { size, colors, border } = euiTheme; const container: CSSObject = { - margin: `${size.xs} ${size.base} 0 ${size.xs}`, + margin: `${size.xs} ${size.base} ${size.base} ${size.xs}`, color: colors.text, padding: `${size.s} 0`, borderStyle: 'solid', diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx index 7daceaa366c43..1eba726607c10 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_node/index.test.tsx @@ -57,7 +57,9 @@ describe('ProcessTreeNode component', () => { it('should have an alternate rendering for a session leader', async () => { renderResult = mockedContext.render(); - expect(renderResult.container.textContent).toEqual(' bash started by vagrant'); + expect(renderResult.container.textContent?.replace(/\s+/g, ' ')).toEqual( + ' bash started by vagrant' + ); }); // commented out until we get new UX for orphans treatment aka disjointed tree diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx index d868dee04cbf5..db81734c65937 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx +++ b/x-pack/plugins/session_view/public/components/process_tree_node/index.tsx @@ -33,6 +33,8 @@ import { AlertButton, ChildrenProcessesButton } from './buttons'; import { useButtonStyles } from './use_button_styles'; import { KIBANA_DATE_FORMAT } from '../../../common/constants'; import { useStyles } from './styles'; +import { SplitText } from './split_text'; +import { Nbsp } from './nbsp'; export interface ProcessDeps { process: Process; @@ -255,14 +257,21 @@ export function ProcessTreeNode({ onClick={onProcessClicked} > {isSessionLeader ? ( - <> - {' '} - {dataOrDash(name || args?.[0])}{' '} - {' '} - {dataOrDash(user?.name)} - + + + + {dataOrDash(name || args?.[0])} + + + + + + + + {dataOrDash(user?.name)} + ) : ( - + <> {showTimestamp && ( {timeStampsNormal} @@ -270,13 +279,15 @@ export function ProcessTreeNode({ )} - {' '} - - {dataOrDash(workingDirectory)}  - {dataOrDash(args?.[0])}{' '} - {args?.slice(1).join(' ')} + + + {dataOrDash(workingDirectory)} + + {dataOrDash(args?.[0])} + + {args?.slice(1).join(' ') || ''} - + )} {showUserEscalation && ( diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/nbsp.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/nbsp.tsx new file mode 100644 index 0000000000000..65274cd0b6ade --- /dev/null +++ b/x-pack/plugins/session_view/public/components/process_tree_node/nbsp.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { CSSObject } from '@emotion/react'; + +const css: CSSObject = { + width: '6px', + display: 'inline-block', +}; + +// Renders a non-breaking space with a specific width. +export const Nbsp = () => { + return  ; +}; diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx new file mode 100644 index 0000000000000..eaa18b18d81cf --- /dev/null +++ b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.test.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { SplitText } from './split_text'; + +describe('SplitText component', () => { + it('should split a text into one span for each character', async () => { + const text = 'hello world'; + + const renderResult = render({text}); + for (const char of text.replace(/\s+/g, '').split('')) { + expect(await renderResult.findAllByText(char)).toBeTruthy(); + } + expect(renderResult.container.textContent?.replace(/\s+/g, ' ')).toEqual(text); + }); + it('should provide an acessible label for screen readers', async () => { + const text = 'hello world'; + + const renderResult = render({text}); + expect(renderResult.queryByRole('document', { name: text })).toBeTruthy(); + }); +}); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx new file mode 100644 index 0000000000000..d31590c9ab967 --- /dev/null +++ b/x-pack/plugins/session_view/public/components/process_tree_node/split_text.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { CSSObject } from '@emotion/react'; + +type Props = { + children: string; + role?: string; +}; + +const css: CSSObject = { + '&&': { + display: 'inline', + fontSize: 0, + lineHeight: 0, + }, +}; + +// Split a text into multiple spans, each of which a single character. This is +// useful for creating inline "like" text but still having control over the blocks +// exclusive features, such height or line-height. +// It adds a `aria-label` attribute to a parent span, which is used by screen readers to +// read the text as a single block. +export const SplitText = ({ children, role = 'document', ...props }: Props) => ( + + {children.split('').map(function (char, index) { + return ( + + ); + })} + +); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts b/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts index e328c28be8bad..b68df480064b3 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts +++ b/x-pack/plugins/session_view/public/components/process_tree_node/styles.ts @@ -30,14 +30,15 @@ export const useStyles = ({ const cached = useMemo(() => { const { colors, border, size, font } = euiTheme; + const ALERT_INDICATOR_WIDTH = '3px'; + const LINE_HEIGHT = '21px'; + const FONT_SIZE = '13px'; const TREE_INDENT = `calc(${size.l} + ${size.xxs})`; const PROCESS_TREE_LEFT_PADDING = size.s; const darkText: CSSObject = { color: colors.text, fontFamily: font.familyCode, - paddingLeft: size.xxs, - paddingRight: size.xs, }; const children: CSSObject = { @@ -84,15 +85,19 @@ export const useStyles = ({ const { bgColor, borderColor, hoverColor, searchResColor } = getHighlightColors(); + const fontSpacingReset: CSSObject = { + fontSize: 0, + lineHeight: 0, + }; + const processNode: CSSObject = { + ...fontSpacingReset, display: 'block', cursor: 'pointer', position: 'relative', - padding: `${size.xs} 0px`, marginBottom: isSessionLeader ? size.s : '0px', '&:hover:before': { backgroundColor: hoverColor, - transform: `translateY(-${size.xs})`, }, '&:before': { position: 'absolute', @@ -100,10 +105,29 @@ export const useStyles = ({ pointerEvents: 'none', content: `''`, marginLeft: `calc(-${depth} * ${TREE_INDENT} - ${PROCESS_TREE_LEFT_PADDING})`, - borderLeft: `${size.xs} solid ${borderColor}`, + borderLeft: `${ALERT_INDICATOR_WIDTH} solid ${borderColor}`, backgroundColor: bgColor, width: `calc(100% + ${depth} * ${TREE_INDENT} + ${PROCESS_TREE_LEFT_PADDING})`, - transform: `translateY(-${size.xs})`, + }, + }; + + const textSection: CSSObject = { + marginLeft: size.s, + span: { + fontSize: FONT_SIZE, + lineHeight: LINE_HEIGHT, + verticalAlign: 'middle', + display: 'inline-block', + }, + }; + + const sessionLeader: CSSObject = { + ...fontSpacingReset, + 'span, b': { + fontSize: FONT_SIZE, + lineHeight: LINE_HEIGHT, + display: 'inline-block', + verticalAlign: 'middle', }, }; @@ -119,16 +143,17 @@ export const useStyles = ({ verticalAlign: 'middle', color: euiVars.euiTextSubduedColor, wordBreak: 'break-all', - minHeight: `calc(${size.l} - ${size.xxs})`, - lineHeight: `calc(${size.l} - ${size.xxs})`, + padding: `${size.xs} 0px`, + button: { + marginLeft: '6px', + marginRight: size.xxs, + }, }; const workingDir: CSSObject = { color: colors.successText, fontFamily: font.familyCode, fontWeight: font.weight.regular, - paddingLeft: size.s, - paddingRight: size.xxs, }; const timeStamp: CSSObject = { @@ -139,6 +164,7 @@ export const useStyles = ({ paddingRight: size.base, paddingLeft: size.xxl, position: 'relative', + lineHeight: LINE_HEIGHT, }; const alertDetails: CSSObject = { @@ -157,6 +183,8 @@ export const useStyles = ({ timeStamp, alertDetails, icon, + textSection, + sessionLeader, }; }, [depth, euiTheme, hasAlerts, hasInvestigatedAlert, isSelected, euiVars, isSessionLeader]); diff --git a/x-pack/plugins/session_view/public/components/process_tree_node/use_button_styles.ts b/x-pack/plugins/session_view/public/components/process_tree_node/use_button_styles.ts index 04d3eb793bfda..8cd4e2c5004b4 100644 --- a/x-pack/plugins/session_view/public/components/process_tree_node/use_button_styles.ts +++ b/x-pack/plugins/session_view/public/components/process_tree_node/use_button_styles.ts @@ -37,7 +37,8 @@ export const useButtonStyles = () => { }, }, '&&:hover, &&:focus': { - background: transparentize(euiVars.euiColorVis6, 0.04), + background: transparentize(euiVars.euiColorVis6, 0.12), + textDecoration: 'none', }, '&.isExpanded > span svg': { transform: `rotate(180deg)`, @@ -61,7 +62,8 @@ export const useButtonStyles = () => { background: transparentize(euiVars.euiColorDanger, 0.04), border: `${border.width.thin} solid ${transparentize(euiVars.euiColorDanger, 0.48)}`, '&&:hover, &&:focus': { - background: transparentize(euiVars.euiColorDanger, 0.04), + background: transparentize(euiVars.euiColorDanger, 0.12), + textDecoration: 'none', }, '&.isExpanded': { color: colors.ghost, diff --git a/x-pack/plugins/session_view/public/hooks/use_eui_theme.ts b/x-pack/plugins/session_view/public/hooks/use_eui_theme.ts index f7021f6146f09..02f7dd479d2ac 100644 --- a/x-pack/plugins/session_view/public/hooks/use_eui_theme.ts +++ b/x-pack/plugins/session_view/public/hooks/use_eui_theme.ts @@ -13,6 +13,7 @@ type EuiThemeProps = Parameters; type ExtraEuiVars = { // eslint-disable-next-line @typescript-eslint/naming-convention euiColorVis6_asText: string; + buttonsBackgroundNormalDefaultPrimary: string; }; type EuiVars = typeof euiLightVars & ExtraEuiVars; type EuiThemeReturn = ReturnType & { euiVars: EuiVars }; @@ -29,6 +30,7 @@ export const useEuiTheme = (...props: EuiThemeProps): EuiThemeReturn => { const extraEuiVars: ExtraEuiVars = { // eslint-disable-next-line @typescript-eslint/naming-convention euiColorVis6_asText: shade(themeVars.euiColorVis6, 0.335), + buttonsBackgroundNormalDefaultPrimary: '#006DE4', }; return { From 5f06375fe6afa4a49ee5986cb277085e49f96a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Wed, 4 May 2022 17:15:33 +0200 Subject: [PATCH 31/68] [FullStory] Document browser exposed config in the test (#131527) --- test/plugin_functional/test_suites/core_plugins/rendering.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 0e2484691e03b..56264eec24477 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -165,6 +165,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.cloud.deployment_url (string)', 'xpack.cloud.full_story.enabled (boolean)', 'xpack.cloud.full_story.org_id (any)', + // No PII. Just the list of event types we want to forward to FullStory. 'xpack.cloud.full_story.eventTypesAllowlist (array)', 'xpack.cloud.id (string)', 'xpack.cloud.organization_url (string)', From 956612d071a9b9a1567ed997db15c69aba7433f3 Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau Date: Wed, 4 May 2022 11:18:05 -0400 Subject: [PATCH 32/68] [RAM] Bug api find/index alerts (#131338) * fix bug * fix unit test * bing back tests alive after a long CPR * fix test and bring back recursive aggs * I need to do an intersectiona and not union * fix last integration test --- .../authorization/alerting_authorization.ts | 1 + x-pack/plugins/rule_registry/common/types.ts | 270 ++++++++++-------- .../server/alert_data_client/alerts_client.ts | 14 +- .../rule_registry/server/routes/find.ts | 8 +- .../rule_data_plugin_service.mock.ts | 2 +- .../rule_data_plugin_service.ts | 11 +- .../search_strategy/search_strategy.test.ts | 26 +- .../server/search_strategy/search_strategy.ts | 21 +- .../alerting.test.ts | 36 ++- .../feature_privilege_builder/alerting.ts | 2 +- .../security_solution/server/features.ts | 6 + .../rule_registry/alerts/data.json | 8 +- .../tests/basic/find_alerts.ts | 78 ++--- .../tests/basic/get_alerts_index.ts | 48 ++-- .../security_and_spaces/tests/basic/index.ts | 5 +- .../tests/trial/get_alert_by_id.ts | 16 +- .../spaces_only/tests/trial/update_alert.ts | 16 +- 17 files changed, 305 insertions(+), 263 deletions(-) diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts index b9acfed7dcc65..26aa7a706db0a 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization.ts @@ -32,6 +32,7 @@ export enum ReadOperations { GetAlertSummary = 'getAlertSummary', GetExecutionLog = 'getExecutionLog', Find = 'find', + GetAuthorizedAlertsIndices = 'getAuthorizedAlertsIndices', } export enum WriteOperations { diff --git a/x-pack/plugins/rule_registry/common/types.ts b/x-pack/plugins/rule_registry/common/types.ts index 4bf5fa8b23fdc..d1c5b6706c391 100644 --- a/x-pack/plugins/rule_registry/common/types.ts +++ b/x-pack/plugins/rule_registry/common/types.ts @@ -75,9 +75,8 @@ interface BucketAggsSchemas { | { [x: string]: SortOrderSchema } | Array<{ [x: string]: SortOrderSchema }>; }; - aggs?: { - [x: string]: BucketAggsSchemas; - }; + aggs?: BucketAggsSchemas; + aggregations?: BucketAggsSchemas; } /** @@ -114,78 +113,83 @@ interface BucketAggsSchemas { * - significant_text * - variable_width_histogram */ -export const BucketAggsSchemas: t.Type = t.recursion('BucketAggsSchemas', () => - t.exact( - t.partial({ - filter: t.exact( - t.partial({ - term: t.record(t.string, t.union([t.string, t.boolean, t.number])), - }) - ), - date_histogram: t.exact( - t.partial({ - field: t.string, - fixed_interval: t.string, - min_doc_count: t.number, - extended_bounds: t.type({ - min: t.string, - max: t.string, - }), - }) - ), - histogram: t.exact( - t.partial({ - field: t.string, - interval: t.number, - min_doc_count: t.number, - extended_bounds: t.exact( - t.type({ - min: t.number, - max: t.number, - }) - ), - hard_bounds: t.exact( - t.type({ - min: t.number, - max: t.number, - }) - ), - missing: t.number, - keyed: t.boolean, - order: t.exact( - t.type({ - _count: t.string, - _key: t.string, - }) - ), - }) - ), - nested: t.type({ - path: t.string, - }), - terms: t.exact( - t.partial({ - field: t.string, - collect_mode: t.string, - exclude: t.union([t.string, t.array(t.string)]), - include: t.union([t.string, t.array(t.string)]), - execution_hint: t.string, - missing: t.union([t.number, t.string]), - min_doc_count: t.number, - size: t.number, - show_term_doc_count_error: t.boolean, - order: t.union([ - sortOrderSchema, - t.record(t.string, sortOrderSchema), - t.array(t.record(t.string, sortOrderSchema)), - ]), - }) - ), - aggs: t.record(t.string, BucketAggsSchemas), - }) - ) +const bucketAggsTempsSchemas: t.Type = t.exact( + t.partial({ + filter: t.exact( + t.partial({ + term: t.record(t.string, t.union([t.string, t.boolean, t.number])), + }) + ), + date_histogram: t.exact( + t.partial({ + field: t.string, + fixed_interval: t.string, + min_doc_count: t.number, + extended_bounds: t.type({ + min: t.string, + max: t.string, + }), + }) + ), + histogram: t.exact( + t.partial({ + field: t.string, + interval: t.number, + min_doc_count: t.number, + extended_bounds: t.exact( + t.type({ + min: t.number, + max: t.number, + }) + ), + hard_bounds: t.exact( + t.type({ + min: t.number, + max: t.number, + }) + ), + missing: t.number, + keyed: t.boolean, + order: t.exact( + t.type({ + _count: t.string, + _key: t.string, + }) + ), + }) + ), + nested: t.type({ + path: t.string, + }), + terms: t.exact( + t.partial({ + field: t.string, + collect_mode: t.string, + exclude: t.union([t.string, t.array(t.string)]), + include: t.union([t.string, t.array(t.string)]), + execution_hint: t.string, + missing: t.union([t.number, t.string]), + min_doc_count: t.number, + size: t.number, + show_term_doc_count_error: t.boolean, + order: t.union([ + sortOrderSchema, + t.record(t.string, sortOrderSchema), + t.array(t.record(t.string, sortOrderSchema)), + ]), + }) + ), + }) ); +export const bucketAggsSchemas = t.intersection([ + bucketAggsTempsSchemas, + t.partial({ + aggs: t.union([t.record(t.string, bucketAggsTempsSchemas), t.undefined]), + aggregations: t.union([t.record(t.string, bucketAggsTempsSchemas), t.undefined]), + }), +]); + /** * Schemas for the metrics Aggregations * @@ -215,57 +219,75 @@ export const BucketAggsSchemas: t.Type = t.recursion('BucketA * - t_test * - value_count */ -export const metricsAggsSchemas = t.partial({ - avg: t.partial({ - field: t.string, - missing: t.union([t.string, t.number, t.boolean]), - }), - cardinality: t.partial({ - field: t.string, - precision_threshold: t.number, - rehash: t.boolean, - missing: t.union([t.string, t.number, t.boolean]), - }), - min: t.partial({ - field: t.string, - missing: t.union([t.string, t.number, t.boolean]), - format: t.string, - }), - max: t.partial({ - field: t.string, - missing: t.union([t.string, t.number, t.boolean]), - format: t.string, - }), - sum: t.partial({ - field: t.string, - missing: t.union([t.string, t.number, t.boolean]), - }), - top_hits: t.partial({ - explain: t.boolean, - docvalue_fields: t.union([t.string, t.array(t.string)]), - stored_fields: t.union([t.string, t.array(t.string)]), - from: t.number, - size: t.number, - sort: sortSchema, - seq_no_primary_term: t.boolean, - version: t.boolean, - track_scores: t.boolean, - highlight: t.any, - _source: t.union([t.boolean, t.string, t.array(t.string)]), - }), - weighted_avg: t.partial({ - format: t.string, - value_type: t.string, - value: t.partial({ - field: t.string, - missing: t.number, - }), - weight: t.partial({ - field: t.string, - missing: t.number, - }), - }), -}); +export const metricsAggsSchemas = t.exact( + t.partial({ + avg: t.exact( + t.partial({ + field: t.string, + missing: t.union([t.string, t.number, t.boolean]), + }) + ), + cardinality: t.exact( + t.partial({ + field: t.string, + precision_threshold: t.number, + rehash: t.boolean, + missing: t.union([t.string, t.number, t.boolean]), + }) + ), + min: t.exact( + t.partial({ + field: t.string, + missing: t.union([t.string, t.number, t.boolean]), + format: t.string, + }) + ), + max: t.exact( + t.partial({ + field: t.string, + missing: t.union([t.string, t.number, t.boolean]), + format: t.string, + }) + ), + sum: t.exact( + t.partial({ + field: t.string, + missing: t.union([t.string, t.number, t.boolean]), + }) + ), + top_hits: t.exact( + t.partial({ + explain: t.boolean, + docvalue_fields: t.union([t.string, t.array(t.string)]), + stored_fields: t.union([t.string, t.array(t.string)]), + from: t.number, + size: t.number, + sort: sortSchema, + seq_no_primary_term: t.boolean, + version: t.boolean, + track_scores: t.boolean, + highlight: t.any, + _source: t.union([t.boolean, t.string, t.array(t.string)]), + }) + ), + weighted_avg: t.exact( + t.partial({ + format: t.string, + value_type: t.string, + value: t.partial({ + field: t.string, + missing: t.number, + }), + weight: t.partial({ + field: t.string, + missing: t.number, + }), + }) + ), + aggs: t.undefined, + aggregations: t.undefined, + }) +); export type PutIndexTemplateRequest = estypes.IndicesPutIndexTemplateRequest & { body?: { composed_of?: string[] }; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index b5df5dc830d48..effd2f4f81b89 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -647,7 +647,6 @@ export class AlertsClient { [ReadOperations.Find, ReadOperations.Get, WriteOperations.Update], AlertingAuthorizationEntity.Alert ); - // As long as the user can read a minimum of one type of rule type produced by the provided feature, // the user should be provided that features' alerts index. // Limiting which alerts that user can read on that index will be done via the findAuthorizationFilter @@ -655,19 +654,16 @@ export class AlertsClient { for (const ruleType of augmentedRuleTypes.authorizedRuleTypes) { authorizedFeatures.add(ruleType.producer); } - const validAuthorizedFeatures = Array.from(authorizedFeatures).filter( (feature): feature is ValidFeatureId => featureIds.includes(feature) && isValidFeatureId(feature) ); - - const toReturn = validAuthorizedFeatures.flatMap((feature) => { - const indices = this.ruleDataService.findIndicesByFeature(feature, Dataset.alerts); - if (feature === 'siem') { - return indices.map((i) => `${i.baseName}-${this.spaceId}`); - } else { - return indices.map((i) => i.baseName); + const toReturn = validAuthorizedFeatures.map((feature) => { + const index = this.ruleDataService.findIndexByFeature(feature, Dataset.alerts); + if (index == null) { + throw new Error(`This feature id ${feature} should be associated to an alert index`); } + return index?.getPrimaryAlias(this.spaceId ?? '*') ?? ''; }); return toReturn; diff --git a/x-pack/plugins/rule_registry/server/routes/find.ts b/x-pack/plugins/rule_registry/server/routes/find.ts index eca0a6c2a0551..675037baa312a 100644 --- a/x-pack/plugins/rule_registry/server/routes/find.ts +++ b/x-pack/plugins/rule_registry/server/routes/find.ts @@ -14,7 +14,7 @@ import { PositiveInteger } from '@kbn/securitysolution-io-ts-types'; import { RacRequestHandlerContext } from '../types'; import { BASE_RAC_ALERTS_API_PATH } from '../../common/constants'; import { buildRouteValidation } from './utils/route_validation'; -import { BucketAggsSchemas } from '../../common/types'; +import { bucketAggsSchemas, metricsAggsSchemas } from '../../common/types'; export const findAlertsByQueryRoute = (router: IRouter) => { router.post( @@ -26,7 +26,11 @@ export const findAlertsByQueryRoute = (router: IRouter t.partial({ index: t.string, query: t.object, - aggs: t.union([t.record(t.string, BucketAggsSchemas), t.undefined]), + aggs: t.union([ + t.record(t.string, bucketAggsSchemas), + t.record(t.string, metricsAggsSchemas), + t.undefined, + ]), size: t.union([PositiveInteger, t.undefined]), track_total_hits: t.union([t.boolean, t.undefined]), _source: t.union([t.array(t.string), t.undefined]), diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts index 8bbc14cab9f82..cfbfafd0092bf 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts @@ -16,7 +16,7 @@ export const ruleDataServiceMock = { initializeService: jest.fn(), initializeIndex: jest.fn(), findIndexByName: jest.fn(), - findIndicesByFeature: jest.fn(), + findIndexByFeature: jest.fn(), }), }; diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts index a940201841e6f..a336f73c87c79 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.ts @@ -71,7 +71,7 @@ export interface IRuleDataService { * Looks up the index information associated with the given Kibana "feature". * Note: features are used in RBAC. */ - findIndicesByFeature(featureId: ValidFeatureId, dataset?: Dataset): IndexInfo[]; + findIndexByFeature(featureId: ValidFeatureId, dataset: Dataset): IndexInfo | null; } // TODO: This is a leftover. Remove its usage from the "observability" plugin and delete it. @@ -214,8 +214,13 @@ export class RuleDataService implements IRuleDataService { return this.indicesByBaseName.get(baseName) ?? null; } - public findIndicesByFeature(featureId: ValidFeatureId, dataset?: Dataset): IndexInfo[] { + public findIndexByFeature(featureId: ValidFeatureId, dataset: Dataset): IndexInfo | null { const foundIndices = this.indicesByFeatureId.get(featureId) ?? []; - return dataset ? foundIndices.filter((i) => i.indexOptions.dataset === dataset) : foundIndices; + if (dataset && foundIndices.length > 0) { + return foundIndices.filter((i) => i.indexOptions.dataset === dataset)[0]; + } else if (foundIndices.length > 0) { + return foundIndices[0]; + } + return null; } } diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts index 79b9a8cd75c58..9bfc4d7a40640 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.test.ts @@ -78,12 +78,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { const searchStrategySearch = jest.fn().mockImplementation(() => of(response)); beforeEach(() => { - ruleDataService.findIndicesByFeature.mockImplementation(() => { - return [ - { - baseName: 'test', - } as IndexInfo, - ]; + ruleDataService.findIndexByFeature.mockImplementation(() => { + return { + baseName: 'test', + } as IndexInfo; }); data.search.getSearchStrategy.mockImplementation(() => { @@ -108,7 +106,7 @@ describe('ruleRegistrySearchStrategyProvider()', () => { }); afterEach(() => { - ruleDataService.findIndicesByFeature.mockClear(); + ruleDataService.findIndexByFeature.mockClear(); data.search.getSearchStrategy.mockClear(); (data.search.searchAsInternalUser.search as jest.Mock).mockClear(); getAuthzFilterSpy.mockClear(); @@ -156,12 +154,10 @@ describe('ruleRegistrySearchStrategyProvider()', () => { }; }); - ruleDataService.findIndicesByFeature.mockImplementation(() => { - return [ - { - baseName: 'myTestIndex', - } as unknown as IndexInfo, - ]; + ruleDataService.findIndexByFeature.mockImplementation(() => { + return { + baseName: 'myTestIndex', + } as unknown as IndexInfo; }); let searchRequest: RuleRegistrySearchRequest = {} as unknown as RuleRegistrySearchRequest; @@ -199,8 +195,8 @@ describe('ruleRegistrySearchStrategyProvider()', () => { request: {}, }; - ruleDataService.findIndicesByFeature.mockImplementationOnce(() => { - return []; + ruleDataService.findIndexByFeature.mockImplementationOnce(() => { + return null; }); const strategy = ruleRegistrySearchStrategyProvider( diff --git a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts index 851ffbdc098da..255af29a9a9d3 100644 --- a/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts +++ b/x-pack/plugins/rule_registry/server/search_strategy/search_strategy.ts @@ -89,17 +89,16 @@ export const ruleRegistrySearchStrategyProvider = ( ); return accum; } - - return [ - ...accum, - ...ruleDataService - .findIndicesByFeature(featureId, Dataset.alerts) - .map((indexInfo) => { - return featureId === 'siem' - ? `${indexInfo.baseName}-${space?.id ?? ''}*` - : `${indexInfo.baseName}*`; - }), - ]; + const alertIndexInfo = ruleDataService.findIndexByFeature(featureId, Dataset.alerts); + if (alertIndexInfo) { + return [ + ...accum, + featureId === 'siem' + ? `${alertIndexInfo.baseName}-${space?.id ?? ''}*` + : `${alertIndexInfo.baseName}*`, + ]; + } + return accum; }, []); if (indices.length === 0) { diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts index 8596f80d09d46..c4da245f48fcd 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.test.ts @@ -128,6 +128,7 @@ describe(`feature_privilege_builder`, () => { Array [ "alerting:1.0.0-zeta1:alert-type/my-feature/alert/get", "alerting:1.0.0-zeta1:alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/getAuthorizedAlertsIndices", ] `); }); @@ -175,6 +176,7 @@ describe(`feature_privilege_builder`, () => { "alerting:1.0.0-zeta1:alert-type/my-feature/rule/find", "alerting:1.0.0-zeta1:alert-type/my-feature/alert/get", "alerting:1.0.0-zeta1:alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/getAuthorizedAlertsIndices", ] `); }); @@ -263,12 +265,13 @@ describe(`feature_privilege_builder`, () => { }); expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` - Array [ - "alerting:1.0.0-zeta1:alert-type/my-feature/alert/get", - "alerting:1.0.0-zeta1:alert-type/my-feature/alert/find", - "alerting:1.0.0-zeta1:alert-type/my-feature/alert/update", - ] - `); + Array [ + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/get", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/getAuthorizedAlertsIndices", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/update", + ] + `); }); test('grants `all` privileges to rules and alerts under feature consumer', () => { @@ -326,6 +329,7 @@ describe(`feature_privilege_builder`, () => { "alerting:1.0.0-zeta1:alert-type/my-feature/rule/unsnooze", "alerting:1.0.0-zeta1:alert-type/my-feature/alert/get", "alerting:1.0.0-zeta1:alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/getAuthorizedAlertsIndices", "alerting:1.0.0-zeta1:alert-type/my-feature/alert/update", ] `); @@ -420,14 +424,16 @@ describe(`feature_privilege_builder`, () => { }); expect(alertingFeaturePrivileges.getActions(privilege, feature)).toMatchInlineSnapshot(` - Array [ - "alerting:1.0.0-zeta1:alert-type/my-feature/alert/get", - "alerting:1.0.0-zeta1:alert-type/my-feature/alert/find", - "alerting:1.0.0-zeta1:alert-type/my-feature/alert/update", - "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/get", - "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/find", - ] - `); + Array [ + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/get", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/getAuthorizedAlertsIndices", + "alerting:1.0.0-zeta1:alert-type/my-feature/alert/update", + "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/get", + "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/getAuthorizedAlertsIndices", + ] + `); }); test('grants both `all` and `read` to rules and alerts privileges under feature consumer', () => { @@ -490,9 +496,11 @@ describe(`feature_privilege_builder`, () => { "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/rule/find", "alerting:1.0.0-zeta1:another-alert-type/my-feature/alert/get", "alerting:1.0.0-zeta1:another-alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:another-alert-type/my-feature/alert/getAuthorizedAlertsIndices", "alerting:1.0.0-zeta1:another-alert-type/my-feature/alert/update", "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/get", "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/find", + "alerting:1.0.0-zeta1:readonly-alert-type/my-feature/alert/getAuthorizedAlertsIndices", ] `); }); diff --git a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts index c23a989951f52..3a692e935cf37 100644 --- a/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts +++ b/x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/alerting.ts @@ -18,7 +18,7 @@ enum AlertingEntity { const readOperations: Record = { rule: ['get', 'getRuleState', 'getAlertSummary', 'getExecutionLog', 'find'], - alert: ['get', 'find'], + alert: ['get', 'find', 'getAuthorizedAlertsIndices'], }; const writeOperations: Record = { diff --git a/x-pack/plugins/security_solution/server/features.ts b/x-pack/plugins/security_solution/server/features.ts index 340c4c54c5fc6..375f66a36c3ac 100644 --- a/x-pack/plugins/security_solution/server/features.ts +++ b/x-pack/plugins/security_solution/server/features.ts @@ -133,6 +133,9 @@ export const getKibanaPrivilegesFeaturePrivileges = (ruleTypes: string[]): Kiban rule: { all: ruleTypes, }, + alert: { + all: ruleTypes, + }, }, management: { insightsAndAlerting: ['triggersActions'], @@ -156,6 +159,9 @@ export const getKibanaPrivilegesFeaturePrivileges = (ruleTypes: string[]): Kiban rule: { read: ruleTypes, }, + alert: { + all: ruleTypes, + }, }, management: { insightsAndAlerting: ['triggersActions'], diff --git a/x-pack/test/functional/es_archives/rule_registry/alerts/data.json b/x-pack/test/functional/es_archives/rule_registry/alerts/data.json index 284c6e9519cc1..9c8d233e02074 100644 --- a/x-pack/test/functional/es_archives/rule_registry/alerts/data.json +++ b/x-pack/test/functional/es_archives/rule_registry/alerts/data.json @@ -57,7 +57,7 @@ "source": { "event.kind" : "signal", "@timestamp": "2020-12-16T15:16:18.570Z", - "kibana.alert.rule.rule_type_id": "siem.signals", + "kibana.alert.rule.rule_type_id": "siem.queryRule", "message": "hello world security", "kibana.alert.rule.consumer": "siem", "kibana.alert.workflow_status": "open", @@ -74,7 +74,7 @@ "source": { "event.kind" : "signal", "@timestamp": "2020-12-16T15:16:18.570Z", - "kibana.alert.rule.rule_type_id": "siem.customRule", + "kibana.alert.rule.rule_type_id": "siem.queryRule", "message": "hello world security", "kibana.alert.rule.consumer": "siem", "kibana.alert.workflow_status": "open", @@ -90,7 +90,7 @@ "id": "space1securityalert", "source": { "@timestamp": "2020-12-16T15:16:18.570Z", - "kibana.alert.rule.rule_type_id": "siem.signals", + "kibana.alert.rule.rule_type_id": "siem.queryRule", "message": "hello world security", "kibana.alert.rule.consumer": "siem", "kibana.alert.workflow_status": "open", @@ -106,7 +106,7 @@ "id": "space2securityalert", "source": { "@timestamp": "2020-12-16T15:16:18.570Z", - "kibana.alert.rule.rule_type_id": "siem.signals", + "kibana.alert.rule.rule_type_id": "siem.queryRule", "message": "hello world security", "kibana.alert.rule.consumer": "siem", "kibana.alert.workflow_status": "open", diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts index ef06fc80c485c..35461b47f6def 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/find_alerts.ts @@ -50,7 +50,6 @@ export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const TEST_URL = '/internal/rac/alerts'; - const ALERTS_INDEX_URL = `${TEST_URL}/index`; const SPACE1 = 'space1'; const SPACE2 = 'space2'; const APM_ALERT_ID = 'NoxgpHkBqbdrfX07MqXV'; @@ -58,38 +57,7 @@ export default ({ getService }: FtrProviderContext) => { const SECURITY_SOLUTION_ALERT_ID = '020202'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; - const getAPMIndexName = async (user: User) => { - const { body: indexNames }: { body: { index_name: string[] | undefined } } = - await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(SPACE1)}${ALERTS_INDEX_URL}`) - .auth(user.username, user.password) - .set('kbn-xsrf', 'true') - .expect(200); - const observabilityIndex = indexNames?.index_name?.find( - (indexName) => indexName === APM_ALERT_INDEX - ); - expect(observabilityIndex).to.eql(APM_ALERT_INDEX); // assert this here so we can use constants in the dynamically-defined test cases below - }; - - const getSecuritySolutionIndexName = async (user: User) => { - const { body: indexNames }: { body: { index_name: string[] | undefined } } = - await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(SPACE1)}${ALERTS_INDEX_URL}`) - .auth(user.username, user.password) - .set('kbn-xsrf', 'true') - .expect(200); - const securitySolution = indexNames?.index_name?.find((indexName) => - indexName.startsWith(SECURITY_SOLUTION_ALERT_INDEX) - ); - expect(securitySolution).to.eql(`${SECURITY_SOLUTION_ALERT_INDEX}-${SPACE1}`); // assert this here so we can use constants in the dynamically-defined test cases below - }; - describe('Alert - Find - RBAC - spaces', () => { - before(async () => { - await getSecuritySolutionIndexName(superUser); - await getAPMIndexName(superUser); - }); - before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/rule_registry/alerts'); }); @@ -98,6 +66,32 @@ export default ({ getService }: FtrProviderContext) => { await esArchiver.unload('x-pack/test/functional/es_archives/rule_registry/alerts'); }); + it(`${superUser.username} should reject at route level when aggs contains script alerts which match query in ${SPACE1}/${SECURITY_SOLUTION_ALERT_INDEX}`, async () => { + const found = await supertestWithoutAuth + .post(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}/find`) + .auth(superUser.username, superUser.password) + .set('kbn-xsrf', 'true') + .send({ + query: { match: { [ALERT_WORKFLOW_STATUS]: 'open' } }, + aggs: { + alertsByGroupingCount: { + terms: { + field: 'kibana.alert.rule.name', + order: { + _count: 'desc', + }, + script: { + source: 'SCRIPT', + }, + size: 10000, + }, + }, + }, + index: SECURITY_SOLUTION_ALERT_INDEX, + }); + expect(found.statusCode).to.eql(400); + }); + it(`${superUser.username} should reject at route level when nested aggs contains script alerts which match query in ${SPACE1}/${SECURITY_SOLUTION_ALERT_INDEX}`, async () => { const found = await supertestWithoutAuth .post(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}/find`) @@ -164,6 +158,26 @@ export default ({ getService }: FtrProviderContext) => { expect(found.body.hits.total.value).to.be.above(0); }); + it(`${superUser.username} should allow cardinality aggs in ${SPACE1}/${SECURITY_SOLUTION_ALERT_INDEX}`, async () => { + const found = await supertestWithoutAuth + .post(`${getSpaceUrlPrefix(SPACE1)}${TEST_URL}/find`) + .auth(superUser.username, superUser.password) + .set('kbn-xsrf', 'true') + .send({ + size: 1, + aggs: { + nbr_consumer: { + cardinality: { + field: 'kibana.alert.rule.consumer', + }, + }, + }, + index: '.alerts*', + }); + expect(found.statusCode).to.eql(200); + expect(found.body.aggregations.nbr_consumer.value).to.be.equal(2); + }); + function addTests({ space, authorizedUsers, unauthorizedUsers, alertId, index }: TestCase) { authorizedUsers.forEach(({ username, password }) => { it(`${username} should finds alerts which match query in ${space}/${index}`, async () => { diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts index 1ba48d5d1aa27..3b30f1b64dc2b 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/get_alerts_index.ts @@ -20,17 +20,16 @@ export default ({ getService }: FtrProviderContext) => { const TEST_URL = '/internal/rac/alerts'; const ALERTS_INDEX_URL = `${TEST_URL}/index`; const SPACE1 = 'space1'; - const APM_ALERT_INDEX = '.alerts-observability-apm'; + const APM_ALERT_INDEX = '.alerts-observability.apm.alerts'; const SECURITY_SOLUTION_ALERT_INDEX = '.alerts-security.alerts'; - const getAPMIndexName = async (user: User, space: string, expected: number = 200) => { - const { body: indexNames }: { body: { index_name: string[] | undefined } } = - await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?features=apm`) - .auth(user.username, user.password) - .set('kbn-xsrf', 'true') - .expect(expected); - return indexNames; + const getAPMIndexName = async (user: User, space: string, expectedStatusCode: number = 200) => { + const resp = await supertestWithoutAuth + .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?features=apm`) + .auth(user.username, user.password) + .set('kbn-xsrf', 'true') + .expect(expectedStatusCode); + return resp.body.index_name as string[]; }; const getSecuritySolutionIndexName = async ( @@ -38,13 +37,13 @@ export default ({ getService }: FtrProviderContext) => { space: string, expectedStatusCode: number = 200 ) => { - const { body: indexNames }: { body: { index_name: string[] | undefined } } = - await supertestWithoutAuth - .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?features=siem`) - .auth(user.username, user.password) - .set('kbn-xsrf', 'true') - .expect(expectedStatusCode); - return indexNames; + const resp = await supertestWithoutAuth + .get(`${getSpaceUrlPrefix(space)}${ALERTS_INDEX_URL}?features=siem`) + .auth(user.username, user.password) + .set('kbn-xsrf', 'true') + .expect(expectedStatusCode); + + return resp.body.index_name as string[]; }; describe('Alert - Get Index - RBAC - spaces', () => { @@ -54,31 +53,22 @@ export default ({ getService }: FtrProviderContext) => { describe('Users:', () => { it(`${obsOnlySpacesAll.username} should be able to access the APM alert in ${SPACE1}`, async () => { const indexNames = await getAPMIndexName(obsOnlySpacesAll, SPACE1); - const observabilityIndex = indexNames?.index_name?.find( - (indexName) => indexName === APM_ALERT_INDEX - ); - expect(observabilityIndex).to.eql(APM_ALERT_INDEX); // assert this here so we can use constants in the dynamically-defined test cases below + expect(indexNames.includes(`${APM_ALERT_INDEX}-${SPACE1}`)).to.eql(true); // assert this here so we can use constants in the dynamically-defined test cases below }); it(`${superUser.username} should be able to access the APM alert in ${SPACE1}`, async () => { const indexNames = await getAPMIndexName(superUser, SPACE1); - const observabilityIndex = indexNames?.index_name?.find( - (indexName) => indexName === APM_ALERT_INDEX - ); - expect(observabilityIndex).to.eql(APM_ALERT_INDEX); // assert this here so we can use constants in the dynamically-defined test cases below + expect(indexNames.includes(`${APM_ALERT_INDEX}-${SPACE1}`)).to.eql(true); // assert this here so we can use constants in the dynamically-defined test cases below }); it(`${secOnlyRead.username} should NOT be able to access the APM alert in ${SPACE1}`, async () => { const indexNames = await getAPMIndexName(secOnlyRead, SPACE1); - expect(indexNames?.index_name?.length).to.eql(0); + expect(indexNames?.length).to.eql(0); }); it(`${secOnlyRead.username} should be able to access the security solution alert in ${SPACE1}`, async () => { const indexNames = await getSecuritySolutionIndexName(secOnlyRead, SPACE1); - const securitySolution = indexNames?.index_name?.find((indexName) => - indexName.startsWith(SECURITY_SOLUTION_ALERT_INDEX) - ); - expect(securitySolution).to.eql(`${SECURITY_SOLUTION_ALERT_INDEX}-${SPACE1}`); // assert this here so we can use constants in the dynamically-defined test cases below + expect(indexNames.includes(`${SECURITY_SOLUTION_ALERT_INDEX}-${SPACE1}`)).to.eql(true); // assert this here so we can use constants in the dynamically-defined test cases below }); }); }); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts index 229f31375200a..ad63d6d1c7ef5 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts @@ -27,8 +27,9 @@ export default ({ loadTestFile, getService }: FtrProviderContext): void => { // loadTestFile(require.resolve('./get_alert_by_id')); // loadTestFile(require.resolve('./update_alert')); // loadTestFile(require.resolve('./bulk_update_alerts')); - // loadTestFile(require.resolve('./find_alerts')); - // loadTestFile(require.resolve('./get_alerts_index')); + + loadTestFile(require.resolve('./get_alerts_index')); + loadTestFile(require.resolve('./find_alerts')); loadTestFile(require.resolve('./search_strategy')); }); }; diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts index a9969fd3bfd52..d248858f19f6d 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/get_alert_by_id.ts @@ -31,10 +31,9 @@ export default ({ getService }: FtrProviderContext) => { .get(`${getSpaceUrlPrefix(SPACE1)}${ALERTS_INDEX_URL}`) .set('kbn-xsrf', 'true') .expect(200); - const observabilityIndex = indexNames?.index_name?.find( - (indexName) => indexName === APM_ALERT_INDEX - ); - expect(observabilityIndex).to.eql(APM_ALERT_INDEX); // assert this here so we can use constants in the dynamically-defined test cases below + expect( + indexNames?.index_name?.filter((indexName) => indexName.startsWith(APM_ALERT_INDEX)).length + ).to.eql(1); // assert this here so we can use constants in the dynamically-defined test cases below }; const getSecuritySolutionIndexName = async (user: User) => { @@ -43,10 +42,11 @@ export default ({ getService }: FtrProviderContext) => { .get(`${getSpaceUrlPrefix(SPACE1)}${ALERTS_INDEX_URL}`) .set('kbn-xsrf', 'true') .expect(200); - const securitySolution = indexNames?.index_name?.find((indexName) => - indexName.startsWith(SECURITY_SOLUTION_ALERT_INDEX) - ); - expect(securitySolution).to.eql(`${SECURITY_SOLUTION_ALERT_INDEX}-${SPACE1}`); // assert this here so we can use constants in the dynamically-defined test cases below + expect( + indexNames?.index_name?.filter((indexName) => + indexName.startsWith(`${SECURITY_SOLUTION_ALERT_INDEX}-${SPACE1}`) + ).length + ).to.eql(1); // assert this here so we can use constants in the dynamically-defined test cases below }; describe('Alerts - GET - RBAC', () => { diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts index 5b5bc64a5a9bd..31c3cfdecb9ee 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/update_alert.ts @@ -31,10 +31,9 @@ export default ({ getService }: FtrProviderContext) => { .get(`${getSpaceUrlPrefix(SPACE1)}${ALERTS_INDEX_URL}`) .set('kbn-xsrf', 'true') .expect(200); - const observabilityIndex = indexNames?.index_name?.find( - (indexName) => indexName === APM_ALERT_INDEX - ); - expect(observabilityIndex).to.eql(APM_ALERT_INDEX); // assert this here so we can use constants in the dynamically-defined test cases below + expect( + indexNames?.index_name?.filter((indexName) => indexName.startsWith(APM_ALERT_INDEX)).length + ).to.eql(1); // assert this here so we can use constants in the dynamically-defined test cases below }; const getSecuritySolutionIndexName = async (user: User) => { @@ -43,10 +42,11 @@ export default ({ getService }: FtrProviderContext) => { .get(`${getSpaceUrlPrefix(SPACE1)}${ALERTS_INDEX_URL}`) .set('kbn-xsrf', 'true') .expect(200); - const securitySolution = indexNames?.index_name?.find((indexName) => - indexName.startsWith(SECURITY_SOLUTION_ALERT_INDEX) - ); - expect(securitySolution).to.eql(`${SECURITY_SOLUTION_ALERT_INDEX}-${SPACE1}`); // assert this here so we can use constants in the dynamically-defined test cases below + expect( + indexNames?.index_name?.filter((indexName) => + indexName.startsWith(`${SECURITY_SOLUTION_ALERT_INDEX}-${SPACE1}`) + ).length + ).to.eql(1); // assert this here so we can use constants in the dynamically-defined test cases below }; describe('Alert - Update - RBAC - spaces', () => { From 29705c01e4cca9ebd2b83ef1afd52546ddc198c6 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Wed, 4 May 2022 08:45:24 -0700 Subject: [PATCH 33/68] [Security Solution][Legacy Actions] - Update legacy action migration to account for more edge cases (#130511) ## Summary Updates the legacy actions migration code to account for edge cases we had not initially caught. Thanks to testing from some teammates, they reported seeing the following behavior: - Rules created pre 7.16 with no actions still create the legacy action sidecar (but not a `siem.notifications` legacy actions alert) which upon migration to 7.16+ was not being deleted - Rules created pre 7.16 with actions that run on every rule run create the legacy action sidecar(but not a `siem.notifications` legacy actions alert) which upon migration to 7.16+ was not being deleted - Rules created pre 7.16 with actions that were never enabled until 8.x did not have a `siem.notifications` legacy actions alert type created Because the legacy migration code relied on checking if a corresponding `siem.notifications` SO existed to kick off the necessary cleanup/migration, the above edge cases were not being caught. --- .../routes/__mocks__/request_responses.ts | 373 +++++- .../rules/add_prepackaged_rules_route.test.ts | 11 + .../routes/rules/delete_rules_route.test.ts | 13 + .../rules/patch_rules_bulk_route.test.ts | 14 + .../routes/rules/patch_rules_route.test.ts | 13 + .../rules/perform_bulk_action_route.test.ts | 23 +- .../rules/update_rules_bulk_route.test.ts | 15 + .../routes/rules/update_rules_route.test.ts | 13 + .../rules/update_prepacked_rules.test.ts | 14 +- .../lib/detection_engine/rules/utils.test.ts | 474 ++++++++ .../lib/detection_engine/rules/utils.ts | 126 +- .../security_and_spaces/tests/delete_rules.ts | 3 +- .../tests/delete_rules_bulk.ts | 7 +- .../security_and_spaces/tests/index.ts | 4 + .../tests/legacy_actions_migrations.ts | 322 +++++ .../get_legacy_action_notification_so.ts | 27 + ...et_legacy_action_notifications_so_by_id.ts | 29 + .../utils/get_legacy_actions_so_by_id.ts | 29 + .../utils/get_rule_so_by_id.ts | 27 + .../utils/get_slack_action.ts | 14 + .../utils/index.ts | 5 + .../legacy_actions/data.json | 1064 +++++++++++++++++ 22 files changed, 2584 insertions(+), 36 deletions(-) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/legacy_actions_migrations.ts create mode 100644 x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notification_so.ts create mode 100644 x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notifications_so_by_id.ts create mode 100644 x-pack/test/detection_engine_api_integration/utils/get_legacy_actions_so_by_id.ts create mode 100644 x-pack/test/detection_engine_api_integration/utils/get_rule_so_by_id.ts create mode 100644 x-pack/test/detection_engine_api_integration/utils/get_slack_action.ts create mode 100644 x-pack/test/functional/es_archives/security_solution/legacy_actions/data.json diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts index 8e2f0da4e65c9..e7f539d31ec0c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -9,7 +9,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { ruleTypeMappings } from '@kbn/securitysolution-rules'; -import { SavedObjectsFindResponse } from '@kbn/core/server'; +import { SavedObjectsFindResponse, SavedObjectsFindResult } from '@kbn/core/server'; import { ActionResult } from '@kbn/actions-plugin/server'; import { @@ -49,6 +49,8 @@ import { } from '../../../../../common/detection_engine/schemas/common'; // eslint-disable-next-line no-restricted-imports import type { LegacyRuleNotificationAlertType } from '../../notifications/legacy_types'; +// eslint-disable-next-line no-restricted-imports +import { LegacyIRuleActionsAttributes } from '../../rule_actions/legacy_types'; import { RuleExecutionSummariesByRuleId } from '../../rule_execution_log'; export const typicalSetStatusSignalByIdsPayload = (): SetSignalsStatusSchemaDecoded => ({ @@ -688,14 +690,20 @@ export const getSignalsMigrationStatusRequest = () => /** * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function */ -export const legacyGetNotificationResult = (): LegacyRuleNotificationAlertType => ({ - id: '200dbf2f-b269-4bf9-aa85-11ba32ba73ba', +export const legacyGetNotificationResult = ({ + id = '456', + ruleId = '123', +}: { + id?: string; + ruleId?: string; +} = {}): LegacyRuleNotificationAlertType => ({ + id, name: 'Notification for Rule Test', tags: [], alertTypeId: 'siem.notifications', consumer: 'siem', params: { - ruleAlertId: '85b64e8a-2e40-4096-86af-5ac172c10825', + ruleAlertId: `${ruleId}`, }, schedule: { interval: '5m', @@ -732,10 +740,357 @@ export const legacyGetNotificationResult = (): LegacyRuleNotificationAlertType = /** * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function */ -export const legacyGetFindNotificationsResultWithSingleHit = - (): FindHit => ({ +export const legacyGetHourlyNotificationResult = ( + id = '456', + ruleId = '123' +): LegacyRuleNotificationAlertType => ({ + id, + name: 'Notification for Rule Test', + tags: [], + alertTypeId: 'siem.notifications', + consumer: 'siem', + params: { + ruleAlertId: `${ruleId}`, + }, + schedule: { + interval: '1h', + }, + enabled: true, + actions: [ + { + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + actionTypeId: '.email', + id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', + }, + ], + throttle: null, + notifyWhen: 'onActiveAlert', + apiKey: null, + apiKeyOwner: 'elastic', + createdBy: 'elastic', + updatedBy: 'elastic', + createdAt: new Date('2020-03-21T11:15:13.530Z'), + muteAll: false, + mutedInstanceIds: [], + scheduledTaskId: '62b3a130-6b70-11ea-9ce9-6b9818c4cbd7', + updatedAt: new Date('2020-03-21T12:37:08.730Z'), + executionStatus: { + status: 'unknown', + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + }, +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetDailyNotificationResult = ( + id = '456', + ruleId = '123' +): LegacyRuleNotificationAlertType => ({ + id, + name: 'Notification for Rule Test', + tags: [], + alertTypeId: 'siem.notifications', + consumer: 'siem', + params: { + ruleAlertId: `${ruleId}`, + }, + schedule: { + interval: '1d', + }, + enabled: true, + actions: [ + { + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + actionTypeId: '.email', + id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', + }, + ], + throttle: null, + notifyWhen: 'onActiveAlert', + apiKey: null, + apiKeyOwner: 'elastic', + createdBy: 'elastic', + updatedBy: 'elastic', + createdAt: new Date('2020-03-21T11:15:13.530Z'), + muteAll: false, + mutedInstanceIds: [], + scheduledTaskId: '62b3a130-6b70-11ea-9ce9-6b9818c4cbd7', + updatedAt: new Date('2020-03-21T12:37:08.730Z'), + executionStatus: { + status: 'unknown', + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + }, +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetWeeklyNotificationResult = ( + id = '456', + ruleId = '123' +): LegacyRuleNotificationAlertType => ({ + id, + name: 'Notification for Rule Test', + tags: [], + alertTypeId: 'siem.notifications', + consumer: 'siem', + params: { + ruleAlertId: `${ruleId}`, + }, + schedule: { + interval: '7d', + }, + enabled: true, + actions: [ + { + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + actionTypeId: '.email', + id: '99403909-ca9b-49ba-9d7a-7e5320e68d05', + }, + ], + throttle: null, + notifyWhen: 'onActiveAlert', + apiKey: null, + apiKeyOwner: 'elastic', + createdBy: 'elastic', + updatedBy: 'elastic', + createdAt: new Date('2020-03-21T11:15:13.530Z'), + muteAll: false, + mutedInstanceIds: [], + scheduledTaskId: '62b3a130-6b70-11ea-9ce9-6b9818c4cbd7', + updatedAt: new Date('2020-03-21T12:37:08.730Z'), + executionStatus: { + status: 'unknown', + lastExecutionDate: new Date('2020-08-20T19:23:38Z'), + }, +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetFindNotificationsResultWithSingleHit = ( + ruleId = '123' +): FindHit => ({ + page: 1, + perPage: 1, + total: 1, + data: [legacyGetNotificationResult({ ruleId })], +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetSiemNotificationRuleNoActionsSOResult = ( + ruleId = '123' +): SavedObjectsFindResult => ({ + type: 'siem-detection-engine-rule-actions', + id: 'ID_OF_LEGACY_SIDECAR_NO_ACTIONS', + namespaces: ['default'], + attributes: { + actions: [], + ruleThrottle: 'no_actions', + alertThrottle: null, + }, + references: [{ id: ruleId, type: 'alert', name: 'alert_0' }], + migrationVersion: { + 'siem-detection-engine-rule-actions': '7.11.2', + }, + coreMigrationVersion: '7.15.2', + updated_at: '2022-03-31T19:06:40.473Z', + version: 'WzIzNywxXQ==', + score: 0, +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetSiemNotificationRuleEveryRunSOResult = ( + ruleId = '123' +): SavedObjectsFindResult => ({ + type: 'siem-detection-engine-rule-actions', + id: 'ID_OF_LEGACY_SIDECAR_RULE_RUN_ACTIONS', + namespaces: ['default'], + attributes: { + actions: [ + { + group: 'default', + actionRef: 'action_0', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + action_type_id: '.email', + }, + ], + ruleThrottle: 'rule', + alertThrottle: null, + }, + references: [{ id: ruleId, type: 'alert', name: 'alert_0' }], + migrationVersion: { + 'siem-detection-engine-rule-actions': '7.11.2', + }, + coreMigrationVersion: '7.15.2', + updated_at: '2022-03-31T19:06:40.473Z', + version: 'WzIzNywxXQ==', + score: 0, +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetSiemNotificationRuleHourlyActionsSOResult = ( + ruleId = '123', + connectorId = '456' +): SavedObjectsFindResult => ({ + type: 'siem-detection-engine-rule-actions', + id: 'ID_OF_LEGACY_SIDECAR_HOURLY_ACTIONS', + namespaces: ['default'], + attributes: { + actions: [ + { + group: 'default', + actionRef: 'action_0', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + action_type_id: '.email', + }, + ], + ruleThrottle: '1h', + alertThrottle: '1h', + }, + references: [ + { id: ruleId, type: 'alert', name: 'alert_0' }, + { id: connectorId, type: 'action', name: 'action_0' }, + ], + migrationVersion: { + 'siem-detection-engine-rule-actions': '7.11.2', + }, + coreMigrationVersion: '7.15.2', + updated_at: '2022-03-31T19:06:40.473Z', + version: 'WzIzNywxXQ==', + score: 0, +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetSiemNotificationRuleDailyActionsSOResult = ( + ruleId = '123', + connectorId = '456' +): SavedObjectsFindResult => ({ + type: 'siem-detection-engine-rule-actions', + id: 'ID_OF_LEGACY_SIDECAR_DAILY_ACTIONS', + namespaces: ['default'], + attributes: { + actions: [ + { + group: 'default', + actionRef: 'action_0', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + action_type_id: '.email', + }, + ], + ruleThrottle: '1d', + alertThrottle: '1d', + }, + references: [ + { id: ruleId, type: 'alert', name: 'alert_0' }, + { id: connectorId, type: 'action', name: 'action_0' }, + ], + migrationVersion: { + 'siem-detection-engine-rule-actions': '7.11.2', + }, + coreMigrationVersion: '7.15.2', + updated_at: '2022-03-31T19:06:40.473Z', + version: 'WzIzNywxXQ==', + score: 0, +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetSiemNotificationRuleWeeklyActionsSOResult = ( + ruleId = '123', + connectorId = '456' +): SavedObjectsFindResult => ({ + type: 'siem-detection-engine-rule-actions', + id: 'ID_OF_LEGACY_SIDECAR_WEEKLY_ACTIONS', + namespaces: ['default'], + attributes: { + actions: [ + { + group: 'default', + actionRef: 'action_0', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + action_type_id: '.email', + }, + ], + ruleThrottle: '7d', + alertThrottle: '7d', + }, + references: [ + { id: ruleId, type: 'alert', name: 'alert_0' }, + { id: connectorId, type: 'action', name: 'action_0' }, + ], + migrationVersion: { + 'siem-detection-engine-rule-actions': '7.11.2', + }, + coreMigrationVersion: '7.15.2', + updated_at: '2022-03-31T19:06:40.473Z', + version: 'WzIzNywxXQ==', + score: 0, +}); + +const getLegacyActionSOs = (ruleId = '123', connectorId = '456') => ({ + none: () => legacyGetSiemNotificationRuleNoActionsSOResult(ruleId), + rule: () => legacyGetSiemNotificationRuleEveryRunSOResult(ruleId), + hourly: () => legacyGetSiemNotificationRuleHourlyActionsSOResult(ruleId, connectorId), + daily: () => legacyGetSiemNotificationRuleDailyActionsSOResult(ruleId, connectorId), + weekly: () => legacyGetSiemNotificationRuleWeeklyActionsSOResult(ruleId, connectorId), +}); + +/** + * @deprecated Once we are confident all rules relying on side-car actions SO's have been migrated to SO references we should remove this function + */ +export const legacyGetSiemNotificationRuleActionsSOResultWithSingleHit = ( + actionTypes: Array<'none' | 'rule' | 'daily' | 'hourly' | 'weekly'>, + ruleId = '123', + connectorId = '456' +): SavedObjectsFindResponse => { + const actions = getLegacyActionSOs(ruleId, connectorId); + + return { page: 1, - perPage: 1, + per_page: 1, total: 1, - data: [legacyGetNotificationResult()], - }); + saved_objects: actionTypes.map((type) => actions[type]()), + }; +}; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts index 327b8afb46b5d..8db750ba220af 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts @@ -21,6 +21,15 @@ import { installPrepackagedTimelines } from '../../../timeline/routes/prepackage // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from '@kbn/core/server/elasticsearch/client/mocks'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import { legacyMigrate } from '../../rules/utils'; + +jest.mock('../../rules/utils', () => { + const actual = jest.requireActual('../../rules/utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); jest.mock('../../rules/get_prepackaged_rules', () => { return { @@ -92,6 +101,8 @@ describe('add_prepackaged_rules_route', () => { errors: [], }); + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); + context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise(getBasicEmptySearchResponse()) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts index 83a40005d0148..85c324008856c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts @@ -13,10 +13,20 @@ import { getFindResultWithSingleHit, getDeleteRequestById, getEmptySavedObjectsResponse, + getRuleMock, } from '../__mocks__/request_responses'; import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { deleteRulesRoute } from './delete_rules_route'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import { legacyMigrate } from '../../rules/utils'; + +jest.mock('../../rules/utils', () => { + const actual = jest.requireActual('../../rules/utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); describe('delete_rules', () => { let server: ReturnType; @@ -29,6 +39,8 @@ describe('delete_rules', () => { clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); clients.savedObjectsClient.find.mockResolvedValue(getEmptySavedObjectsResponse()); + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); + deleteRulesRoute(server.router); }); @@ -54,6 +66,7 @@ describe('delete_rules', () => { test('returns 404 when deleting a single rule that does not exist with a valid actionClient and alertClient', async () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); + (legacyMigrate as jest.Mock).mockResolvedValue(null); const response = await server.inject( getDeleteRequest(), requestContextMock.convertContext(context) diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts index 6abac6e946380..fa75be49a61c5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts @@ -23,9 +23,18 @@ import { patchRulesBulkRoute } from './patch_rules_bulk_route'; import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/rule_schemas.mock'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; import { loggingSystemMock } from '@kbn/core/server/mocks'; +import { legacyMigrate } from '../../rules/utils'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); +jest.mock('../../rules/utils', () => { + const actual = jest.requireActual('../../rules/utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); + describe('patch_rules_bulk', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -40,6 +49,8 @@ describe('patch_rules_bulk', () => { clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); // rule exists clients.rulesClient.update.mockResolvedValue(getRuleMock(getQueryRuleParams())); // update succeeds + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); + patchRulesBulkRoute(server.router, ml, logger); }); @@ -54,6 +65,7 @@ describe('patch_rules_bulk', () => { test('returns an error in the response when updating a single rule that does not exist', async () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); + (legacyMigrate as jest.Mock).mockResolvedValue(null); const response = await server.inject( getPatchBulkRequest(), requestContextMock.convertContext(context) @@ -148,6 +160,8 @@ describe('patch_rules_bulk', () => { describe('request validation', () => { test('rejects payloads with no ID', async () => { + (legacyMigrate as jest.Mock).mockResolvedValue(null); + const request = requestMock.create({ method: 'patch', path: DETECTION_ENGINE_RULES_BULK_UPDATE, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts index cbcf5540b4f15..87c2e79922457 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts @@ -21,9 +21,18 @@ import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { patchRulesRoute } from './patch_rules_route'; import { getPatchRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/patch_rules_schema.mock'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import { legacyMigrate } from '../../rules/utils'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); +jest.mock('../../rules/utils', () => { + const actual = jest.requireActual('../../rules/utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); + describe('patch_rules', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -41,6 +50,8 @@ describe('patch_rules', () => { getRuleExecutionSummarySucceeded() ); + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); + patchRulesRoute(server.router, ml); }); @@ -55,6 +66,7 @@ describe('patch_rules', () => { test('returns 404 when updating a single rule that does not exist', async () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); + (legacyMigrate as jest.Mock).mockResolvedValue(null); const response = await server.inject( getPatchRequest(), requestContextMock.convertContext(context) @@ -67,6 +79,7 @@ describe('patch_rules', () => { }); test('returns error if requesting a non-rule', async () => { + (legacyMigrate as jest.Mock).mockResolvedValue(null); clients.rulesClient.find.mockResolvedValue(nonRuleFindResult()); const response = await server.inject( getPatchRequest(), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts index 3dc8ab5199c7f..4c50ee58e2d7f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts @@ -14,6 +14,7 @@ import { getBulkActionEditRequest, getFindResultWithSingleHit, getFindResultWithMultiHits, + getRuleMock, } from '../__mocks__/request_responses'; import { requestContextMock, serverMock, requestMock } from '../__mocks__'; import { performBulkActionRoute } from './perform_bulk_action_route'; @@ -23,10 +24,20 @@ import { } from '../../../../../common/detection_engine/schemas/request/perform_bulk_action_schema.mock'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { readRules } from '../../rules/read_rules'; +import { legacyMigrate } from '../../rules/utils'; +import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); jest.mock('../../rules/read_rules', () => ({ readRules: jest.fn() })); +jest.mock('../../rules/utils', () => { + const actual = jest.requireActual('../../rules/utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); + describe('perform_bulk_action', () => { const readRulesMock = readRules as jest.Mock; let server: ReturnType; @@ -40,6 +51,8 @@ describe('perform_bulk_action', () => { logger = loggingSystemMock.createLogger(); ({ clients, context } = requestContextMock.createTools()); ml = mlServicesMock.createSetupContract(); + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); + clients.rulesClient.find.mockResolvedValue(getFindResultWithSingleHit()); performBulkActionRoute(server.router, ml, logger); }); @@ -220,7 +233,10 @@ describe('perform_bulk_action', () => { readRulesMock.mockImplementationOnce(() => Promise.resolve({ ...mockRule, params: { ...mockRule.params, type: 'machine_learning' } }) ); - + (legacyMigrate as jest.Mock).mockResolvedValue({ + ...mockRule, + params: { ...mockRule.params, type: 'machine_learning' }, + }); const request = requestMock.create({ method: 'patch', path: DETECTION_ENGINE_RULES_BULK_ACTION, @@ -271,7 +287,10 @@ describe('perform_bulk_action', () => { readRulesMock.mockImplementationOnce(() => Promise.resolve({ ...mockRule, params: { ...mockRule.params, index: ['index-*'] } }) ); - + (legacyMigrate as jest.Mock).mockResolvedValue({ + ...mockRule, + params: { ...mockRule.params, index: ['index-*'] }, + }); const request = requestMock.create({ method: 'patch', path: DETECTION_ENGINE_RULES_BULK_ACTION, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts index 88720646fa6cd..e0c9289a562e7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts @@ -21,9 +21,18 @@ import { BulkError } from '../utils'; import { getCreateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/rule_schemas.mock'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; import { loggingSystemMock } from '@kbn/core/server/mocks'; +import { legacyMigrate } from '../../rules/utils'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); +jest.mock('../../rules/utils', () => { + const actual = jest.requireActual('../../rules/utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); + describe('update_rules_bulk', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -40,6 +49,8 @@ describe('update_rules_bulk', () => { clients.appClient.getSignalsIndex.mockReturnValue('.siem-signals-test-index'); + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); + updateRulesBulkRoute(server.router, ml, logger); }); @@ -54,6 +65,8 @@ describe('update_rules_bulk', () => { test('returns 200 as a response when updating a single rule that does not exist', async () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); + (legacyMigrate as jest.Mock).mockResolvedValue(null); + const expected: BulkError[] = [ { error: { message: 'rule_id: "rule-1" not found', status_code: 404 }, @@ -116,6 +129,8 @@ describe('update_rules_bulk', () => { describe('request validation', () => { test('rejects payloads with no ID', async () => { + (legacyMigrate as jest.Mock).mockResolvedValue(null); + const noIdRequest = requestMock.create({ method: 'put', path: DETECTION_ENGINE_RULES_BULK_UPDATE, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index 39040f4c9c4fc..7f2d5c3bde7e0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -21,9 +21,18 @@ import { DETECTION_ENGINE_RULES_URL } from '../../../../../common/constants'; import { updateRulesRoute } from './update_rules_route'; import { getUpdateRulesSchemaMock } from '../../../../../common/detection_engine/schemas/request/rule_schemas.mock'; import { getQueryRuleParams } from '../../schemas/rule_schemas.mock'; +import { legacyMigrate } from '../../rules/utils'; jest.mock('../../../machine_learning/authz', () => mockMlAuthzFactory.create()); +jest.mock('../../rules/utils', () => { + const actual = jest.requireActual('../../rules/utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); + describe('update_rules', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); @@ -42,6 +51,8 @@ describe('update_rules', () => { ); clients.appClient.getSignalsIndex.mockReturnValue('.siem-signals-test-index'); + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); + updateRulesRoute(server.router, ml); }); @@ -56,6 +67,7 @@ describe('update_rules', () => { test('returns 404 when updating a single rule that does not exist', async () => { clients.rulesClient.find.mockResolvedValue(getEmptyFindResult()); + (legacyMigrate as jest.Mock).mockResolvedValue(null); const response = await server.inject( getUpdateRequest(), requestContextMock.convertContext(context) @@ -69,6 +81,7 @@ describe('update_rules', () => { }); test('returns error when updating non-rule', async () => { + (legacyMigrate as jest.Mock).mockResolvedValue(null); clients.rulesClient.find.mockResolvedValue(nonRuleFindResult()); const response = await server.inject( getUpdateRequest(), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts index 96fba6703a537..2a54ce1e976d4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/update_prepacked_rules.test.ts @@ -7,14 +7,24 @@ import { rulesClientMock } from '@kbn/alerting-plugin/server/mocks'; import { savedObjectsClientMock } from '@kbn/core/server/mocks'; -import { getFindResultWithSingleHit } from '../routes/__mocks__/request_responses'; +import { getRuleMock, getFindResultWithSingleHit } from '../routes/__mocks__/request_responses'; import { updatePrepackagedRules } from './update_prepacked_rules'; import { patchRules } from './patch_rules'; import { getAddPrepackagedRulesSchemaDecodedMock } from '../../../../common/detection_engine/schemas/request/add_prepackaged_rules_schema.mock'; import { ruleExecutionLogMock } from '../rule_execution_log/__mocks__'; +import { legacyMigrate } from './utils'; +import { getQueryRuleParams } from '../schemas/rule_schemas.mock'; jest.mock('./patch_rules'); +jest.mock('./utils', () => { + const actual = jest.requireActual('./utils'); + return { + ...actual, + legacyMigrate: jest.fn(), + }; +}); + describe('updatePrepackagedRules', () => { let rulesClient: ReturnType; let savedObjectsClient: ReturnType; @@ -24,6 +34,8 @@ describe('updatePrepackagedRules', () => { rulesClient = rulesClientMock.create(); savedObjectsClient = savedObjectsClientMock.create(); ruleExecutionLog = ruleExecutionLogMock.forRoutes.create(); + + (legacyMigrate as jest.Mock).mockResolvedValue(getRuleMock(getQueryRuleParams())); }); it('should omit actions and enabled when calling patchRules', async () => { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts index 5151a58d0d885..0952da3182e01 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.test.ts @@ -13,6 +13,8 @@ import { transformToAlertThrottle, transformFromAlertThrottle, transformActions, + legacyMigrate, + getUpdatedActionsParams, } from './utils'; import { RuleAction, SanitizedRule } from '@kbn/alerting-plugin/common'; import { RuleParams } from '../schemas/rule_schemas'; @@ -23,6 +25,67 @@ import { import { FullResponseSchema } from '../../../../common/detection_engine/schemas/request'; // eslint-disable-next-line no-restricted-imports import { LegacyRuleActions } from '../rule_actions/legacy_types'; +import { + getEmptyFindResult, + legacyGetSiemNotificationRuleActionsSOResultWithSingleHit, + legacyGetDailyNotificationResult, + legacyGetHourlyNotificationResult, + legacyGetWeeklyNotificationResult, +} from '../routes/__mocks__/request_responses'; +import { requestContextMock } from '../routes/__mocks__'; + +const getRuleLegacyActions = (): SanitizedRule => + ({ + id: '123', + notifyWhen: 'onThrottleInterval', + name: 'Simple Rule Query', + tags: ['__internal_rule_id:ruleId', '__internal_immutable:false'], + alertTypeId: 'siem.queryRule', + consumer: 'siem', + enabled: true, + throttle: '1h', + apiKeyOwner: 'elastic', + createdBy: 'elastic', + updatedBy: 'elastic', + muteAll: false, + mutedInstanceIds: [], + monitoring: { execution: { history: [], calculated_metrics: { success_ratio: 0 } } }, + mapped_params: { risk_score: 1, severity: '60-high' }, + schedule: { interval: '5m' }, + actions: [], + params: { + author: [], + description: 'Simple Rule Query', + ruleId: 'ruleId', + falsePositives: [], + from: 'now-6m', + immutable: false, + outputIndex: '.siem-signals-default', + maxSignals: 100, + riskScore: 1, + riskScoreMapping: [], + severity: 'high', + severityMapping: [], + threat: [], + to: 'now', + references: [], + version: 1, + exceptionsList: [], + type: 'query', + language: 'kuery', + index: ['auditbeat-*'], + query: 'user.name: root or user.name: admin', + }, + snoozeEndTime: null, + updatedAt: '2022-03-31T21:47:25.695Z', + createdAt: '2022-03-31T21:47:16.379Z', + scheduledTaskId: '21bb9b60-b13c-11ec-99d0-asdfasdfasf', + executionStatus: { + status: 'pending', + lastExecutionDate: '2022-03-31T21:47:25.695Z', + lastDuration: 0, + }, + } as unknown as SanitizedRule); describe('utils', () => { describe('#calculateInterval', () => { @@ -588,4 +651,415 @@ describe('utils', () => { ]); }); }); + + describe('#legacyMigrate', () => { + const ruleId = '123'; + const connectorId = '456'; + const { clients } = requestContextMock.createTools(); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + test('it does no cleanup or migration if no legacy reminants found', async () => { + clients.rulesClient.find.mockResolvedValueOnce(getEmptyFindResult()); + clients.savedObjectsClient.find.mockResolvedValueOnce({ + page: 0, + per_page: 0, + total: 0, + saved_objects: [], + }); + + const rule = { + ...getRuleLegacyActions(), + id: ruleId, + actions: [], + throttle: null, + notifyWhen: 'onActiveAlert', + muteAll: true, + } as SanitizedRule; + + const migratedRule = await legacyMigrate({ + rulesClient: clients.rulesClient, + savedObjectsClient: clients.savedObjectsClient, + rule, + }); + + expect(clients.rulesClient.delete).not.toHaveBeenCalled(); + expect(clients.savedObjectsClient.delete).not.toHaveBeenCalled(); + expect(migratedRule).toEqual(rule); + }); + + // Even if a rule is created with no actions pre 7.16, a + // siem-detection-engine-rule-actions SO is still created + test('it migrates a rule with no actions', async () => { + // siem.notifications is not created for a rule with no actions + clients.rulesClient.find.mockResolvedValueOnce(getEmptyFindResult()); + // siem-detection-engine-rule-actions SO is still created + clients.savedObjectsClient.find.mockResolvedValueOnce( + legacyGetSiemNotificationRuleActionsSOResultWithSingleHit(['none'], ruleId, connectorId) + ); + + const migratedRule = await legacyMigrate({ + rulesClient: clients.rulesClient, + savedObjectsClient: clients.savedObjectsClient, + rule: { + ...getRuleLegacyActions(), + id: ruleId, + actions: [], + throttle: null, + notifyWhen: 'onActiveAlert', + muteAll: true, + }, + }); + + expect(clients.rulesClient.delete).not.toHaveBeenCalled(); + expect(clients.savedObjectsClient.delete).toHaveBeenCalledWith( + 'siem-detection-engine-rule-actions', + 'ID_OF_LEGACY_SIDECAR_NO_ACTIONS' + ); + expect(migratedRule?.actions).toEqual([]); + expect(migratedRule?.throttle).toBeNull(); + expect(migratedRule?.muteAll).toBeTruthy(); + expect(migratedRule?.notifyWhen).toEqual('onActiveAlert'); + }); + + test('it migrates a rule with every rule run action', async () => { + // siem.notifications is not created for a rule with actions run every rule run + clients.rulesClient.find.mockResolvedValueOnce(getEmptyFindResult()); + // siem-detection-engine-rule-actions SO is still created + clients.savedObjectsClient.find.mockResolvedValueOnce( + legacyGetSiemNotificationRuleActionsSOResultWithSingleHit(['rule'], ruleId, connectorId) + ); + + const migratedRule = await legacyMigrate({ + rulesClient: clients.rulesClient, + savedObjectsClient: clients.savedObjectsClient, + rule: { + ...getRuleLegacyActions(), + id: ruleId, + actions: [ + { + actionTypeId: '.email', + params: { + subject: 'Test Actions', + to: ['test@test.com'], + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + }, + id: connectorId, + group: 'default', + }, + ], + throttle: null, + notifyWhen: 'onActiveAlert', + muteAll: false, + }, + }); + + expect(clients.rulesClient.delete).not.toHaveBeenCalled(); + expect(clients.savedObjectsClient.delete).toHaveBeenCalledWith( + 'siem-detection-engine-rule-actions', + 'ID_OF_LEGACY_SIDECAR_RULE_RUN_ACTIONS' + ); + expect(migratedRule?.actions).toEqual([ + { + id: connectorId, + actionTypeId: '.email', + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + subject: 'Test Actions', + to: ['test@test.com'], + }, + }, + ]); + expect(migratedRule?.notifyWhen).toEqual('onActiveAlert'); + expect(migratedRule?.throttle).toBeNull(); + expect(migratedRule?.muteAll).toBeFalsy(); + }); + + test('it migrates a rule with daily legacy actions', async () => { + // siem.notifications is not created for a rule with no actions + clients.rulesClient.find.mockResolvedValueOnce({ + page: 1, + perPage: 1, + total: 1, + data: [legacyGetDailyNotificationResult(connectorId, ruleId)], + }); + // siem-detection-engine-rule-actions SO is still created + clients.savedObjectsClient.find.mockResolvedValueOnce( + legacyGetSiemNotificationRuleActionsSOResultWithSingleHit(['daily'], ruleId, connectorId) + ); + + const migratedRule = await legacyMigrate({ + rulesClient: clients.rulesClient, + savedObjectsClient: clients.savedObjectsClient, + rule: { + ...getRuleLegacyActions(), + id: ruleId, + actions: [], + throttle: null, + notifyWhen: 'onActiveAlert', + }, + }); + + expect(clients.rulesClient.delete).toHaveBeenCalledWith({ id: '456' }); + expect(clients.savedObjectsClient.delete).toHaveBeenCalledWith( + 'siem-detection-engine-rule-actions', + 'ID_OF_LEGACY_SIDECAR_DAILY_ACTIONS' + ); + expect(migratedRule?.actions).toEqual([ + { + actionTypeId: '.email', + group: 'default', + id: connectorId, + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + }, + ]); + expect(migratedRule?.throttle).toEqual('1d'); + expect(migratedRule?.notifyWhen).toEqual('onThrottleInterval'); + expect(migratedRule?.muteAll).toBeFalsy(); + }); + + test('it migrates a rule with hourly legacy actions', async () => { + // siem.notifications is not created for a rule with no actions + clients.rulesClient.find.mockResolvedValueOnce({ + page: 1, + perPage: 1, + total: 1, + data: [legacyGetHourlyNotificationResult(connectorId, ruleId)], + }); + // siem-detection-engine-rule-actions SO is still created + clients.savedObjectsClient.find.mockResolvedValueOnce( + legacyGetSiemNotificationRuleActionsSOResultWithSingleHit(['hourly'], ruleId, connectorId) + ); + + const migratedRule = await legacyMigrate({ + rulesClient: clients.rulesClient, + savedObjectsClient: clients.savedObjectsClient, + rule: { + ...getRuleLegacyActions(), + id: ruleId, + actions: [], + throttle: null, + notifyWhen: 'onActiveAlert', + }, + }); + + expect(clients.rulesClient.delete).toHaveBeenCalledWith({ id: '456' }); + expect(clients.savedObjectsClient.delete).toHaveBeenCalledWith( + 'siem-detection-engine-rule-actions', + 'ID_OF_LEGACY_SIDECAR_HOURLY_ACTIONS' + ); + expect(migratedRule?.actions).toEqual([ + { + actionTypeId: '.email', + group: 'default', + id: connectorId, + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + }, + ]); + expect(migratedRule?.throttle).toEqual('1h'); + expect(migratedRule?.notifyWhen).toEqual('onThrottleInterval'); + expect(migratedRule?.muteAll).toBeFalsy(); + }); + + test('it migrates a rule with weekly legacy actions', async () => { + // siem.notifications is not created for a rule with no actions + clients.rulesClient.find.mockResolvedValueOnce({ + page: 1, + perPage: 1, + total: 1, + data: [legacyGetWeeklyNotificationResult(connectorId, ruleId)], + }); + // siem-detection-engine-rule-actions SO is still created + clients.savedObjectsClient.find.mockResolvedValueOnce( + legacyGetSiemNotificationRuleActionsSOResultWithSingleHit(['weekly'], ruleId, connectorId) + ); + + const migratedRule = await legacyMigrate({ + rulesClient: clients.rulesClient, + savedObjectsClient: clients.savedObjectsClient, + rule: { + ...getRuleLegacyActions(), + id: ruleId, + actions: [], + throttle: null, + notifyWhen: 'onActiveAlert', + }, + }); + + expect(clients.rulesClient.delete).toHaveBeenCalledWith({ id: '456' }); + expect(clients.savedObjectsClient.delete).toHaveBeenCalledWith( + 'siem-detection-engine-rule-actions', + 'ID_OF_LEGACY_SIDECAR_WEEKLY_ACTIONS' + ); + expect(migratedRule?.actions).toEqual([ + { + actionTypeId: '.email', + group: 'default', + id: connectorId, + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Test Actions', + }, + }, + ]); + expect(migratedRule?.throttle).toEqual('7d'); + expect(migratedRule?.notifyWhen).toEqual('onThrottleInterval'); + expect(migratedRule?.muteAll).toBeFalsy(); + }); + }); + + describe('#getUpdatedActionsParams', () => { + it('updates one action', () => { + const { id, ...rule } = { + ...getRuleLegacyActions(), + id: '123', + actions: [], + throttle: null, + notifyWhen: 'onActiveAlert', + } as SanitizedRule; + + expect( + getUpdatedActionsParams({ + rule: { + ...rule, + id, + }, + ruleThrottle: '1h', + actions: [ + { + actionRef: 'action_0', + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['a@a.com'], + subject: 'Test Actions', + }, + action_type_id: '.email', + }, + ], + references: [ + { + id: '61ec7a40-b076-11ec-bb3f-1f063f8e06cf', + type: 'alert', + name: 'alert_0', + }, + { + id: '1234', + type: 'action', + name: 'action_0', + }, + ], + }) + ).toEqual({ + ...rule, + actions: [ + { + actionTypeId: '.email', + group: 'default', + id: '1234', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + subject: 'Test Actions', + to: ['a@a.com'], + }, + }, + ], + throttle: '1h', + notifyWhen: 'onThrottleInterval', + }); + }); + + it('updates multiple actions', () => { + const { id, ...rule } = { + ...getRuleLegacyActions(), + id: '123', + actions: [], + throttle: null, + notifyWhen: 'onActiveAlert', + } as SanitizedRule; + + expect( + getUpdatedActionsParams({ + rule: { + ...rule, + id, + }, + ruleThrottle: '1h', + actions: [ + { + actionRef: 'action_0', + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + to: ['test@test.com'], + subject: 'Rule email', + }, + action_type_id: '.email', + }, + { + actionRef: 'action_1', + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + }, + action_type_id: '.slack', + }, + ], + references: [ + { + id: '064e3160-b076-11ec-bb3f-1f063f8e06cf', + type: 'alert', + name: 'alert_0', + }, + { + id: 'c95cb100-b075-11ec-bb3f-1f063f8e06cf', + type: 'action', + name: 'action_0', + }, + { + id: '207fa0e0-c04e-11ec-8a52-4fb92379525a', + type: 'action', + name: 'action_1', + }, + ], + }) + ).toEqual({ + ...rule, + actions: [ + { + actionTypeId: '.email', + group: 'default', + id: 'c95cb100-b075-11ec-bb3f-1f063f8e06cf', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + subject: 'Rule email', + to: ['test@test.com'], + }, + }, + { + actionTypeId: '.slack', + group: 'default', + id: '207fa0e0-c04e-11ec-8a52-4fb92379525a', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + }, + }, + ], + throttle: '1h', + notifyWhen: 'onThrottleInterval', + }); + }); + }); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts index c7858a131cb1f..dd25676a758e4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/utils.ts @@ -28,6 +28,7 @@ import type { } from '@kbn/securitysolution-io-ts-alerting-types'; import type { ListArrayOrUndefined } from '@kbn/securitysolution-io-ts-list-types'; import type { VersionOrUndefined } from '@kbn/securitysolution-io-ts-types'; +import { SavedObjectReference } from '@kbn/core/server'; import { RuleAction, RuleNotifyWhenType, SanitizedRule } from '@kbn/alerting-plugin/common'; import { RulesClient } from '@kbn/alerting-plugin/server'; import { @@ -63,7 +64,11 @@ import { NOTIFICATION_THROTTLE_RULE, } from '../../../../common/constants'; // eslint-disable-next-line no-restricted-imports -import { LegacyRuleActions } from '../rule_actions/legacy_types'; +import { + LegacyIRuleActionsAttributes, + LegacyRuleActions, + LegacyRuleAlertSavedObjectAction, +} from '../rule_actions/legacy_types'; import { FullResponseSchema } from '../../../../common/detection_engine/schemas/request'; import { transformAlertToRuleAction } from '../../../../common/detection_engine/transform_actions'; // eslint-disable-next-line no-restricted-imports @@ -302,6 +307,59 @@ export const maybeMute = async ({ } }; +/** + * Translate legacy action sidecar action to rule action + */ +export const getUpdatedActionsParams = ({ + rule, + ruleThrottle, + actions, + references, +}: { + rule: SanitizedRule; + ruleThrottle: string | null; + actions: LegacyRuleAlertSavedObjectAction[]; + references: SavedObjectReference[]; +}): Omit, 'id'> => { + const { id, ...restOfRule } = rule; + + const actionReference = references.reduce>( + (acc, reference) => { + acc[reference.name] = reference; + return acc; + }, + {} + ); + + if (isEmpty(actionReference)) { + throw new Error( + `An error occurred migrating legacy action for rule with id:${id}. Connector reference id not found.` + ); + } + // If rule has an action on any other interval (other than on every + // rule run), need to move the action info from the sidecar/legacy action + // into the rule itself + return { + ...restOfRule, + actions: actions.reduce((acc, action) => { + const { actionRef, action_type_id: actionTypeId, ...resOfAction } = action; + if (!actionReference[actionRef]) { + return acc; + } + return [ + ...acc, + { + ...resOfAction, + id: actionReference[actionRef].id, + actionTypeId, + }, + ]; + }, []), + throttle: transformToAlertThrottle(ruleThrottle), + notifyWhen: transformToNotifyWhen(ruleThrottle), + }; +}; + /** * Determines if rule needs to be migrated from legacy actions * and returns necessary pieces for the updated rule @@ -332,7 +390,7 @@ export const legacyMigrate = async ({ }, }, }), - savedObjectsClient.find({ + savedObjectsClient.find({ type: legacyRuleActionsSavedObjectType, hasReference: { type: 'alert', @@ -341,29 +399,57 @@ export const legacyMigrate = async ({ }), ]); - if (siemNotification != null && siemNotification.data.length > 0) { - await Promise.all([ - rulesClient.delete({ id: siemNotification.data[0].id }), - legacyRuleActionsSO != null && legacyRuleActionsSO.saved_objects.length > 0 - ? savedObjectsClient.delete( - legacyRuleActionsSavedObjectType, - legacyRuleActionsSO.saved_objects[0].id - ) - : null, - ]); + const siemNotificationsExist = siemNotification != null && siemNotification.data.length > 0; + const legacyRuleNotificationSOsExist = + legacyRuleActionsSO != null && legacyRuleActionsSO.saved_objects.length > 0; + + // Assumption: if no legacy sidecar SO or notification rule types exist + // that reference the rule in question, assume rule actions are not legacy + if (!siemNotificationsExist && !legacyRuleNotificationSOsExist) { + return rule; + } + // If the legacy notification rule type ("siem.notification") exist, + // migration and cleanup are needed + if (siemNotificationsExist) { + await rulesClient.delete({ id: siemNotification.data[0].id }); + } + // If legacy notification sidecar ("siem-detection-engine-rule-actions") + // exist, migration and cleanup are needed + if (legacyRuleNotificationSOsExist) { + // Delete the legacy sidecar SO + await savedObjectsClient.delete( + legacyRuleActionsSavedObjectType, + legacyRuleActionsSO.saved_objects[0].id + ); + + // If "siem-detection-engine-rule-actions" notes that `ruleThrottle` is + // "no_actions" or "rule", rule has no actions or rule is set to run + // action on every rule run. In these cases, sidecar deletion is the only + // cleanup needed and updates to the "throttle" and "notifyWhen". "siem.notification" are + // not created for these action types + if ( + legacyRuleActionsSO.saved_objects[0].attributes.ruleThrottle === 'no_actions' || + legacyRuleActionsSO.saved_objects[0].attributes.ruleThrottle === 'rule' + ) { + return rule; + } + + // Use "legacyRuleActionsSO" instead of "siemNotification" as "siemNotification" is not created + // until a rule is run and added to task manager. That means that if by chance a user has a rule + // with actions which they have yet to enable, the actions would be lost. Instead, + // "legacyRuleActionsSO" is created on rule creation (pre 7.15) and we can rely on it to be there + const migratedRule = getUpdatedActionsParams({ + rule, + ruleThrottle: legacyRuleActionsSO.saved_objects[0].attributes.ruleThrottle, + actions: legacyRuleActionsSO.saved_objects[0].attributes.actions, + references: legacyRuleActionsSO.saved_objects[0].references, + }); - const { id, ...restOfRule } = rule; - const migratedRule = { - ...restOfRule, - actions: siemNotification.data[0].actions, - throttle: siemNotification.data[0].schedule.interval, - notifyWhen: transformToNotifyWhen(siemNotification.data[0].throttle), - }; await rulesClient.update({ id: rule.id, data: migratedRule, }); + return { id: rule.id, ...migratedRule }; } - return rule; }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules.ts index 69cbd9fd4d4c7..f138bad4b9d2c 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules.ts @@ -20,6 +20,7 @@ import { getSimpleRuleOutput, getSimpleRuleOutputWithoutRuleId, getSimpleRuleWithoutRuleId, + getSlackAction, getWebHookAction, removeServerGeneratedProperties, removeServerGeneratedPropertiesIncludingRuleId, @@ -148,7 +149,7 @@ export default ({ getService }: FtrProviderContext): void => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') - .send(getWebHookAction()) + .send(getSlackAction()) .expect(200); // create a rule without actions diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts index 29f5d5edf49d9..d05dcb690994c 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts @@ -20,6 +20,7 @@ import { getSimpleRuleOutput, getSimpleRuleOutputWithoutRuleId, getSimpleRuleWithoutRuleId, + getSlackAction, getWebHookAction, removeServerGeneratedProperties, removeServerGeneratedPropertiesIncludingRuleId, @@ -277,7 +278,7 @@ export default ({ getService }: FtrProviderContext): void => { const { body: hookAction } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') - .send(getWebHookAction()) + .send(getSlackAction()) .expect(200); // create a rule without actions @@ -318,12 +319,12 @@ export default ({ getService }: FtrProviderContext): void => { const { body: hookAction1 } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') - .send(getWebHookAction()) + .send(getSlackAction()) .expect(200); const { body: hookAction2 } = await supertest .post('/api/actions/action') .set('kbn-xsrf', 'true') - .send(getWebHookAction()) + .send(getSlackAction()) .expect(200); // create 2 rules without actions diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts index a3c4dd8ed3be1..9a61569ada3b0 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts @@ -13,6 +13,9 @@ export default ({ loadTestFile }: FtrProviderContext): void => { describe('', function () { this.tags('ciGroup11'); + // !!NOTE: For new routes that do any updates on a rule, please ensure that you are including the legacy + // action migration code. We are monitoring legacy action telemetry to clean up once we see their + // existence being near 0. loadTestFile(require.resolve('./aliases')); loadTestFile(require.resolve('./add_actions')); loadTestFile(require.resolve('./update_actions')); @@ -33,6 +36,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./get_rule_execution_events')); loadTestFile(require.resolve('./import_rules')); loadTestFile(require.resolve('./import_export_rules')); + loadTestFile(require.resolve('./legacy_actions_migrations')); loadTestFile(require.resolve('./read_rules')); loadTestFile(require.resolve('./resolve_read_rules')); loadTestFile(require.resolve('./update_rules')); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/legacy_actions_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/legacy_actions_migrations.ts new file mode 100644 index 0000000000000..ad6e45954e06a --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/legacy_actions_migrations.ts @@ -0,0 +1,322 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; + +import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { + getLegacyActionSOById, + getLegacyActionNotificationSOById, + getRuleSOById, +} from '../../utils'; + +/** + * @deprecated Once the legacy notification system is removed, remove this test too. + */ +// eslint-disable-next-line import/no-default-export +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const es = getService('es'); + const esArchiver = getService('esArchiver'); + + // This test suite is not meant to test a specific route, but to test the legacy action migration + // code that lives in multiple routes. This code is also tested in each of the routes it lives in + // but not in as much detail and relying on mocks. This test loads an es_archive containing rules + // created in 7.15 with legacy actions. + // For new routes that do any updates on a rule, please ensure that you are including the legacy + // action migration code. We are monitoring legacy action telemetry to clean up once we see their + // existence being near 0. + describe('migrate_legacy_actions', () => { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/legacy_actions'); + }); + + after(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/legacy_actions' + ); + }); + + it('migrates legacy actions for rule with no actions', async () => { + const soId = '9095ee90-b075-11ec-bb3f-1f063f8e06cf'; + const ruleId = '2297be91-894c-4831-830f-b424a0ec84f0'; + const legacySidecarId = '926668d0-b075-11ec-bb3f-1f063f8e06cf'; + + // check for legacy sidecar action + const sidecarActionSO = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionSO.hits.hits.length).to.eql(1); + + // check for legacy notification SO + // should not have been created for a rule with no actions + const legacyNotificationSO = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSO.hits.hits.length).to.eql(0); + + // patch enable the rule + // any route that edits the rule should trigger the migration + await supertest + .patch(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .send({ rule_id: ruleId, enabled: false }) + .expect(200); + + const { + hits: { + hits: [{ _source: ruleSO }], + }, + } = await getRuleSOById(es, soId); + + // Sidecar should be removed + const sidecarActionsSOAfterMigration = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionsSOAfterMigration.hits.hits.length).to.eql(0); + + expect(ruleSO?.alert.actions).to.eql([]); + expect(ruleSO?.alert.throttle).to.eql(null); + expect(ruleSO?.alert.notifyWhen).to.eql('onActiveAlert'); + }); + + it('migrates legacy actions for rule with action run on every run', async () => { + const soId = 'dc6595f0-b075-11ec-bb3f-1f063f8e06cf'; + const ruleId = '72a0d429-363b-4f70-905e-c6019a224d40'; + const legacySidecarId = 'dde13970-b075-11ec-bb3f-1f063f8e06cf'; + + // check for legacy sidecar action + const sidecarActionSO = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionSO.hits.hits.length).to.eql(1); + + // check for legacy notification SO + // should not have been created for a rule that runs on every rule run + const legacyNotificationSO = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSO.hits.hits.length).to.eql(0); + + // patch enable the rule + // any route that edits the rule should trigger the migration + await supertest + .patch(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .send({ rule_id: ruleId, enabled: false }) + .expect(200); + + const { + hits: { + hits: [{ _source: ruleSO }], + }, + } = await getRuleSOById(es, soId); + + // Sidecar should be removed + const sidecarActionsSOAfterMigration = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionsSOAfterMigration.hits.hits.length).to.eql(0); + + expect(ruleSO?.alert.actions).to.eql([ + { + actionRef: 'action_0', + actionTypeId: '.email', + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + subject: 'Test Actions', + to: ['test@test.com'], + }, + }, + ]); + expect(ruleSO?.alert.throttle).to.eql(null); + expect(ruleSO?.alert.notifyWhen).to.eql('onActiveAlert'); + expect(ruleSO?.references).to.eql([ + { + id: 'c95cb100-b075-11ec-bb3f-1f063f8e06cf', + name: 'action_0', + type: 'action', + }, + ]); + }); + + it('migrates legacy actions for rule with action run hourly', async () => { + const soId = '064e3160-b076-11ec-bb3f-1f063f8e06cf'; + const ruleId = '4c056b05-75ac-4209-be32-82100f771eb4'; + const legacySidecarId = '07aa8d10-b076-11ec-bb3f-1f063f8e06cf'; + + // check for legacy sidecar action + const sidecarActionSO = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionSO.hits.hits.length).to.eql(1); + + // check for legacy notification SO + const legacyNotificationSO = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSO.hits.hits.length).to.eql(1); + + // patch enable the rule + // any route that edits the rule should trigger the migration + await supertest + .patch(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .send({ rule_id: ruleId, enabled: false }) + .expect(200); + + const { + hits: { + hits: [{ _source: ruleSO }], + }, + } = await getRuleSOById(es, soId); + + // Sidecar should be removed + const sidecarActionsSOAfterMigration = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionsSOAfterMigration.hits.hits.length).to.eql(0); + + // Legacy notification should be removed + const legacyNotificationSOAfterMigration = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSOAfterMigration.hits.hits.length).to.eql(0); + + expect(ruleSO?.alert.actions).to.eql([ + { + actionTypeId: '.email', + params: { + subject: 'Rule email', + to: ['test@test.com'], + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + }, + actionRef: 'action_0', + group: 'default', + }, + { + actionTypeId: '.slack', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + }, + actionRef: 'action_1', + group: 'default', + }, + ]); + expect(ruleSO?.alert.throttle).to.eql('1h'); + expect(ruleSO?.alert.notifyWhen).to.eql('onThrottleInterval'); + expect(ruleSO?.references).to.eql([ + { + id: 'c95cb100-b075-11ec-bb3f-1f063f8e06cf', + name: 'action_0', + type: 'action', + }, + { + id: '207fa0e0-c04e-11ec-8a52-4fb92379525a', + name: 'action_1', + type: 'action', + }, + ]); + }); + + it('migrates legacy actions for rule with action run daily', async () => { + const soId = '27639570-b076-11ec-bb3f-1f063f8e06cf'; + const ruleId = '8e2c8550-f13f-4e21-be0c-92148d71a5f1'; + const legacySidecarId = '291ae260-b076-11ec-bb3f-1f063f8e06cf'; + + // check for legacy sidecar action + const sidecarActionSO = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionSO.hits.hits.length).to.eql(1); + + // check for legacy notification SO + const legacyNotificationSO = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSO.hits.hits.length).to.eql(1); + + // patch enable the rule + await supertest + .patch(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .send({ rule_id: ruleId, enabled: false }) + .expect(200); + + const { + hits: { + hits: [{ _source: ruleSO }], + }, + } = await getRuleSOById(es, soId); + + // Sidecar should be removed + const sidecarActionsSOAfterMigration = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionsSOAfterMigration.hits.hits.length).to.eql(0); + + // Legacy notification should be removed + const legacyNotificationSOAfterMigration = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSOAfterMigration.hits.hits.length).to.eql(0); + + expect(ruleSO?.alert.actions).to.eql([ + { + actionRef: 'action_0', + actionTypeId: '.email', + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + subject: 'Test Actions', + to: ['test@test.com'], + }, + }, + ]); + expect(ruleSO?.alert.throttle).to.eql('1d'); + expect(ruleSO?.alert.notifyWhen).to.eql('onThrottleInterval'); + expect(ruleSO?.references).to.eql([ + { + id: 'c95cb100-b075-11ec-bb3f-1f063f8e06cf', + name: 'action_0', + type: 'action', + }, + ]); + }); + + it('migrates legacy actions for rule with action run weekly', async () => { + const soId = '61ec7a40-b076-11ec-bb3f-1f063f8e06cf'; + const ruleId = '05fbdd2a-e802-420b-bdc3-95ae0acca454'; + const legacySidecarId = '63aa2fd0-b076-11ec-bb3f-1f063f8e06cf'; + + // check for legacy sidecar action + const sidecarActionSO = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionSO.hits.hits.length).to.eql(1); + + // check for legacy notification SO + const legacyNotificationSO = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSO.hits.hits.length).to.eql(1); + + // patch enable the rule + await supertest + .patch(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .send({ rule_id: ruleId, enabled: false }) + .expect(200); + + const { + hits: { + hits: [{ _source: ruleSO }], + }, + } = await getRuleSOById(es, soId); + + // Sidecar should be removed + const sidecarActionsSOAfterMigration = await getLegacyActionSOById(es, legacySidecarId); + expect(sidecarActionsSOAfterMigration.hits.hits.length).to.eql(0); + + // Legacy notification should be removed + const legacyNotificationSOAfterMigration = await getLegacyActionNotificationSOById(es, soId); + expect(legacyNotificationSOAfterMigration.hits.hits.length).to.eql(0); + + expect(ruleSO?.alert.actions).to.eql([ + { + actionRef: 'action_0', + actionTypeId: '.email', + group: 'default', + params: { + message: 'Rule {{context.rule.name}} generated {{state.signals_count}} alerts', + subject: 'Test Actions', + to: ['test@test.com'], + }, + }, + ]); + expect(ruleSO?.alert.throttle).to.eql('7d'); + expect(ruleSO?.alert.notifyWhen).to.eql('onThrottleInterval'); + expect(ruleSO?.references).to.eql([ + { + id: 'c95cb100-b075-11ec-bb3f-1f063f8e06cf', + name: 'action_0', + type: 'action', + }, + ]); + }); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notification_so.ts b/x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notification_so.ts new file mode 100644 index 0000000000000..9a084d800a2d8 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notification_so.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Client } from '@elastic/elasticsearch'; +import { SavedObjectReference } from '@kbn/core/server'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { LegacyRuleNotificationAlertTypeParams } from '@kbn/security-solution-plugin/server/lib/detection_engine/notifications/legacy_types'; + +interface LegacyActionNotificationSO extends LegacyRuleNotificationAlertTypeParams { + references: SavedObjectReference[]; +} + +/** + * Fetch all legacy action sidecar notification SOs from the .kibana index + * @param es The ElasticSearch service + */ +export const getLegacyActionNotificationSO = async ( + es: Client +): Promise> => + es.search({ + index: '.kibana', + q: 'alert.alertTypeId:siem.notifications', + }); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notifications_so_by_id.ts b/x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notifications_so_by_id.ts new file mode 100644 index 0000000000000..3120e85e899bf --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notifications_so_by_id.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Client } from '@elastic/elasticsearch'; +import { SavedObjectReference } from '@kbn/core/server'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { LegacyRuleNotificationAlertTypeParams } from '@kbn/security-solution-plugin/server/lib/detection_engine/notifications/legacy_types'; + +interface LegacyActionNotificationSO extends LegacyRuleNotificationAlertTypeParams { + references: SavedObjectReference[]; +} + +/** + * Fetch legacy action sidecar notification SOs from the .kibana index + * @param es The ElasticSearch service + * @param id SO id + */ +export const getLegacyActionNotificationSOById = async ( + es: Client, + id: string +): Promise> => + es.search({ + index: '.kibana', + q: `alert.alertTypeId:siem.notifications AND alert.params.ruleAlertId:"${id}"`, + }); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_legacy_actions_so_by_id.ts b/x-pack/test/detection_engine_api_integration/utils/get_legacy_actions_so_by_id.ts new file mode 100644 index 0000000000000..48ea142aa28ca --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/utils/get_legacy_actions_so_by_id.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Client } from '@elastic/elasticsearch'; +import { SavedObjectReference } from '@kbn/core/server'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { LegacyRuleActions } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_actions/legacy_types'; + +interface LegacyActionSO extends LegacyRuleActions { + references: SavedObjectReference[]; +} + +/** + * Fetch legacy action sidecar SOs from the .kibana index + * @param es The ElasticSearch service + * @param id SO id + */ +export const getLegacyActionSOById = async ( + es: Client, + id: string +): Promise> => + es.search({ + index: '.kibana', + q: `type:siem-detection-engine-rule-actions AND _id:"siem-detection-engine-rule-actions:${id}"`, + }); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_rule_so_by_id.ts b/x-pack/test/detection_engine_api_integration/utils/get_rule_so_by_id.ts new file mode 100644 index 0000000000000..5a46f96cc400a --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/utils/get_rule_so_by_id.ts @@ -0,0 +1,27 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Client } from '@elastic/elasticsearch'; +import { SavedObjectReference } from '@kbn/core/server'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { Rule } from '@kbn/alerting-plugin/common'; + +interface RuleSO { + alert: Rule; + references: SavedObjectReference[]; +} + +/** + * Fetch legacy action sidecar SOs from the .kibana index + * @param es The ElasticSearch service + * @param id SO id + */ +export const getRuleSOById = async (es: Client, id: string): Promise> => + es.search({ + index: '.kibana', + q: `type:alert AND _id:"alert:${id}"`, + }); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_slack_action.ts b/x-pack/test/detection_engine_api_integration/utils/get_slack_action.ts new file mode 100644 index 0000000000000..1d88f2cdbce73 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/utils/get_slack_action.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const getSlackAction = () => ({ + actionTypeId: '.slack', + secrets: { + webhookUrl: 'http://localhost:123', + }, + name: 'Slack connector', +}); diff --git a/x-pack/test/detection_engine_api_integration/utils/index.ts b/x-pack/test/detection_engine_api_integration/utils/index.ts index 3fb9c8ebafc02..81bad1b1b583b 100644 --- a/x-pack/test/detection_engine_api_integration/utils/index.ts +++ b/x-pack/test/detection_engine_api_integration/utils/index.ts @@ -35,7 +35,10 @@ export * from './get_detection_metrics_from_body'; export * from './get_eql_rule_for_signal_testing'; export * from './get_event_log_execute_complete_by_id'; export * from './get_index_name_from_load'; +export * from './get_legacy_action_notification_so'; +export * from './get_legacy_action_notifications_so_by_id'; export * from './get_legacy_action_so'; +export * from './get_legacy_actions_so_by_id'; export * from './get_open_signals'; export * from './get_prepackaged_rule_status'; export * from './get_query_all_signals'; @@ -44,6 +47,7 @@ export * from './get_query_signals_ids'; export * from './get_query_signals_rule_id'; export * from './get_rule'; export * from './get_rule_for_signal_testing'; +export * from './get_rule_so_by_id'; export * from './get_rule_for_signal_testing_with_timestamp_override'; export * from './get_rule_with_web_hook_action'; export * from './get_saved_query_rule_for_signal_testing'; @@ -70,6 +74,7 @@ export * from './get_stats'; export * from './get_stats_url'; export * from './get_threat_match_rule_for_signal_testing'; export * from './get_threshold_rule_for_signal_testing'; +export * from './get_slack_action'; export * from './get_web_hook_action'; export * from './index_event_log_execution_events'; export * from './install_prepackaged_rules'; diff --git a/x-pack/test/functional/es_archives/security_solution/legacy_actions/data.json b/x-pack/test/functional/es_archives/security_solution/legacy_actions/data.json new file mode 100644 index 0000000000000..25aa371e02144 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/legacy_actions/data.json @@ -0,0 +1,1064 @@ +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "action:c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "source" : { + "action" : { + "actionTypeId" : ".email", + "name" : "test", + "isMissingSecrets" : false, + "config" : { + "hasAuth" : true, + "from" : "a@a.com", + "host" : "gmail", + "port" : 56, + "service" : "other", + "secure" : null + }, + "secrets" : "jCv0fZczCM+rlWXIkI6Qo/ZqasgxPhplokCaNeXJrJlJYjKeCgbZgiLAEue4bpq4GUDohfye8o1BlJCQi+3HJPb2Qp6lhbcvXn+C6wUzxj9ZitwY8ZTDo34e22TX7qHFs/1mVfO4stjZ6X86ufRZttjTNu4qjchfi3Jao7nWbw==" + }, + "type" : "action", + "references" : [ ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "action" : "8.0.0" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:07:27.777Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "action:207fa0e0-c04e-11ec-8a52-4fb92379525a", + "source" : { + "action" : { + "actionTypeId" : ".slack", + "name" : "Slack connector", + "isMissingSecrets" : false, + "config" : { }, + "secrets" : "WTpvAWxAnR1yHdFqQrmGGeOmqGzeIDQnjGexz7F3JdFVEH0CJkPbiyEk9SiiBr1OPZ3s0LWqphjNREjyxSTCTuYTKaEIQ1+mJFQzjIulekMZklQdon7kNh4hOVHW832IX1Lpx9f5cgAPQst2bqJCehz+3BeZOh17Hgrvb/0zzKRCR4cvlhYbOUNUCNR/d6YoEniwUK8pO9xcel9hle7XY6MNfBGiMX8T41O87lvgp9xDjch3LpwqzDjUIFs=" + }, + "type" : "action", + "references" : [ ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "action" : "8.0.0" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:07:27.777Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:9095ee90-b075-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ no actions", + "tags" : [ + "__internal_rule_id:2297be91-894c-4831-830f-b424a0ec84f0", + "__internal_immutable:false", + "auto_disabled_8.0" + ], + "alertTypeId" : "siem.queryRule", + "consumer" : "siem", + "params" : { + "author" : [ ], + "description" : "a", + "ruleId" : "2297be91-894c-4831-830f-b424a0ec84f0", + "falsePositives" : [ ], + "from" : "now-360s", + "immutable" : false, + "license" : "", + "outputIndex" : "", + "meta" : { + "from" : "1m", + "kibana_siem_app_url" : "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals" : 100, + "riskScore" : 21, + "riskScoreMapping" : [ ], + "severity" : "low", + "severityMapping" : [ ], + "threat" : [ ], + "to" : "now", + "references" : [ ], + "version" : 1, + "exceptionsList" : [ ], + "type" : "query", + "language" : "kuery", + "index" : [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query" : "*:*", + "filters" : [ ] + }, + "schedule" : { + "interval" : "5m" + }, + "enabled" : true, + "actions" : [ ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:05:53.511Z", + "updatedAt" : "2022-03-30T22:05:53.511Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "ok", + "lastExecutionDate" : "2022-03-31T19:53:37.507Z", + "error" : null, + "lastDuration" : 2377 + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "scheduledTaskId" : null, + "legacyId" : "9095ee90-b075-11ec-bb3f-1f063f8e06cf" + }, + "type" : "alert", + "references" : [ ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-31T19:53:39.885Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:dc6595f0-b075-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ action - every rule run", + "tags" : [ + "__internal_rule_id:72a0d429-363b-4f70-905e-c6019a224d40", + "__internal_immutable:false", + "auto_disabled_8.0" + ], + "alertTypeId" : "siem.queryRule", + "consumer" : "siem", + "params" : { + "author" : [ ], + "description" : "a", + "ruleId" : "72a0d429-363b-4f70-905e-c6019a224d40", + "falsePositives" : [ ], + "from" : "now-360s", + "immutable" : false, + "license" : "", + "outputIndex" : "", + "meta" : { + "from" : "1m", + "kibana_siem_app_url" : "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals" : 100, + "riskScore" : 21, + "riskScoreMapping" : [ ], + "severity" : "low", + "severityMapping" : [ ], + "threat" : [ ], + "to" : "now", + "references" : [ ], + "version" : 1, + "exceptionsList" : [ ], + "type" : "query", + "language" : "kuery", + "index" : [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query" : "*:* ", + "filters" : [ ] + }, + "schedule" : { + "interval" : "5m" + }, + "enabled" : true, + "actions" : [ + { + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Test Actions" + }, + "actionTypeId" : ".email", + "actionRef" : "action_0" + } + ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:08:00.172Z", + "updatedAt" : "2022-03-30T22:08:00.172Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "ok", + "lastExecutionDate" : "2022-03-31T19:55:43.502Z", + "error" : null, + "lastDuration" : 2700 + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "scheduledTaskId" : null, + "legacyId" : "dc6595f0-b075-11ec-bb3f-1f063f8e06cf" + }, + "type" : "alert", + "references" : [ + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "name" : "action_0", + "type" : "action" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-31T19:55:46.202Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:064e3160-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ action - every hour", + "tags" : [ + "__internal_rule_id:4c056b05-75ac-4209-be32-82100f771eb4", + "__internal_immutable:false", + "auto_disabled_8.0" + ], + "alertTypeId" : "siem.queryRule", + "consumer" : "siem", + "params" : { + "author" : [ ], + "description" : "a", + "ruleId" : "4c056b05-75ac-4209-be32-82100f771eb4", + "falsePositives" : [ ], + "from" : "now-360s", + "immutable" : false, + "license" : "", + "outputIndex" : "", + "meta" : { + "from" : "1m", + "kibana_siem_app_url" : "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals" : 100, + "riskScore" : 21, + "riskScoreMapping" : [ ], + "severity" : "low", + "severityMapping" : [ ], + "threat" : [ ], + "to" : "now", + "references" : [ ], + "version" : 1, + "exceptionsList" : [ ], + "type" : "query", + "language" : "kuery", + "index" : [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query" : "*:*", + "filters" : [ ] + }, + "schedule" : { + "interval" : "5m" + }, + "enabled" : true, + "actions" : [ ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:09:10.261Z", + "updatedAt" : "2022-03-30T22:09:10.261Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "ok", + "lastExecutionDate" : "2022-03-31T19:56:43.499Z", + "error" : null, + "lastDuration" : 2815 + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "scheduledTaskId" : null, + "legacyId" : "064e3160-b076-11ec-bb3f-1f063f8e06cf" + }, + "type" : "alert", + "references" : [ ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-31T19:56:46.314Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:27639570-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ action - daily", + "tags" : [ + "__internal_rule_id:8e2c8550-f13f-4e21-be0c-92148d71a5f1", + "__internal_immutable:false", + "auto_disabled_8.0" + ], + "alertTypeId" : "siem.queryRule", + "consumer" : "siem", + "params" : { + "author" : [ ], + "description" : "a", + "ruleId" : "8e2c8550-f13f-4e21-be0c-92148d71a5f1", + "falsePositives" : [ ], + "from" : "now-360s", + "immutable" : false, + "license" : "", + "outputIndex" : "", + "meta" : { + "from" : "1m", + "kibana_siem_app_url" : "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals" : 100, + "riskScore" : 21, + "riskScoreMapping" : [ ], + "severity" : "low", + "severityMapping" : [ ], + "threat" : [ ], + "to" : "now", + "references" : [ ], + "version" : 1, + "exceptionsList" : [ ], + "type" : "query", + "language" : "kuery", + "index" : [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query" : "*:*", + "filters" : [ ] + }, + "schedule" : { + "interval" : "5m" + }, + "enabled" : true, + "actions" : [ ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:10:06.358Z", + "updatedAt" : "2022-03-30T22:10:06.358Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "ok", + "lastExecutionDate" : "2022-03-31T19:58:13.480Z", + "error" : null, + "lastDuration" : 3023 + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "scheduledTaskId" : null, + "legacyId" : "27639570-b076-11ec-bb3f-1f063f8e06cf" + }, + "type" : "alert", + "references" : [ ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-31T19:58:16.503Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:61ec7a40-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ actions - weekly", + "tags" : [ + "__internal_rule_id:05fbdd2a-e802-420b-bdc3-95ae0acca454", + "__internal_immutable:false", + "auto_disabled_8.0" + ], + "alertTypeId" : "siem.queryRule", + "consumer" : "siem", + "params" : { + "author" : [ ], + "description" : "a", + "ruleId" : "05fbdd2a-e802-420b-bdc3-95ae0acca454", + "falsePositives" : [ ], + "from" : "now-360s", + "immutable" : false, + "license" : "", + "outputIndex" : "", + "meta" : { + "from" : "1m", + "kibana_siem_app_url" : "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals" : 100, + "riskScore" : 21, + "riskScoreMapping" : [ ], + "severity" : "low", + "severityMapping" : [ ], + "threat" : [ ], + "to" : "now", + "references" : [ ], + "version" : 1, + "exceptionsList" : [ ], + "type" : "query", + "language" : "kuery", + "index" : [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query" : "*:*", + "filters" : [ ] + }, + "schedule" : { + "interval" : "5m" + }, + "enabled" : true, + "actions" : [ ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:11:44.516Z", + "updatedAt" : "2022-03-30T22:11:44.516Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "ok", + "lastExecutionDate" : "2022-03-31T19:54:22.442Z", + "error" : null, + "lastDuration" : 2612 + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "scheduledTaskId" : null, + "legacyId" : "61ec7a40-b076-11ec-bb3f-1f063f8e06cf" + }, + "type" : "alert", + "references" : [ ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-31T19:54:25.054Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:64492ef0-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ actions - weekly", + "tags" : [ + "__internal_rule_alert_id:61ec7a40-b076-11ec-bb3f-1f063f8e06cf" + ], + "alertTypeId" : "siem.notifications", + "consumer" : "siem", + "params" : { + "ruleAlertId" : "61ec7a40-b076-11ec-bb3f-1f063f8e06cf" + }, + "schedule" : { + "interval" : "7d" + }, + "enabled" : true, + "actions" : [ + { + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Test Actions" + }, + "actionTypeId" : ".email", + "actionRef" : "action_0" + } + ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:11:48.661Z", + "updatedAt" : "2022-03-30T22:11:48.661Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "ok", + "lastExecutionDate" : "2022-03-30T22:11:51.640Z", + "error" : null + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "scheduledTaskId" : null, + "legacyId" : "64492ef0-b076-11ec-bb3f-1f063f8e06cf" + }, + "type" : "alert", + "references" : [ + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "name" : "action_0", + "type" : "action" + }, + { + "id" : "61ec7a40-b076-11ec-bb3f-1f063f8e06cf", + "name" : "param:alert_0", + "type" : "alert" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:11:51.707Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:d42e8210-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ action - every hour", + "tags" : [ + "__internal_rule_alert_id:064e3160-b076-11ec-bb3f-1f063f8e06cf" + ], + "alertTypeId" : "siem.notifications", + "consumer" : "siem", + "params" : { + "ruleAlertId" : "064e3160-b076-11ec-bb3f-1f063f8e06cf" + }, + "schedule" : { + "interval" : "1h" + }, + "enabled" : true, + "actions" : [ + { + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Rule email" + }, + "actionTypeId" : ".email", + "actionRef" : "action_0" + }, + { + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts" + }, + "actionTypeId" : ".slack", + "actionRef" : "action_1" + } + ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:14:56.318Z", + "updatedAt" : "2022-03-30T22:15:12.135Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "pending", + "lastExecutionDate" : "2022-03-30T22:14:56.318Z", + "error" : null + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "legacyId" : "d42e8210-b076-11ec-bb3f-1f063f8e06cf" + }, + "type" : "alert", + "references" : [ + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "name" : "action_0", + "type" : "action" + }, + { + "id" : "207fa0e0-c04e-11ec-8a52-4fb92379525a", + "name" : "action_1", + "type" : "action" + }, + { + "id" : "064e3160-b076-11ec-bb3f-1f063f8e06cf", + "name" : "param:alert_0", + "type" : "alert" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:15:12.135Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "alert:29ba2fa0-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "alert" : { + "name" : "test w/ action - daily", + "tags" : [ + "__internal_rule_alert_id:27639570-b076-11ec-bb3f-1f063f8e06cf" + ], + "alertTypeId" : "siem.notifications", + "consumer" : "siem", + "params" : { + "ruleAlertId" : "27639570-b076-11ec-bb3f-1f063f8e06cf" + }, + "schedule" : { + "interval" : "1d" + }, + "enabled" : true, + "actions" : [ + { + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Test Actions" + }, + "actionTypeId" : ".email", + "actionRef" : "action_0" + } + ], + "throttle" : null, + "notifyWhen" : "onActiveAlert", + "apiKeyOwner" : null, + "apiKey" : null, + "createdBy" : "1527796724", + "updatedBy" : "1527796724", + "createdAt" : "2022-03-30T22:10:10.435Z", + "updatedAt" : "2022-03-30T22:10:10.435Z", + "muteAll" : false, + "mutedInstanceIds" : [ ], + "executionStatus" : { + "status" : "ok", + "lastExecutionDate" : "2022-04-01T22:10:15.478Z", + "error" : null, + "lastDuration" : 984 + }, + "meta" : { + "versionApiKeyLastmodified" : "7.15.2" + }, + "scheduledTaskId" : null, + "legacyId" : "29ba2fa0-b076-11ec-bb3f-1f063f8e06cf", + "monitoring" : { + "execution" : { + "history" : [ + { + "duration" : 111, + "success" : true, + "timestamp" : 1648764614215 + }, + { + "duration" : 984, + "success" : true, + "timestamp" : 1648851016462 + } + ], + "calculated_metrics" : { + "p99" : 984, + "success_ratio" : 1, + "p50" : 547.5, + "p95" : 984 + } + } + } + }, + "type" : "alert", + "references" : [ + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "name" : "action_0", + "type" : "action" + }, + { + "id" : "27639570-b076-11ec-bb3f-1f063f8e06cf", + "name" : "param:alert_0", + "type" : "alert" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "alert" : "8.0.1" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-04-01T22:10:16.467Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "siem-detection-engine-rule-actions:926668d0-b075-11ec-bb3f-1f063f8e06cf", + "source" : { + "siem-detection-engine-rule-actions" : { + "actions" : [ ], + "ruleThrottle" : "no_actions", + "alertThrottle" : null + }, + "type" : "siem-detection-engine-rule-actions", + "references" : [ + { + "id" : "9095ee90-b075-11ec-bb3f-1f063f8e06cf", + "type" : "alert", + "name" : "alert_0" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "siem-detection-engine-rule-actions" : "8.0.0" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:05:55.563Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "siem-detection-engine-rule-actions:dde13970-b075-11ec-bb3f-1f063f8e06cf", + "source" : { + "siem-detection-engine-rule-actions" : { + "actions" : [ + { + "actionRef" : "action_0", + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Test Actions" + }, + "action_type_id" : ".email" + } + ], + "ruleThrottle" : "rule", + "alertThrottle" : null + }, + "type" : "siem-detection-engine-rule-actions", + "references" : [ + { + "id" : "dc6595f0-b075-11ec-bb3f-1f063f8e06cf", + "type" : "alert", + "name" : "alert_0" + }, + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "type" : "action", + "name" : "action_0" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "siem-detection-engine-rule-actions" : "8.0.0" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:08:02.207Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "siem-detection-engine-rule-actions:07aa8d10-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "siem-detection-engine-rule-actions" : { + "actions" : [ + { + "actionRef" : "action_0", + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Rule email" + }, + "action_type_id" : ".email" + }, + { + "actionRef" : "action_1", + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts" + }, + "action_type_id" : ".slack" + } + ], + "ruleThrottle" : "1h", + "alertThrottle" : "1h" + }, + "type" : "siem-detection-engine-rule-actions", + "references" : [ + { + "id" : "064e3160-b076-11ec-bb3f-1f063f8e06cf", + "type" : "alert", + "name" : "alert_0" + }, + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "type" : "action", + "name" : "action_0" + }, + { + "id" : "207fa0e0-c04e-11ec-8a52-4fb92379525a", + "type" : "action", + "name" : "action_1" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "siem-detection-engine-rule-actions" : "8.0.0" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:09:12.300Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "siem-detection-engine-rule-actions:291ae260-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "siem-detection-engine-rule-actions" : { + "actions" : [ + { + "actionRef" : "action_0", + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Test Actions" + }, + "action_type_id" : ".email" + } + ], + "ruleThrottle" : "1d", + "alertThrottle" : "1d" + }, + "type" : "siem-detection-engine-rule-actions", + "references" : [ + { + "id" : "27639570-b076-11ec-bb3f-1f063f8e06cf", + "type" : "alert", + "name" : "alert_0" + }, + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "type" : "action", + "name" : "action_0" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "siem-detection-engine-rule-actions" : "8.0.0" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:10:08.399Z" + } + } +} + +{ + "type": "doc", + "value": { + "index" : ".kibana", + "id" : "siem-detection-engine-rule-actions:63aa2fd0-b076-11ec-bb3f-1f063f8e06cf", + "source" : { + "siem-detection-engine-rule-actions" : { + "actions" : [ + { + "actionRef" : "action_0", + "group" : "default", + "params" : { + "message" : "Rule {{context.rule.name}} generated {{state.signals_count}} alerts", + "to" : [ + "test@test.com" + ], + "subject" : "Test Actions" + }, + "action_type_id" : ".email" + } + ], + "ruleThrottle" : "7d", + "alertThrottle" : "7d" + }, + "type" : "siem-detection-engine-rule-actions", + "references" : [ + { + "id" : "61ec7a40-b076-11ec-bb3f-1f063f8e06cf", + "type" : "alert", + "name" : "alert_0" + }, + { + "id" : "c95cb100-b075-11ec-bb3f-1f063f8e06cf", + "type" : "action", + "name" : "action_0" + } + ], + "namespaces" : [ + "default" + ], + "migrationVersion" : { + "siem-detection-engine-rule-actions" : "8.0.0" + }, + "coreMigrationVersion" : "8.1.2", + "updated_at" : "2022-03-30T22:11:46.643Z" + } + } +} From f4d558a6da7c09bb33a9301279dd1d250e8e011e Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Wed, 4 May 2022 12:19:25 -0400 Subject: [PATCH 34/68] [DOCS] Update details about alert visibility in Stack Management (#130202) Co-authored-by: Lisa Cawley --- .../alerting-troubleshooting.asciidoc | 32 +++++++++++++------ docs/user/alerting/rule-types.asciidoc | 14 +++++++- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/docs/user/alerting/alerting-troubleshooting.asciidoc b/docs/user/alerting/alerting-troubleshooting.asciidoc index 5f3c566e82d42..5978d0f903145 100644 --- a/docs/user/alerting/alerting-troubleshooting.asciidoc +++ b/docs/user/alerting/alerting-troubleshooting.asciidoc @@ -1,11 +1,7 @@ -[role="xpack"] [[alerting-troubleshooting]] -== Troubleshooting -++++ -Troubleshooting -++++ +== Troubleshooting and limitations -Alerting provides many options for diagnosing problems with Rules and Connectors. +Alerting provides many options for diagnosing problems with rules and connectors. [float] [[alerting-kibana-log]] @@ -85,7 +81,7 @@ The result of this http request (and printed to stdout by https://github.com/pmu [[alerting-error-banners]] === Look for error banners -The Rule Management and Rule Details pages contain an error banner, which helps to identify the errors for the rules: +The *Rule Management* and *Rule Details* pages contain an error banner, which helps to identify the errors for the rules: [role="screenshot"] image::images/rules-management-health.png[Rule management page with the errors banner] @@ -96,14 +92,14 @@ image::images/rules-details-health.png[Rule details page with the errors banner] [[task-manager-diagnostics]] === Task Manager diagnostics -Under the hood, Rules and Connectors uses a plugin called Task Manager, which handles the scheduling, execution, and error handling of the tasks. +Under the hood, *Rules and Connectors* uses a plugin called Task Manager, which handles the scheduling, execution, and error handling of the tasks. This means that failure cases in Rules or Connectors will, at times, be revealed by the Task Manager mechanism, rather than the Rules mechanism. Task Manager provides a visible status which can be used to diagnose issues and is very well documented <> and <>. Task Manager uses the `.kibana_task_manager` index, an internal index that contains all the saved objects that represent the tasks in the system. [float] -==== Getting from a Rule to its Task +==== Getting from a rule to its task When a rule is created, a task is created, scheduled to run at the interval specified. For example, when a rule is created and configured to check every 5 minutes, then the underlying task will be expected to run every 5 minutes. In practice, after each time the rule runs, the task is scheduled to run again in 5 minutes, rather than being scheduled to run every 5 minutes indefinitely. If you use the <> to fetch the underlying rule, you’ll get an object like so: @@ -190,12 +186,28 @@ When diagnosing the health state of the task, you will most likely be interested Investigating the underlying task can help you gauge whether the problem you’re seeing is rooted in the rule not running at all, whether it’s running and failing, or whether it is running, but exhibiting behavior that is different than what was expected (at which point you should focus on the rule itself, rather than the task). -In addition to the above methods, broadly used the next approaches and common issues: +In addition to the above methods, refer to the following approaches and common issues: * <> * <> * <> +[discrete] +[[alerting-limitations]] +=== Limitations + +The following limitations and known problems apply to the {version} release of +the {kib} {alert-features}. + +[discrete] +==== Alert visibility + +If you create a rule in the {observability} or {security-app}, its alerts are +not visible in *{stack-manage-app} > {rules-ui}*. You can view them only in the +{kib} app where you created the rule. If you use the +<>, the visibility of the alerts is related to +the `consumer` property. + include::troubleshooting/alerting-common-issues.asciidoc[] include::troubleshooting/event-log-index.asciidoc[] include::troubleshooting/testing-connectors.asciidoc[] diff --git a/docs/user/alerting/rule-types.asciidoc b/docs/user/alerting/rule-types.asciidoc index 324347f3b2648..120c580330b9f 100644 --- a/docs/user/alerting/rule-types.asciidoc +++ b/docs/user/alerting/rule-types.asciidoc @@ -41,6 +41,12 @@ see {subscriptions}[the subscription page]. Observability rules are categorized into APM and User Experience, Logs, Metrics, Stack Monitoring, and Uptime. +[NOTE] +============================================== +If you create a rule in the {observability} app, its alerts are not visible in +*{stack-manage-app} > {rules-ui}*. They are visible only in the {observability} app. +============================================== + [cols="2*<"] |=== @@ -72,7 +78,13 @@ beta:[] {ml-docs}/ml-configuring-alerts.html[{ml-cap} rules] run scheduled check [[security-rules]] === Security rules -Security rules detect suspicious source events with pre-built or custom rules and create alerts when a rule’s conditions are met. For more information, refer to {security-guide}/prebuilt-rules.html[Security rules]. +Security rules detect suspicious source events with pre-built or custom rules and create alerts when a rule's conditions are met. For more information, refer to {security-guide}/prebuilt-rules.html[Security rules]. + +[NOTE] +============================================== +Alerts associated with security rules are visible only in the {security-app}; +they are not visible in *{stack-manage-app} > {rules-ui}*. +============================================== include::rule-types/index-threshold.asciidoc[] include::rule-types/es-query.asciidoc[] From 143fe7f6e74a242e15046263e22e54d783cec95b Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 4 May 2022 11:21:35 -0500 Subject: [PATCH 35/68] skip suite blocking es promotion (#125033) --- .../security_and_spaces/tests/create_ml.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts index 20c914e17ce70..94d65933bc9dc 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts @@ -92,7 +92,8 @@ export default ({ getService }: FtrProviderContext) => { return body; } - describe('Generating signals from ml anomalies', () => { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/125033 + describe.skip('Generating signals from ml anomalies', () => { before(async () => { // Order is critical here: auditbeat data must be loaded before attempting to start the ML job, // as the job looks for certain indices on start From 722698275900fca36a7fd0d8ec253028e434af8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Fern=C3=A1ndez=20Haro?= Date: Wed, 4 May 2022 18:22:34 +0200 Subject: [PATCH 36/68] [EBT] Add Elastic V3 Shippers (#130696) Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- ...lugin-core-public.analyticsservicesetup.md | 2 +- ...gin-core-server.analyticsservicepreboot.md | 2 +- ...lugin-core-server.analyticsservicesetup.md | 2 +- package.json | 6 + packages/BUILD.bazel | 6 + .../analytics_client/analytics_client.test.ts | 22 +- .../src/analytics_client/analytics_client.ts | 15 + .../client/src/analytics_client/mocks.ts | 1 + .../client/src/analytics_client/types.ts | 4 + packages/analytics/client/src/events/types.ts | 12 + .../analytics/client/src/shippers/mocks.ts | 1 + .../analytics/client/src/shippers/types.ts | 4 + packages/analytics/shippers/README.md | 2 + .../shippers/elastic_v3/browser/BUILD.bazel | 128 +++++ .../shippers/elastic_v3/browser/README.md | 25 + .../elastic_v3/browser/jest.config.js | 13 + .../shippers/elastic_v3/browser/package.json | 8 + .../browser/src/browser_shipper.test.ts | 291 ++++++++++++ .../elastic_v3/browser/src/browser_shipper.ts | 121 +++++ .../shippers/elastic_v3/browser/src/index.ts | 10 + .../shippers/elastic_v3/browser/tsconfig.json | 17 + .../shippers/elastic_v3/common/BUILD.bazel | 125 +++++ .../shippers/elastic_v3/common/README.md | 10 + .../shippers/elastic_v3/common/jest.config.js | 13 + .../shippers/elastic_v3/common/package.json | 8 + .../common/src/build_headers.test.ts | 32 ++ .../elastic_v3/common/src/build_headers.ts | 16 + .../elastic_v3/common/src/build_url.test.ts | 23 + .../elastic_v3/common/src/build_url.ts | 26 ++ .../common/src/error_with_code.test.ts | 20 + .../elastic_v3/common/src/error_with_code.ts | 13 + .../common/src/events_to_ndjson.test.ts | 50 ++ .../elastic_v3/common/src/events_to_ndjson.ts | 13 + .../shippers/elastic_v3/common/src/index.ts | 14 + .../src/report_telemetry_counters.test.ts | 203 ++++++++ .../common/src/report_telemetry_counters.ts | 55 +++ .../shippers/elastic_v3/common/src/types.ts | 29 ++ .../shippers/elastic_v3/common/tsconfig.json | 17 + .../shippers/elastic_v3/server/BUILD.bazel | 123 +++++ .../shippers/elastic_v3/server/README.md | 25 + .../shippers/elastic_v3/server/jest.config.js | 13 + .../shippers/elastic_v3/server/package.json | 7 + .../shippers/elastic_v3/server/src/index.ts | 10 + .../server/src/server_shipper.test.mocks.ts | 15 + .../server/src/server_shipper.test.ts | 438 ++++++++++++++++++ .../elastic_v3/server/src/server_shipper.ts | 290 ++++++++++++ .../shippers/elastic_v3/server/tsconfig.json | 17 + .../analytics/shippers/fullstory/README.md | 6 +- .../fullstory/src/fullstory_shipper.ts | 4 + .../src/bazel_package_dirs.ts | 1 + .../src/worker/webpack.config.ts | 2 +- .../analytics/analytics_service.mock.ts | 1 + .../public/analytics/analytics_service.ts | 5 +- src/core/public/core_system.ts | 1 + src/core/public/public.api.md | 2 +- .../analytics/analytics_service.mock.ts | 1 + .../server/analytics/analytics_service.ts | 7 +- src/core/server/server.api.md | 4 +- src/core/server/server.ts | 1 + src/plugins/telemetry/common/constants.ts | 6 + src/plugins/telemetry/public/plugin.test.ts | 22 +- src/plugins/telemetry/public/plugin.ts | 9 +- src/plugins/telemetry/server/plugin.test.ts | 34 ++ src/plugins/telemetry/server/plugin.ts | 110 ++++- .../public/custom_shipper.ts | 1 + .../server/custom_shipper.ts | 1 + .../public/custom_shipper.ts | 1 + .../server/custom_shipper.ts | 1 + yarn.lock | 24 + 69 files changed, 2498 insertions(+), 43 deletions(-) create mode 100644 packages/analytics/shippers/elastic_v3/browser/BUILD.bazel create mode 100644 packages/analytics/shippers/elastic_v3/browser/README.md create mode 100644 packages/analytics/shippers/elastic_v3/browser/jest.config.js create mode 100644 packages/analytics/shippers/elastic_v3/browser/package.json create mode 100644 packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.test.ts create mode 100644 packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.ts create mode 100644 packages/analytics/shippers/elastic_v3/browser/src/index.ts create mode 100644 packages/analytics/shippers/elastic_v3/browser/tsconfig.json create mode 100644 packages/analytics/shippers/elastic_v3/common/BUILD.bazel create mode 100644 packages/analytics/shippers/elastic_v3/common/README.md create mode 100644 packages/analytics/shippers/elastic_v3/common/jest.config.js create mode 100644 packages/analytics/shippers/elastic_v3/common/package.json create mode 100644 packages/analytics/shippers/elastic_v3/common/src/build_headers.test.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/build_headers.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/build_url.test.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/build_url.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/error_with_code.test.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/error_with_code.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.test.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/index.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/src/types.ts create mode 100644 packages/analytics/shippers/elastic_v3/common/tsconfig.json create mode 100644 packages/analytics/shippers/elastic_v3/server/BUILD.bazel create mode 100644 packages/analytics/shippers/elastic_v3/server/README.md create mode 100644 packages/analytics/shippers/elastic_v3/server/jest.config.js create mode 100644 packages/analytics/shippers/elastic_v3/server/package.json create mode 100644 packages/analytics/shippers/elastic_v3/server/src/index.ts create mode 100644 packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts create mode 100644 packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts create mode 100644 packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts create mode 100644 packages/analytics/shippers/elastic_v3/server/tsconfig.json create mode 100644 src/plugins/telemetry/server/plugin.test.ts diff --git a/docs/development/core/public/kibana-plugin-core-public.analyticsservicesetup.md b/docs/development/core/public/kibana-plugin-core-public.analyticsservicesetup.md index b1d059fe556b4..8cee67f0110dd 100644 --- a/docs/development/core/public/kibana-plugin-core-public.analyticsservicesetup.md +++ b/docs/development/core/public/kibana-plugin-core-public.analyticsservicesetup.md @@ -9,5 +9,5 @@ Exposes the public APIs of the AnalyticsClient during the setup phase. Signature: ```typescript -export declare type AnalyticsServiceSetup = AnalyticsClient; +export declare type AnalyticsServiceSetup = Omit; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.analyticsservicepreboot.md b/docs/development/core/server/kibana-plugin-core-server.analyticsservicepreboot.md index d648455dde18d..e1129181dbb49 100644 --- a/docs/development/core/server/kibana-plugin-core-server.analyticsservicepreboot.md +++ b/docs/development/core/server/kibana-plugin-core-server.analyticsservicepreboot.md @@ -9,5 +9,5 @@ Exposes the public APIs of the AnalyticsClient during the preboot phase Signature: ```typescript -export declare type AnalyticsServicePreboot = AnalyticsClient; +export declare type AnalyticsServicePreboot = Omit; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.analyticsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.analyticsservicesetup.md index aa84919848f24..5dc90eb0c1f03 100644 --- a/docs/development/core/server/kibana-plugin-core-server.analyticsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.analyticsservicesetup.md @@ -9,5 +9,5 @@ Exposes the public APIs of the AnalyticsClient during the setup phase. Signature: ```typescript -export declare type AnalyticsServiceSetup = AnalyticsClient; +export declare type AnalyticsServiceSetup = Omit; ``` diff --git a/package.json b/package.json index 1b785b1fcaaab..2659301131a7a 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,9 @@ "@kbn/ambient-ui-types": "link:bazel-bin/packages/kbn-ambient-ui-types", "@kbn/analytics": "link:bazel-bin/packages/kbn-analytics", "@kbn/analytics-client": "link:bazel-bin/packages/analytics/client", + "@kbn/analytics-shippers-elastic-v3-browser": "link:bazel-bin/packages/analytics/shippers/elastic_v3/browser", + "@kbn/analytics-shippers-elastic-v3-common": "link:bazel-bin/packages/analytics/shippers/elastic_v3/common", + "@kbn/analytics-shippers-elastic-v3-server": "link:bazel-bin/packages/analytics/shippers/elastic_v3/server", "@kbn/analytics-shippers-fullstory": "link:bazel-bin/packages/analytics/shippers/fullstory", "@kbn/apm-config-loader": "link:bazel-bin/packages/kbn-apm-config-loader", "@kbn/apm-utils": "link:bazel-bin/packages/kbn-apm-utils", @@ -605,6 +608,9 @@ "@types/kbn__alerts": "link:bazel-bin/packages/kbn-alerts/npm_module_types", "@types/kbn__analytics": "link:bazel-bin/packages/kbn-analytics/npm_module_types", "@types/kbn__analytics-client": "link:bazel-bin/packages/analytics/client/npm_module_types", + "@types/kbn__analytics-shippers-elastic-v3-browser": "link:bazel-bin/packages/analytics/shippers/elastic_v3/browser/npm_module_types", + "@types/kbn__analytics-shippers-elastic-v3-common": "link:bazel-bin/packages/analytics/shippers/elastic_v3/common/npm_module_types", + "@types/kbn__analytics-shippers-elastic-v3-server": "link:bazel-bin/packages/analytics/shippers/elastic_v3/server/npm_module_types", "@types/kbn__analytics-shippers-fullstory": "link:bazel-bin/packages/analytics/shippers/fullstory/npm_module_types", "@types/kbn__apm-config-loader": "link:bazel-bin/packages/kbn-apm-config-loader/npm_module_types", "@types/kbn__apm-utils": "link:bazel-bin/packages/kbn-apm-utils/npm_module_types", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index 43c80fc882159..52d4cbbdfb8c0 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -10,6 +10,9 @@ filegroup( name = "build_pkg_code", srcs = [ "//packages/analytics/client:build", + "//packages/analytics/shippers/elastic_v3/browser:build", + "//packages/analytics/shippers/elastic_v3/common:build", + "//packages/analytics/shippers/elastic_v3/server:build", "//packages/analytics/shippers/fullstory:build", "//packages/elastic-apm-synthtrace:build", "//packages/elastic-eslint-config-kibana:build", @@ -114,6 +117,9 @@ filegroup( name = "build_pkg_types", srcs = [ "//packages/analytics/client:build_types", + "//packages/analytics/shippers/elastic_v3/browser:build_types", + "//packages/analytics/shippers/elastic_v3/common:build_types", + "//packages/analytics/shippers/elastic_v3/server:build_types", "//packages/analytics/shippers/fullstory:build_types", "//packages/elastic-apm-synthtrace:build_types", "//packages/elastic-safer-lodash-set:build_types", diff --git a/packages/analytics/client/src/analytics_client/analytics_client.test.ts b/packages/analytics/client/src/analytics_client/analytics_client.test.ts index 9eeade4e8d454..5348ffa1979fa 100644 --- a/packages/analytics/client/src/analytics_client/analytics_client.test.ts +++ b/packages/analytics/client/src/analytics_client/analytics_client.test.ts @@ -33,6 +33,7 @@ describe('AnalyticsClient', () => { }); afterEach(() => { + analyticsClient.shutdown(); jest.useRealTimers(); }); @@ -285,13 +286,16 @@ describe('AnalyticsClient', () => { constructor({ optInMock, extendContextMock, + shutdownMock, }: { optInMock?: jest.Mock; extendContextMock?: jest.Mock; + shutdownMock?: jest.Mock; }) { super(); if (optInMock) this.optIn = optInMock; if (extendContextMock) this.extendContext = extendContextMock; + if (shutdownMock) this.shutdown = shutdownMock; } } @@ -358,17 +362,30 @@ describe('AnalyticsClient', () => { test( 'Handles errors in the shipper', fakeSchedulers((advance) => { + const optInMock = jest.fn().mockImplementation(() => { + throw new Error('Something went terribly wrong'); + }); const extendContextMock = jest.fn().mockImplementation(() => { throw new Error('Something went terribly wrong'); }); - analyticsClient.registerShipper(MockedShipper, { extendContextMock }); - analyticsClient.optIn({ global: { enabled: true } }); + const shutdownMock = jest.fn().mockImplementation(() => { + throw new Error('Something went terribly wrong'); + }); + analyticsClient.registerShipper(MockedShipper, { + optInMock, + extendContextMock, + shutdownMock, + }); + expect(() => analyticsClient.optIn({ global: { enabled: true } })).not.toThrow(); advance(10); + expect(optInMock).toHaveBeenCalledWith(true); expect(extendContextMock).toHaveBeenCalledWith({}); // The initial context expect(logger.warn).toHaveBeenCalledWith( `Shipper "${MockedShipper.shipperName}" failed to extend the context`, expect.any(Error) ); + expect(() => analyticsClient.shutdown()).not.toThrow(); + expect(shutdownMock).toHaveBeenCalled(); }) ); }); @@ -731,6 +748,7 @@ describe('AnalyticsClient', () => { expect(optInMock1).toHaveBeenCalledWith(false); // Using global and shipper-specific expect(optInMock2).toHaveBeenCalledWith(false); // Using only global }); + test('Catches error in the shipper.optIn method', () => { optInMock1.mockImplementation(() => { throw new Error('Something went terribly wrong'); diff --git a/packages/analytics/client/src/analytics_client/analytics_client.ts b/packages/analytics/client/src/analytics_client/analytics_client.ts index 1c7f261aaf4b4..e38f975fee5a9 100644 --- a/packages/analytics/client/src/analytics_client/analytics_client.ts +++ b/packages/analytics/client/src/analytics_client/analytics_client.ts @@ -208,6 +208,21 @@ export class AnalyticsClient implements IAnalyticsClient { this.shipperRegistered$.next(); }; + public shutdown = () => { + this.shippersRegistry.allShippers.forEach((shipper, shipperName) => { + try { + shipper.shutdown(); + } catch (err) { + this.initContext.logger.warn(`Failed to shutdown shipper "${shipperName}"`, err); + } + }); + this.internalEventQueue$.complete(); + this.internalTelemetryCounter$.complete(); + this.shipperRegistered$.complete(); + this.optInConfig$.complete(); + this.context$.complete(); + }; + /** * Forwards the `events` to the registered shippers, bearing in mind if the shipper is opted-in for that eventType. * @param eventType The event type's name diff --git a/packages/analytics/client/src/analytics_client/mocks.ts b/packages/analytics/client/src/analytics_client/mocks.ts index da707178a756e..221ca0ff3872f 100644 --- a/packages/analytics/client/src/analytics_client/mocks.ts +++ b/packages/analytics/client/src/analytics_client/mocks.ts @@ -18,6 +18,7 @@ function createMockedAnalyticsClient(): jest.Mocked { removeContextProvider: jest.fn(), registerShipper: jest.fn(), telemetryCounter$: new Subject(), + shutdown: jest.fn(), }; } diff --git a/packages/analytics/client/src/analytics_client/types.ts b/packages/analytics/client/src/analytics_client/types.ts index 7dd2be53991b0..88b60dc100e89 100644 --- a/packages/analytics/client/src/analytics_client/types.ts +++ b/packages/analytics/client/src/analytics_client/types.ts @@ -211,4 +211,8 @@ export interface IAnalyticsClient { * Observable to emit the stats of the processed events. */ readonly telemetryCounter$: Observable; + /** + * Stops the client. + */ + shutdown: () => void; } diff --git a/packages/analytics/client/src/events/types.ts b/packages/analytics/client/src/events/types.ts index a63d2adeeb62a..6d31f88621364 100644 --- a/packages/analytics/client/src/events/types.ts +++ b/packages/analytics/client/src/events/types.ts @@ -12,6 +12,18 @@ import type { ShipperName } from '../analytics_client'; * Definition of the context that can be appended to the events through the {@link IAnalyticsClient.registerContextProvider}. */ export interface EventContext { + /** + * The UUID of the cluster + */ + cluster_uuid?: string; + /** + * The name of the cluster. + */ + cluster_name?: string; + /** + * The license ID. + */ + license_id?: string; /** * The unique user ID. */ diff --git a/packages/analytics/client/src/shippers/mocks.ts b/packages/analytics/client/src/shippers/mocks.ts index 6f80d91675c97..4660ae9d27e72 100644 --- a/packages/analytics/client/src/shippers/mocks.ts +++ b/packages/analytics/client/src/shippers/mocks.ts @@ -23,6 +23,7 @@ class MockedShipper implements IShipper { public reportEvents = jest.fn(); public extendContext = jest.fn(); public telemetryCounter$ = new Subject(); + public shutdown = jest.fn(); } export const shippersMock = { diff --git a/packages/analytics/client/src/shippers/types.ts b/packages/analytics/client/src/shippers/types.ts index 15328507b4fe7..67fe2c54bd77e 100644 --- a/packages/analytics/client/src/shippers/types.ts +++ b/packages/analytics/client/src/shippers/types.ts @@ -32,4 +32,8 @@ export interface IShipper { * Observable to emit the stats of the processed events. */ telemetryCounter$?: Observable; + /** + * Shutdown the shipper. + */ + shutdown: () => void; } diff --git a/packages/analytics/shippers/README.md b/packages/analytics/shippers/README.md index 8fc04b9f9ecbc..5ab85d08ff2ca 100644 --- a/packages/analytics/shippers/README.md +++ b/packages/analytics/shippers/README.md @@ -3,3 +3,5 @@ This directory holds the implementation of the _built-in_ shippers provided by the Analytics client. At the moment, the shippers are: * [FullStory](./fullstory/README.md) +* [Elastic V3 (Browser shipper)](./elastic_v3/browser/README.md) +* [Elastic V3 (Server-side shipper)](./elastic_v3/server/README.md) diff --git a/packages/analytics/shippers/elastic_v3/browser/BUILD.bazel b/packages/analytics/shippers/elastic_v3/browser/BUILD.bazel new file mode 100644 index 0000000000000..63332da454feb --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/BUILD.bazel @@ -0,0 +1,128 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "browser" +PKG_REQUIRE_NAME = "@kbn/analytics-shippers-elastic-v3-browser" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + ], + exclude = [ + "**/*.test.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +# In this array place runtime dependencies, including other packages and NPM packages +# which must be available for this code to run. +# +# To reference other packages use: +# "//repo/relative/path/to/package" +# eg. "//packages/kbn-utils" +# +# To reference a NPM package use: +# "@npm//name-of-package" +# eg. "@npm//lodash" +RUNTIME_DEPS = [ + "@npm//rxjs", + "//packages/analytics/client", + "//packages/analytics/shippers/elastic_v3/common", +] + +# In this array place dependencies necessary to build the types, which will include the +# :npm_module_types target of other packages and packages from NPM, including @types/* +# packages. +# +# To reference the types for another package use: +# "//repo/relative/path/to/package:npm_module_types" +# eg. "//packages/kbn-utils:npm_module_types" +# +# References to NPM packages work the same as RUNTIME_DEPS +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//rxjs", + "//packages/analytics/client:npm_module_types", + "//packages/analytics/shippers/elastic_v3/common:npm_module_types", + "//packages/kbn-logging-mocks:npm_module_types", +] + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/analytics/shippers/elastic_v3/browser/README.md b/packages/analytics/shippers/elastic_v3/browser/README.md new file mode 100644 index 0000000000000..fcdd5e8a3ca2e --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/README.md @@ -0,0 +1,25 @@ +# @kbn/analytics-shippers-elastic-v3-browser + +UI-side implementation of the Elastic V3 shipper for the `@kbn/analytics-client`. + +## How to use it + +This module is intended to be used **on the browser only**. Due to the nature of the UI events, they are usually more scattered in time, and we can assume a much lower load than the server. For that reason, it doesn't apply the necessary backpressure mechanisms to prevent the server from getting overloaded with too many events neither identifies if the server sits behind a firewall to discard any incoming events. Refer to `@kbn/analytics-shippers-elastic-v3-server` for the server-side implementation. + +```typescript +import { ElasticV3BrowserShipper } from "@kbn/analytics-shippers-elastic-v3-browser"; + +analytics.registerShipper(ElasticV3BrowserShipper, { channelName: 'myChannel', version: '1.0.0' }); +``` + +## Configuration + +| Name | Description | +|:-------------:|:-------------------------------------------------------------------------------------------| +| `channelName` | The name of the channel to send the events. | +| `version` | The version of the application generating the events. | +| `debug` | When `true`, it logs the responses from the remote Telemetry Service. Defaults to `false`. | + +## Transmission protocol + +This shipper sends the events to the Elastic Internal Telemetry Service. The incoming events are buffered for up to 1 second to attempt to send them in a single request. diff --git a/packages/analytics/shippers/elastic_v3/browser/jest.config.js b/packages/analytics/shippers/elastic_v3/browser/jest.config.js new file mode 100644 index 0000000000000..20067863aad97 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../../../', + roots: ['/packages/analytics/shippers/elastic_v3/browser'], +}; diff --git a/packages/analytics/shippers/elastic_v3/browser/package.json b/packages/analytics/shippers/elastic_v3/browser/package.json new file mode 100644 index 0000000000000..418887000521a --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/analytics-shippers-elastic-v3-browser", + "private": true, + "version": "1.0.0", + "browser": "./target_web/index.js", + "main": "./target_node/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.test.ts b/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.test.ts new file mode 100644 index 0000000000000..6fbe8fc166586 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.test.ts @@ -0,0 +1,291 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { loggerMock } from '@kbn/logging-mocks'; +import type { AnalyticsClientInitContext, Event } from '@kbn/analytics-client'; +import { fakeSchedulers } from 'rxjs-marbles/jest'; +import { firstValueFrom } from 'rxjs'; +import { ElasticV3BrowserShipper } from './browser_shipper'; + +describe('ElasticV3BrowserShipper', () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'test-event-type', + context: {}, + properties: {}, + }, + ]; + + const initContext: AnalyticsClientInitContext = { + sendTo: 'staging', + isDev: true, + logger: loggerMock.create(), + }; + + let shipper: ElasticV3BrowserShipper; + + let fetchMock: jest.Mock; + + beforeEach(() => { + jest.useFakeTimers(); + + fetchMock = jest.fn().mockResolvedValue({ + status: 200, + ok: true, + text: () => Promise.resolve('{"status": "ok"}'), + }); + + Object.defineProperty(global, 'fetch', { + value: fetchMock, + writable: true, + }); + + shipper = new ElasticV3BrowserShipper( + { version: '1.2.3', channelName: 'test-channel', debug: true }, + initContext + ); + }); + + afterEach(() => { + shipper.shutdown(); + jest.useRealTimers(); + }); + + test("custom sendTo overrides Analytics client's", () => { + const prodShipper = new ElasticV3BrowserShipper( + { version: '1.2.3', channelName: 'test-channel', debug: true, sendTo: 'production' }, + initContext + ); + + // eslint-disable-next-line dot-notation + expect(prodShipper['url']).not.toEqual(shipper['url']); + }); + + test('set optIn should update the isOptedIn$ observable', () => { + // eslint-disable-next-line dot-notation + const internalOptIn$ = shipper['isOptedIn$']; + + // Initially undefined + expect(internalOptIn$.value).toBeUndefined(); + + shipper.optIn(true); + expect(internalOptIn$.value).toBe(true); + + shipper.optIn(false); + expect(internalOptIn$.value).toBe(false); + }); + + test('set extendContext should store local values: clusterUuid and licenseId', () => { + // eslint-disable-next-line dot-notation + const getInternalClusterUuid = () => shipper['clusterUuid']; + // eslint-disable-next-line dot-notation + const getInternalLicenseId = () => shipper['licenseId']; + + // Initial values + expect(getInternalClusterUuid()).toBe('UNKNOWN'); + expect(getInternalLicenseId()).toBeUndefined(); + + shipper.extendContext({ cluster_uuid: 'test-cluster-uuid' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); + expect(getInternalLicenseId()).toBeUndefined(); + + shipper.extendContext({ license_id: 'test-license-id' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); + expect(getInternalLicenseId()).toBe('test-license-id'); + + shipper.extendContext({ cluster_uuid: 'test-cluster-uuid-2', license_id: 'test-license-id-2' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid-2'); + expect(getInternalLicenseId()).toBe('test-license-id-2'); + }); + + test('calls to reportEvents do not call `fetch` straight away (buffer of 1s)', () => { + shipper.reportEvents(events); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test( + 'calls to reportEvents do not call `fetch` after 1s because no optIn value is set yet', + fakeSchedulers((advance) => { + shipper.reportEvents(events); + advance(1000); + expect(fetchMock).not.toHaveBeenCalled(); + }) + ); + + test( + 'calls to reportEvents call `fetch` after 1s when optIn value is set to true', + fakeSchedulers(async (advance) => { + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + advance(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_browser", + "type": "succeeded", + } + `); + }) + ); + + test( + 'calls to reportEvents do not call `fetch` after 1s when optIn value is set to false', + fakeSchedulers((advance) => { + shipper.reportEvents(events); + shipper.optIn(false); + advance(1000); + expect(fetchMock).not.toHaveBeenCalled(); + }) + ); + + test('calls to reportEvents call `fetch` when shutting down if optIn value is set to true', async () => { + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + shipper.shutdown(); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_browser", + "type": "succeeded", + } + `); + }); + + test( + 'does not add the query.debug: true property to the request if the shipper is not set with the debug flag', + fakeSchedulers((advance) => { + shipper = new ElasticV3BrowserShipper( + { version: '1.2.3', channelName: 'test-channel' }, + initContext + ); + shipper.reportEvents(events); + shipper.optIn(true); + advance(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + } + ); + }) + ); + + test( + 'handles when the fetch request fails', + fakeSchedulers(async (advance) => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + advance(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "Failed to fetch", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_browser", + "type": "failed", + } + `); + }) + ); + + test( + 'handles when the fetch request fails (request completes but not OK response)', + fakeSchedulers(async (advance) => { + fetchMock.mockResolvedValue({ + ok: false, + status: 400, + text: () => Promise.resolve('{"status": "not ok"}'), + }); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + advance(1000); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + keepalive: true, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "400", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_browser", + "type": "failed", + } + `); + }) + ); +}); diff --git a/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.ts b/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.ts new file mode 100644 index 0000000000000..5607d3d79a13d --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/src/browser_shipper.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { BehaviorSubject, interval, Subject, bufferWhen, concatMap, filter, skipWhile } from 'rxjs'; +import type { + AnalyticsClientInitContext, + Event, + EventContext, + IShipper, + TelemetryCounter, +} from '@kbn/analytics-client'; +import { ElasticV3ShipperOptions, ErrorWithCode } from '@kbn/analytics-shippers-elastic-v3-common'; +import { + buildHeaders, + buildUrl, + createTelemetryCounterHelper, + eventsToNDJSON, +} from '@kbn/analytics-shippers-elastic-v3-common'; + +export class ElasticV3BrowserShipper implements IShipper { + public static shipperName = 'elastic_v3_browser'; + public readonly telemetryCounter$ = new Subject(); + + private readonly reportTelemetryCounters = createTelemetryCounterHelper( + this.telemetryCounter$, + ElasticV3BrowserShipper.shipperName + ); + private readonly url: string; + + private readonly internalQueue$ = new Subject(); + + private readonly isOptedIn$ = new BehaviorSubject(undefined); + private clusterUuid: string = 'UNKNOWN'; + private licenseId: string | undefined; + + constructor( + private readonly options: ElasticV3ShipperOptions, + private readonly initContext: AnalyticsClientInitContext + ) { + this.setUpInternalQueueSubscriber(); + this.url = buildUrl({ + sendTo: options.sendTo ?? initContext.sendTo, + channelName: options.channelName, + }); + } + + public extendContext(newContext: EventContext) { + if (newContext.cluster_uuid) { + this.clusterUuid = newContext.cluster_uuid; + } + if (newContext.license_id) { + this.licenseId = newContext.license_id; + } + } + + public optIn(isOptedIn: boolean) { + this.isOptedIn$.next(isOptedIn); + } + + public reportEvents(events: Event[]) { + events.forEach((event) => { + this.internalQueue$.next(event); + }); + } + + public shutdown() { + this.internalQueue$.complete(); // NOTE: When completing the observable, the buffer logic does not wait and releases any buffered events. + } + + private setUpInternalQueueSubscriber() { + this.internalQueue$ + .pipe( + // Buffer events for 1 second or until we have an optIn value + bufferWhen(() => interval(1000).pipe(skipWhile(() => this.isOptedIn$.value === undefined))), + // Discard any events if we are not opted in + skipWhile(() => this.isOptedIn$.value === false), + // Skip empty buffers + filter((events) => events.length > 0), + // Send events + concatMap(async (events) => this.sendEvents(events)) + ) + .subscribe(); + } + + private async sendEvents(events: Event[]) { + try { + const code = await this.makeRequest(events); + this.reportTelemetryCounters(events, { code }); + } catch (error) { + this.reportTelemetryCounters(events, { code: error.code, error }); + } + } + + private async makeRequest(events: Event[]): Promise { + const { status, text, ok } = await fetch(this.url, { + method: 'POST', + body: eventsToNDJSON(events), + headers: buildHeaders(this.clusterUuid, this.options.version, this.licenseId), + ...(this.options.debug && { query: { debug: true } }), + // Allow the request to outlive the page in case the tab is closed + keepalive: true, + }); + + if (this.options.debug) { + this.initContext.logger.debug( + `[${ElasticV3BrowserShipper.shipperName}]: ${status} - ${await text()}` + ); + } + + if (!ok) { + throw new ErrorWithCode(`${status} - ${await text()}`, `${status}`); + } + + return `${status}`; + } +} diff --git a/packages/analytics/shippers/elastic_v3/browser/src/index.ts b/packages/analytics/shippers/elastic_v3/browser/src/index.ts new file mode 100644 index 0000000000000..9eb6668994037 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/src/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { ElasticV3ShipperOptions } from '@kbn/analytics-shippers-elastic-v3-common'; +export { ElasticV3BrowserShipper } from './browser_shipper'; diff --git a/packages/analytics/shippers/elastic_v3/browser/tsconfig.json b/packages/analytics/shippers/elastic_v3/browser/tsconfig.json new file mode 100644 index 0000000000000..b81a9a0217634 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/browser/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/analytics/shippers/elastic_v3/common/BUILD.bazel b/packages/analytics/shippers/elastic_v3/common/BUILD.bazel new file mode 100644 index 0000000000000..a09ee9019f93d --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/BUILD.bazel @@ -0,0 +1,125 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "common" +PKG_REQUIRE_NAME = "@kbn/analytics-shippers-elastic-v3-common" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + ], + exclude = [ + "**/*.test.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +# In this array place runtime dependencies, including other packages and NPM packages +# which must be available for this code to run. +# +# To reference other packages use: +# "//repo/relative/path/to/package" +# eg. "//packages/kbn-utils" +# +# To reference a NPM package use: +# "@npm//name-of-package" +# eg. "@npm//lodash" +RUNTIME_DEPS = [ + "@npm//rxjs", + "//packages/analytics/client", +] + +# In this array place dependencies necessary to build the types, which will include the +# :npm_module_types target of other packages and packages from NPM, including @types/* +# packages. +# +# To reference the types for another package use: +# "//repo/relative/path/to/package:npm_module_types" +# eg. "//packages/kbn-utils:npm_module_types" +# +# References to NPM packages work the same as RUNTIME_DEPS +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/jest", + "@npm//rxjs", + "//packages/analytics/client:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +jsts_transpiler( + name = "target_web", + srcs = SRCS, + build_pkg_name = package_name(), + web = True, +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node", ":target_web"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/analytics/shippers/elastic_v3/common/README.md b/packages/analytics/shippers/elastic_v3/common/README.md new file mode 100644 index 0000000000000..6684027b1ed7f --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/README.md @@ -0,0 +1,10 @@ +# @kbn/analytics-shippers-elastic-v3-common + +This package holds the common code for the Elastic V3 shippers: + +- Types defining the Shipper configuration `ElasticV3ShipperOptions` +- `buildUrl` utility helps decide which URL to use depending on whether the shipper is configured to send to production or staging. +- `eventsToNdjson` utility converts any array of events to NDJSON format. +- `reportTelemetryCounters` helps with building the TelemetryCounter to emit after processing an event. + +It should be considered an internal package and should not be used other than by the shipper implementations: `@kbn/analytics-shippers-elastic-v3-browser` and `@kbn/analytics-shippers-elastic-v3-server` diff --git a/packages/analytics/shippers/elastic_v3/common/jest.config.js b/packages/analytics/shippers/elastic_v3/common/jest.config.js new file mode 100644 index 0000000000000..1336211347fb7 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../../../', + roots: ['/packages/analytics/shippers/elastic_v3/common'], +}; diff --git a/packages/analytics/shippers/elastic_v3/common/package.json b/packages/analytics/shippers/elastic_v3/common/package.json new file mode 100644 index 0000000000000..ce8825e6bdc1f --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/package.json @@ -0,0 +1,8 @@ +{ + "name": "@kbn/analytics-shippers-elastic-v3-common", + "private": true, + "version": "1.0.0", + "browser": "./target_web/index.js", + "main": "./target_node/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_headers.test.ts b/packages/analytics/shippers/elastic_v3/common/src/build_headers.test.ts new file mode 100644 index 0000000000000..468824916ec48 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/build_headers.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { buildHeaders } from './build_headers'; + +describe('buildHeaders', () => { + test('builds the headers as expected in the V3 endpoints', () => { + expect(buildHeaders('test-cluster', '1.2.3', 'test-license')).toMatchInlineSnapshot(` + Object { + "content-type": "application/x-njson", + "x-elastic-cluster-id": "test-cluster", + "x-elastic-license-id": "test-license", + "x-elastic-stack-version": "1.2.3", + } + `); + }); + + test('if license is not provided, it skips the license header', () => { + expect(buildHeaders('test-cluster', '1.2.3')).toMatchInlineSnapshot(` + Object { + "content-type": "application/x-njson", + "x-elastic-cluster-id": "test-cluster", + "x-elastic-stack-version": "1.2.3", + } + `); + }); +}); diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_headers.ts b/packages/analytics/shippers/elastic_v3/common/src/build_headers.ts new file mode 100644 index 0000000000000..43126cf9d5629 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/build_headers.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export function buildHeaders(clusterUuid: string, version: string, licenseId?: string) { + return { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': clusterUuid, + 'x-elastic-stack-version': version, + ...(licenseId && { 'x-elastic-license-id': licenseId }), + }; +} diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_url.test.ts b/packages/analytics/shippers/elastic_v3/common/src/build_url.test.ts new file mode 100644 index 0000000000000..171491757ea56 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/build_url.test.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { buildUrl } from './build_url'; + +describe('buildUrl', () => { + test('returns production URL', () => { + expect(buildUrl({ sendTo: 'production', channelName: 'test-channel' })).toBe( + 'https://telemetry.elastic.co/v3/send/test-channel' + ); + }); + + test('returns staging URL', () => { + expect(buildUrl({ sendTo: 'staging', channelName: 'test-channel' })).toBe( + 'https://telemetry-staging.elastic.co/v3/send/test-channel' + ); + }); +}); diff --git a/packages/analytics/shippers/elastic_v3/common/src/build_url.ts b/packages/analytics/shippers/elastic_v3/common/src/build_url.ts new file mode 100644 index 0000000000000..f8d88b6804d08 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/build_url.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * Builds the URL for the V3 API. + * @param sendTo Whether to send it to production or staging. + * @param channelName The name of the channel to send the data to. + */ +export function buildUrl({ + sendTo, + channelName, +}: { + sendTo: 'production' | 'staging'; + channelName: string; +}): string { + const baseUrl = + sendTo === 'production' + ? 'https://telemetry.elastic.co' + : 'https://telemetry-staging.elastic.co'; + return `${baseUrl}/v3/send/${channelName}`; +} diff --git a/packages/analytics/shippers/elastic_v3/common/src/error_with_code.test.ts b/packages/analytics/shippers/elastic_v3/common/src/error_with_code.test.ts new file mode 100644 index 0000000000000..9be5d5bdc762c --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/error_with_code.test.ts @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ErrorWithCode } from './error_with_code'; + +describe('ErrorWithCode', () => { + const error = new ErrorWithCode('test', 'test_code'); + test('message and code properties are publicly accessible', () => { + expect(error.message).toBe('test'); + expect(error.code).toBe('test_code'); + }); + test('extends error', () => { + expect(error).toBeInstanceOf(Error); + }); +}); diff --git a/packages/analytics/shippers/elastic_v3/common/src/error_with_code.ts b/packages/analytics/shippers/elastic_v3/common/src/error_with_code.ts new file mode 100644 index 0000000000000..09346575a2df1 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/error_with_code.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export class ErrorWithCode extends Error { + constructor(message: string, public readonly code: string) { + super(message); + } +} diff --git a/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.test.ts b/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.test.ts new file mode 100644 index 0000000000000..4033bcb862967 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.test.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Event } from '@kbn/analytics-client'; +import { eventsToNDJSON } from './events_to_ndjson'; + +describe('eventsToNDJSON', () => { + test('works with one event', () => { + const event: Event = { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type', + context: {}, + properties: {}, + }; + + // Mind the extra line at the bottom + expect(eventsToNDJSON([event])).toMatchInlineSnapshot(` + "{\\"timestamp\\":\\"2020-01-01T00:00:00.000Z\\",\\"event_type\\":\\"event_type\\",\\"context\\":{},\\"properties\\":{}} + " + `); + }); + + test('works with many events', () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type', + context: {}, + properties: {}, + }, + { + timestamp: '2020-01-02T00:00:00.000Z', + event_type: 'event_type', + context: {}, + properties: {}, + }, + ]; + + expect(eventsToNDJSON(events)).toMatchInlineSnapshot(` + "{\\"timestamp\\":\\"2020-01-01T00:00:00.000Z\\",\\"event_type\\":\\"event_type\\",\\"context\\":{},\\"properties\\":{}} + {\\"timestamp\\":\\"2020-01-02T00:00:00.000Z\\",\\"event_type\\":\\"event_type\\",\\"context\\":{},\\"properties\\":{}} + " + `); + }); +}); diff --git a/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.ts b/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.ts new file mode 100644 index 0000000000000..af768770a0d5f --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/events_to_ndjson.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Event } from '@kbn/analytics-client'; + +export function eventsToNDJSON(events: Event[]): string { + return `${events.map((event) => JSON.stringify(event)).join('\n')}\n`; +} diff --git a/packages/analytics/shippers/elastic_v3/common/src/index.ts b/packages/analytics/shippers/elastic_v3/common/src/index.ts new file mode 100644 index 0000000000000..043be5c33c6fe --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { buildHeaders } from './build_headers'; +export { buildUrl } from './build_url'; +export { ErrorWithCode } from './error_with_code'; +export { eventsToNDJSON } from './events_to_ndjson'; +export { createTelemetryCounterHelper } from './report_telemetry_counters'; +export type { ElasticV3ShipperOptions } from './types'; diff --git a/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts b/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts new file mode 100644 index 0000000000000..13a59eb600db5 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.test.ts @@ -0,0 +1,203 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { firstValueFrom, Subject, take, toArray } from 'rxjs'; +import type { Event, TelemetryCounter } from '@kbn/analytics-client'; +import { TelemetryCounterType } from '@kbn/analytics-client'; +import { createTelemetryCounterHelper } from './report_telemetry_counters'; + +describe('reportTelemetryCounters', () => { + let reportTelemetryCounters: ReturnType; + let telemetryCounter$: Subject; + + beforeEach(() => { + telemetryCounter$ = new Subject(); + reportTelemetryCounters = createTelemetryCounterHelper(telemetryCounter$, 'my_shipper'); + }); + + test('emits a success counter for one event', async () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_a', + context: {}, + properties: {}, + }, + ]; + + const counters = firstValueFrom(telemetryCounter$); + + reportTelemetryCounters(events); + + await expect(counters).resolves.toMatchInlineSnapshot(` + Object { + "code": "OK", + "count": 1, + "event_type": "event_type_a", + "source": "my_shipper", + "type": "succeeded", + } + `); + }); + + test('emits a success counter for one event with custom code', async () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_a', + context: {}, + properties: {}, + }, + ]; + + const counters = firstValueFrom(telemetryCounter$); + + reportTelemetryCounters(events, { code: 'my_code' }); + + await expect(counters).resolves.toMatchInlineSnapshot(` + Object { + "code": "my_code", + "count": 1, + "event_type": "event_type_a", + "source": "my_shipper", + "type": "succeeded", + } + `); + }); + + test('emits a counter with custom type', async () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_a', + context: {}, + properties: {}, + }, + ]; + + const counters = firstValueFrom(telemetryCounter$); + + reportTelemetryCounters(events, { + type: TelemetryCounterType.dropped, + code: 'my_code', + }); + + await expect(counters).resolves.toMatchInlineSnapshot(` + Object { + "code": "my_code", + "count": 1, + "event_type": "event_type_a", + "source": "my_shipper", + "type": "dropped", + } + `); + }); + + test('emits a failure counter for one event with error message as a code', async () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_a', + context: {}, + properties: {}, + }, + ]; + + const counters = firstValueFrom(telemetryCounter$); + + reportTelemetryCounters(events, { + error: new Error('Something went terribly wrong'), + }); + + await expect(counters).resolves.toMatchInlineSnapshot(` + Object { + "code": "Something went terribly wrong", + "count": 1, + "event_type": "event_type_a", + "source": "my_shipper", + "type": "failed", + } + `); + }); + + test('emits a failure counter for one event with custom code', async () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_a', + context: {}, + properties: {}, + }, + ]; + + const counters = firstValueFrom(telemetryCounter$); + + reportTelemetryCounters(events, { + code: 'my_code', + error: new Error('Something went terribly wrong'), + }); + + await expect(counters).resolves.toMatchInlineSnapshot(` + Object { + "code": "my_code", + "count": 1, + "event_type": "event_type_a", + "source": "my_shipper", + "type": "failed", + } + `); + }); + + test('emits a success counter for multiple events of different types', async () => { + const events: Event[] = [ + // 2 types a + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_a', + context: {}, + properties: {}, + }, + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_a', + context: {}, + properties: {}, + }, + // 1 type b + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'event_type_b', + context: {}, + properties: {}, + }, + ]; + + const counters = firstValueFrom(telemetryCounter$.pipe(take(2), toArray())); + + reportTelemetryCounters(events); + + await expect(counters).resolves.toMatchInlineSnapshot(` + Array [ + Object { + "code": "OK", + "count": 2, + "event_type": "event_type_a", + "source": "my_shipper", + "type": "succeeded", + }, + Object { + "code": "OK", + "count": 1, + "event_type": "event_type_b", + "source": "my_shipper", + "type": "succeeded", + }, + ] + `); + }); +}); diff --git a/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.ts b/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.ts new file mode 100644 index 0000000000000..e4b63bcf2710f --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/report_telemetry_counters.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { Subject } from 'rxjs'; +import type { Event, TelemetryCounter } from '@kbn/analytics-client'; +import { TelemetryCounterType } from '@kbn/analytics-client'; + +/** + * Creates a telemetry counter helper to make it easier to generate them + * @param telemetryCounter$ The observable that will be used to emit the telemetry counters + * @param source The name of the shipper that is sending the events. + */ +export function createTelemetryCounterHelper( + telemetryCounter$: Subject, + source: string +) { + /** + * Triggers a telemetry counter for each event type. + * @param events The events to trigger the telemetry counter for. + * @param type The type of telemetry counter to trigger. + * @param code The success or error code for additional detail about the result. + * @param error The error that occurred, if any. + */ + return ( + events: Event[], + { type, code, error }: { type?: TelemetryCounterType; code?: string; error?: Error } = {} + ) => { + const eventTypeCounts = countEventTypes(events); + Object.entries(eventTypeCounts).forEach(([eventType, count]) => { + telemetryCounter$.next({ + source, + type: type ?? (error ? TelemetryCounterType.failed : TelemetryCounterType.succeeded), + code: code ?? error?.message ?? 'OK', + count, + event_type: eventType, + }); + }); + }; +} + +function countEventTypes(events: Event[]) { + return events.reduce((acc, event) => { + if (acc[event.event_type]) { + acc[event.event_type] += 1; + } else { + acc[event.event_type] = 1; + } + return acc; + }, {} as Record); +} diff --git a/packages/analytics/shippers/elastic_v3/common/src/types.ts b/packages/analytics/shippers/elastic_v3/common/src/types.ts new file mode 100644 index 0000000000000..c27aa448119fe --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/src/types.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/** + * Options for the Elastic V3 shipper + */ +export interface ElasticV3ShipperOptions { + /** + * The name of the channel to stream all the events to. + */ + channelName: string; + /** + * The product's version. + */ + version: string; + /** + * Provide it to override the Analytics client's default configuration. + */ + sendTo?: 'staging' | 'production'; + /** + * Should show debug information about the requests it makes to the V3 API. + */ + debug?: boolean; +} diff --git a/packages/analytics/shippers/elastic_v3/common/tsconfig.json b/packages/analytics/shippers/elastic_v3/common/tsconfig.json new file mode 100644 index 0000000000000..b81a9a0217634 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/common/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/analytics/shippers/elastic_v3/server/BUILD.bazel b/packages/analytics/shippers/elastic_v3/server/BUILD.bazel new file mode 100644 index 0000000000000..c05164d1f2b7e --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/BUILD.bazel @@ -0,0 +1,123 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_config") +load("@build_bazel_rules_nodejs//:index.bzl", "js_library") +load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") + +PKG_DIRNAME = "server" +PKG_REQUIRE_NAME = "@kbn/analytics-shippers-elastic-v3-server" + +SOURCE_FILES = glob( + [ + "src/**/*.ts", + ], + exclude = [ + "**/*.test.*", + ], +) + +SRCS = SOURCE_FILES + +filegroup( + name = "srcs", + srcs = SRCS, +) + +NPM_MODULE_EXTRA_FILES = [ + "package.json", +] + +# In this array place runtime dependencies, including other packages and NPM packages +# which must be available for this code to run. +# +# To reference other packages use: +# "//repo/relative/path/to/package" +# eg. "//packages/kbn-utils" +# +# To reference a NPM package use: +# "@npm//name-of-package" +# eg. "@npm//lodash" +RUNTIME_DEPS = [ + "@npm//node-fetch", + "@npm//rxjs", + "//packages/analytics/client", + "//packages/analytics/shippers/elastic_v3/common", +] + +# In this array place dependencies necessary to build the types, which will include the +# :npm_module_types target of other packages and packages from NPM, including @types/* +# packages. +# +# To reference the types for another package use: +# "//repo/relative/path/to/package:npm_module_types" +# eg. "//packages/kbn-utils:npm_module_types" +# +# References to NPM packages work the same as RUNTIME_DEPS +TYPES_DEPS = [ + "@npm//@types/node", + "@npm//@types/node-fetch", + "@npm//@types/jest", + "@npm//rxjs", + "//packages/analytics/client:npm_module_types", + "//packages/analytics/shippers/elastic_v3/common:npm_module_types", + "//packages/kbn-logging-mocks:npm_module_types", +] + +jsts_transpiler( + name = "target_node", + srcs = SRCS, + build_pkg_name = package_name(), +) + +ts_config( + name = "tsconfig", + src = "tsconfig.json", + deps = [ + "//:tsconfig.base.json", + "//:tsconfig.bazel.json", + ], +) + +ts_project( + name = "tsc_types", + args = ['--pretty'], + srcs = SRCS, + deps = TYPES_DEPS, + declaration = True, + emit_declaration_only = True, + out_dir = "target_types", + root_dir = "src", + tsconfig = ":tsconfig", +) + +js_library( + name = PKG_DIRNAME, + srcs = NPM_MODULE_EXTRA_FILES, + deps = RUNTIME_DEPS + [":target_node"], + package_name = PKG_REQUIRE_NAME, + visibility = ["//visibility:public"], +) + +pkg_npm( + name = "npm_module", + deps = [":" + PKG_DIRNAME], +) + +filegroup( + name = "build", + srcs = [":npm_module"], + visibility = ["//visibility:public"], +) + +pkg_npm_types( + name = "npm_module_types", + srcs = SRCS, + deps = [":tsc_types"], + package_name = PKG_REQUIRE_NAME, + tsconfig = ":tsconfig", + visibility = ["//visibility:public"], +) + +filegroup( + name = "build_types", + srcs = [":npm_module_types"], + visibility = ["//visibility:public"], +) diff --git a/packages/analytics/shippers/elastic_v3/server/README.md b/packages/analytics/shippers/elastic_v3/server/README.md new file mode 100644 index 0000000000000..ccdcf6a66cbe2 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/README.md @@ -0,0 +1,25 @@ +# @kbn/analytics-shippers-elastic-v3-server + +Server-side implementation of the Elastic V3 shipper for the `@kbn/analytics-client`. + +## How to use it + +This module is intended to be used **on the server-side only**. It is specially designed to apply the necessary backpressure mechanisms to prevent the server from getting overloaded with too many events and identify if the server sits behind a firewall to discard any incoming events. Refer to `@kbn/analytics-shippers-elastic-v3-browser` for the browser-side implementation. + +```typescript +import { ElasticV3ServerShipper } from "@kbn/analytics-shippers-elastic-v3-server"; + +analytics.registerShipper(ElasticV3ServerShipper, { channelName: 'myChannel', version: '1.0.0' }); +``` + +## Configuration + +| Name | Description | +|:-------------:|:-------------------------------------------------------------------------------------------| +| `channelName` | The name of the channel to send the events. | +| `version` | The version of the application generating the events. | +| `debug` | When `true`, it logs the responses from the remote Telemetry Service. Defaults to `false`. | + +## Transmission protocol + +This shipper sends the events to the Elastic Internal Telemetry Service. It holds up to 1000 events in a shared queue. Any additional incoming events once it's full will be dropped. It sends the events from the queue in batches of 10kB every 10 seconds. If not enough events are available in the queue for longer than 10 minutes, it will send any remaining events. When shutting down, it'll send all the remaining events in the queue. diff --git a/packages/analytics/shippers/elastic_v3/server/jest.config.js b/packages/analytics/shippers/elastic_v3/server/jest.config.js new file mode 100644 index 0000000000000..4397eb3e50c5a --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/jest.config.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../../../', + roots: ['/packages/analytics/shippers/elastic_v3/server'], +}; diff --git a/packages/analytics/shippers/elastic_v3/server/package.json b/packages/analytics/shippers/elastic_v3/server/package.json new file mode 100644 index 0000000000000..5ab24844eb1ba --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/analytics-shippers-elastic-v3-server", + "private": true, + "version": "1.0.0", + "main": "./target_node/index.js", + "license": "SSPL-1.0 OR Elastic License 2.0" +} diff --git a/packages/analytics/shippers/elastic_v3/server/src/index.ts b/packages/analytics/shippers/elastic_v3/server/src/index.ts new file mode 100644 index 0000000000000..50faf3c72ab29 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/src/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export type { ElasticV3ShipperOptions } from '@kbn/analytics-shippers-elastic-v3-common'; +export { ElasticV3ServerShipper } from './server_shipper'; diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts new file mode 100644 index 0000000000000..8da36242d48b6 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.mocks.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const fetchMock = jest.fn().mockResolvedValue({ + status: 200, + ok: true, + text: () => Promise.resolve('{"status": "ok"}'), +}); + +jest.doMock('node-fetch', () => fetchMock); diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts new file mode 100644 index 0000000000000..ffdfd797437a9 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.test.ts @@ -0,0 +1,438 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { loggerMock } from '@kbn/logging-mocks'; +import { firstValueFrom } from 'rxjs'; +import { fakeSchedulers } from 'rxjs-marbles/jest'; +import type { AnalyticsClientInitContext, Event } from '@kbn/analytics-client'; +import { fetchMock } from './server_shipper.test.mocks'; +import { ElasticV3ServerShipper } from './server_shipper'; + +const SECONDS = 1000; +const MINUTES = 60 * SECONDS; + +describe('ElasticV3ServerShipper', () => { + const events: Event[] = [ + { + timestamp: '2020-01-01T00:00:00.000Z', + event_type: 'test-event-type', + context: {}, + properties: {}, + }, + ]; + + const nextTick = () => new Promise((resolve) => setImmediate(resolve)); + + const initContext: AnalyticsClientInitContext = { + sendTo: 'staging', + isDev: true, + logger: loggerMock.create(), + }; + + let shipper: ElasticV3ServerShipper; + + // eslint-disable-next-line dot-notation + const setLastBatchSent = (ms: number) => (shipper['lastBatchSent'] = ms); + + beforeEach(() => { + jest.useFakeTimers(); + + shipper = new ElasticV3ServerShipper( + { version: '1.2.3', channelName: 'test-channel', debug: true }, + initContext + ); + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = null; + }); + + afterEach(() => { + shipper.shutdown(); + jest.clearAllMocks(); + }); + + test('set optIn should update the isOptedIn$ observable', () => { + // eslint-disable-next-line dot-notation + const getInternalOptIn = () => shipper['isOptedIn']; + + // Initially undefined + expect(getInternalOptIn()).toBeUndefined(); + + shipper.optIn(true); + expect(getInternalOptIn()).toBe(true); + + shipper.optIn(false); + expect(getInternalOptIn()).toBe(false); + }); + + test('clears the queue after optIn: false', () => { + shipper.reportEvents(events); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1); + + shipper.optIn(false); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(0); + }); + + test('set extendContext should store local values: clusterUuid and licenseId', () => { + // eslint-disable-next-line dot-notation + const getInternalClusterUuid = () => shipper['clusterUuid']; + // eslint-disable-next-line dot-notation + const getInternalLicenseId = () => shipper['licenseId']; + + // Initial values + expect(getInternalClusterUuid()).toBe('UNKNOWN'); + expect(getInternalLicenseId()).toBeUndefined(); + + shipper.extendContext({ cluster_uuid: 'test-cluster-uuid' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); + expect(getInternalLicenseId()).toBeUndefined(); + + shipper.extendContext({ license_id: 'test-license-id' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid'); + expect(getInternalLicenseId()).toBe('test-license-id'); + + shipper.extendContext({ cluster_uuid: 'test-cluster-uuid-2', license_id: 'test-license-id-2' }); + expect(getInternalClusterUuid()).toBe('test-cluster-uuid-2'); + expect(getInternalLicenseId()).toBe('test-license-id-2'); + }); + + test('calls to reportEvents do not call `fetch` straight away', () => { + shipper.reportEvents(events); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + test( + 'calls to reportEvents do not call `fetch` after 10 minutes because no optIn value is set yet', + fakeSchedulers((advance) => { + shipper.reportEvents(events); + advance(10 * MINUTES); + expect(fetchMock).not.toHaveBeenCalled(); + }) + ); + + test( + 'calls to reportEvents call `fetch` after 10 minutes when optIn value is set to true', + fakeSchedulers(async (advance) => { + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * MINUTES); + advance(10 * MINUTES); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "succeeded", + } + `); + }) + ); + + test( + 'calls to reportEvents do not call `fetch` after 10 minutes when optIn value is set to false', + fakeSchedulers((advance) => { + shipper.reportEvents(events); + shipper.optIn(false); + setLastBatchSent(Date.now() - 10 * MINUTES); + advance(10 * MINUTES); + expect(fetchMock).not.toHaveBeenCalled(); + }) + ); + + test('calls to reportEvents call `fetch` when shutting down if optIn value is set to true', async () => { + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + shipper.shutdown(); + await nextTick(); // We are handling the shutdown in a promise, so we need to wait for the next tick. + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "succeeded", + } + `); + }); + + test( + 'does not add the query.debug: true property to the request if the shipper is not set with the debug flag', + fakeSchedulers((advance) => { + shipper = new ElasticV3ServerShipper( + { version: '1.2.3', channelName: 'test-channel' }, + initContext + ); + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = null; + shipper.reportEvents(events); + shipper.optIn(true); + setLastBatchSent(Date.now() - 10 * MINUTES); + advance(10 * MINUTES); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + } + ); + }) + ); + + test( + 'sends when the queue overflows the 10kB leaky bucket one batch every 10s', + fakeSchedulers(async (advance) => { + expect.assertions(2 * 9 + 2); + + shipper.reportEvents(new Array(1000).fill(events[0])); + shipper.optIn(true); + + // Due to the size of the test events, it matches 9 rounds. + for (let i = 0; i < 9; i++) { + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * SECONDS); + advance(10 * SECONDS); + expect(fetchMock).toHaveBeenNthCalledWith( + i + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: new Array(103) + .fill( + '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n' + ) + .join(''), + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "200", + "count": 103, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "succeeded", + } + `); + await nextTick(); + } + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1000 - 9 * 103); // 73 + + // If we call it again, it should not enqueue all the events (only the ones to fill the queue): + shipper.reportEvents(new Array(1000).fill(events[0])); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1000); + }) + ); + + test( + 'handles when the fetch request fails', + fakeSchedulers(async (advance) => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * MINUTES); + advance(10 * MINUTES); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "Failed to fetch", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "failed", + } + `); + }) + ); + + test( + 'handles when the fetch request fails (request completes but not OK response)', + fakeSchedulers(async (advance) => { + fetchMock.mockResolvedValueOnce({ + ok: false, + status: 400, + text: () => Promise.resolve('{"status": "not ok"}'), + }); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * MINUTES); + advance(10 * MINUTES); + expect(fetchMock).toHaveBeenCalledWith( + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "400", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "failed", + } + `); + }) + ); + + test( + 'connectivity check is run after report failure', + fakeSchedulers(async (advance) => { + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + shipper.reportEvents(events); + shipper.optIn(true); + const counter = firstValueFrom(shipper.telemetryCounter$); + setLastBatchSent(Date.now() - 10 * MINUTES); + advance(10 * MINUTES); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { + body: '{"timestamp":"2020-01-01T00:00:00.000Z","event_type":"test-event-type","context":{},"properties":{}}\n', + headers: { + 'content-type': 'application/x-njson', + 'x-elastic-cluster-id': 'UNKNOWN', + 'x-elastic-stack-version': '1.2.3', + }, + method: 'POST', + query: { debug: true }, + } + ); + await expect(counter).resolves.toMatchInlineSnapshot(` + Object { + "code": "Failed to fetch", + "count": 1, + "event_type": "test-event-type", + "source": "elastic_v3_server", + "type": "failed", + } + `); + fetchMock.mockRejectedValueOnce(new Error('Failed to fetch')); + advance(1 * MINUTES); + await nextTick(); + expect(fetchMock).toHaveBeenNthCalledWith( + 2, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + fetchMock.mockResolvedValueOnce({ ok: false }); + advance(2 * MINUTES); + await nextTick(); + expect(fetchMock).toHaveBeenNthCalledWith( + 3, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + + // let's see the effect of after 24 hours: + shipper.reportEvents(events); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(1); + // eslint-disable-next-line dot-notation + shipper['firstTimeOffline'] = 100; + + fetchMock.mockResolvedValueOnce({ ok: false }); + advance(4 * MINUTES); + await nextTick(); + expect(fetchMock).toHaveBeenNthCalledWith( + 4, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(0); + + // New events are not added to the queue because it's been offline for 24 hours. + shipper.reportEvents(events); + // eslint-disable-next-line dot-notation + expect(shipper['internalQueue'].length).toBe(0); + + // Regains connection + fetchMock.mockResolvedValueOnce({ ok: true }); + advance(8 * MINUTES); + await nextTick(); + expect(fetchMock).toHaveBeenNthCalledWith( + 5, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + // eslint-disable-next-line dot-notation + expect(shipper['firstTimeOffline']).toBe(null); + + advance(16 * MINUTES); + await nextTick(); + expect(fetchMock).not.toHaveBeenNthCalledWith( + 6, + 'https://telemetry-staging.elastic.co/v3/send/test-channel', + { method: 'OPTIONS' } + ); + }) + ); +}); diff --git a/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts new file mode 100644 index 0000000000000..1c1277f7d7b4b --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/src/server_shipper.ts @@ -0,0 +1,290 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import fetch from 'node-fetch'; +import { + filter, + Subject, + interval, + concatMap, + merge, + from, + firstValueFrom, + timer, + retryWhen, + tap, + delayWhen, + takeWhile, +} from 'rxjs'; +import type { + AnalyticsClientInitContext, + Event, + EventContext, + IShipper, + TelemetryCounter, +} from '@kbn/analytics-client'; +import { TelemetryCounterType } from '@kbn/analytics-client'; +import type { ElasticV3ShipperOptions } from '@kbn/analytics-shippers-elastic-v3-common'; +import { + buildHeaders, + buildUrl, + createTelemetryCounterHelper, + eventsToNDJSON, + ErrorWithCode, +} from '@kbn/analytics-shippers-elastic-v3-common'; + +const SECOND = 1000; +const MINUTE = 60 * SECOND; +const HOUR = 60 * MINUTE; +const KIB = 1024; +const MAX_NUMBER_OF_EVENTS_IN_INTERNAL_QUEUE = 1000; + +export class ElasticV3ServerShipper implements IShipper { + public static shipperName = 'elastic_v3_server'; + public readonly telemetryCounter$ = new Subject(); + + private readonly reportTelemetryCounters = createTelemetryCounterHelper( + this.telemetryCounter$, + ElasticV3ServerShipper.shipperName + ); + + private readonly internalQueue: Event[] = []; + private readonly shutdown$ = new Subject(); + + private readonly url: string; + + private lastBatchSent = Date.now(); + + private clusterUuid: string = 'UNKNOWN'; + private licenseId?: string; + private isOptedIn?: boolean; + + /** + * Specifies when it went offline: + * - `undefined` means it doesn't know yet whether it is online or offline + * - `null` means it's online + * - `number` means it's offline since that time + * @private + */ + private firstTimeOffline?: number | null; + + constructor( + private readonly options: ElasticV3ShipperOptions, + private readonly initContext: AnalyticsClientInitContext + ) { + this.url = buildUrl({ + sendTo: options.sendTo ?? initContext.sendTo, + channelName: options.channelName, + }); + this.setInternalSubscriber(); + this.checkConnectivity(); + } + + public extendContext(newContext: EventContext) { + if (newContext.cluster_uuid) { + this.clusterUuid = newContext.cluster_uuid; + } + if (newContext.license_id) { + this.licenseId = newContext.license_id; + } + } + + public optIn(isOptedIn: boolean) { + this.isOptedIn = isOptedIn; + + if (isOptedIn === false) { + this.internalQueue.length = 0; + } + } + + public reportEvents(events: Event[]) { + if ( + this.isOptedIn === false || + (this.firstTimeOffline && Date.now() - this.firstTimeOffline > 24 * HOUR) + ) { + return; + } + + const freeSpace = MAX_NUMBER_OF_EVENTS_IN_INTERNAL_QUEUE - this.internalQueue.length; + + // As per design, we only want store up-to 1000 events at a time. Drop anything that goes beyond that limit + if (freeSpace < events.length) { + const toDrop = events.length - freeSpace; + const droppedEvents = events.splice(-toDrop, toDrop); + this.reportTelemetryCounters(droppedEvents, { + type: TelemetryCounterType.dropped, + code: 'queue_full', + }); + } + + this.internalQueue.push(...events); + } + + public shutdown() { + this.shutdown$.complete(); + } + + /** + * Checks the server has connectivity to the remote endpoint. + * The frequency of the connectivity tests will back off, starting with 1 minute, and multiplying by 2 + * until it reaches 1 hour. Then, it’ll keep the 1h frequency until it reaches 24h without connectivity. + * At that point, it clears the queue and stops accepting events in the queue. + * The connectivity checks will continue to happen every 1 hour just in case it regains it at any point. + * @private + */ + private checkConnectivity() { + let backoff = 1 * MINUTE; + timer(0, 1 * MINUTE) + .pipe( + takeWhile(() => this.shutdown$.isStopped === false), + filter(() => this.isOptedIn === true && this.firstTimeOffline !== null), + concatMap(async () => { + const { ok } = await fetch(this.url, { + method: 'OPTIONS', + }); + + if (!ok) { + throw new Error(`Failed to connect to ${this.url}`); + } + + this.firstTimeOffline = null; + backoff = 1 * MINUTE; + }), + retryWhen((errors) => + errors.pipe( + takeWhile(() => this.shutdown$.isStopped === false), + tap(() => { + if (!this.firstTimeOffline) { + this.firstTimeOffline = Date.now(); + } else if (Date.now() - this.firstTimeOffline > 24 * HOUR) { + this.internalQueue.length = 0; + } + backoff = backoff * 2; + if (backoff > 1 * HOUR) { + backoff = 1 * HOUR; + } + }), + delayWhen(() => timer(backoff)) + ) + ) + ) + .subscribe(); + } + + private setInternalSubscriber() { + // Check the status of the queues every 1 second. + merge( + interval(1000), + // Using a promise because complete does not emit through the pipe. + from(firstValueFrom(this.shutdown$, { defaultValue: true })) + ) + .pipe( + // Only move ahead if it's opted-in and online. + filter(() => this.isOptedIn === true && this.firstTimeOffline === null), + + // Send the events now if (validations sorted from cheapest to most CPU expensive): + // - We are shutting down. + // - There are some events in the queue, and we didn't send anything in the last 10 minutes. + // - The last time we sent was more than 10 seconds ago and: + // - We reached the minimum batch size of 10kB per request in our leaky bucket. + // - The queue is full (meaning we'll never get to 10kB because the events are very small). + filter( + () => + (this.internalQueue.length > 0 && + (this.shutdown$.isStopped || Date.now() - this.lastBatchSent >= 10 * MINUTE)) || + (Date.now() - this.lastBatchSent >= 10 * SECOND && + (this.internalQueue.length === 1000 || + this.getQueueByteSize(this.internalQueue) >= 10 * KIB)) + ), + + // Send the events + concatMap(async () => { + this.lastBatchSent = Date.now(); + const eventsToSend = this.getEventsToSend(); + await this.sendEvents(eventsToSend); + }), + + // Stop the subscriber if we are shutting down. + takeWhile(() => !this.shutdown$.isStopped) + ) + .subscribe(); + } + + /** + * Calculates the size of the queue in bytes. + * @returns The number of bytes held in the queue. + * @private + */ + private getQueueByteSize(queue: Event[]) { + return queue.reduce((acc, event) => { + return acc + this.getEventSize(event); + }, 0); + } + + /** + * Calculates the size of the event in bytes. + * @param event The event to calculate the size of. + * @returns The number of bytes held in the event. + * @private + */ + private getEventSize(event: Event) { + return Buffer.from(JSON.stringify(event)).length; + } + + /** + * Returns a queue of events of up-to 10kB. + * @remarks It mutates the internal queue by removing from it the events returned by this method. + * @private + */ + private getEventsToSend(): Event[] { + // If the internal queue is already smaller than the minimum batch size, do a direct assignment. + if (this.getQueueByteSize(this.internalQueue) < 10 * KIB) { + return this.internalQueue.splice(0, this.internalQueue.length); + } + // Otherwise, we'll feed the events to the leaky bucket queue until we reach 10kB. + const queue: Event[] = []; + let queueByteSize = 0; + while (queueByteSize < 10 * KIB) { + const event = this.internalQueue.shift()!; + queueByteSize += this.getEventSize(event); + queue.push(event); + } + return queue; + } + + private async sendEvents(events: Event[]) { + try { + const code = await this.makeRequest(events); + this.reportTelemetryCounters(events, { code }); + } catch (error) { + this.reportTelemetryCounters(events, { code: error.code, error }); + this.firstTimeOffline = undefined; + } + } + + private async makeRequest(events: Event[]): Promise { + const { status, text, ok } = await fetch(this.url, { + method: 'POST', + body: eventsToNDJSON(events), + headers: buildHeaders(this.clusterUuid, this.options.version, this.licenseId), + ...(this.options.debug && { query: { debug: true } }), + }); + + if (this.options.debug) { + this.initContext.logger.debug( + `[${ElasticV3ServerShipper.shipperName}]: ${status} - ${await text()}` + ); + } + + if (!ok) { + throw new ErrorWithCode(`${status} - ${await text()}`, `${status}`); + } + + return `${status}`; + } +} diff --git a/packages/analytics/shippers/elastic_v3/server/tsconfig.json b/packages/analytics/shippers/elastic_v3/server/tsconfig.json new file mode 100644 index 0000000000000..b81a9a0217634 --- /dev/null +++ b/packages/analytics/shippers/elastic_v3/server/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "../../../../../tsconfig.bazel.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "target_types", + "rootDir": "src", + "stripInternal": false, + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/analytics/shippers/fullstory/README.md b/packages/analytics/shippers/fullstory/README.md index 5bcc8d3c7d040..6d1c443db3d22 100644 --- a/packages/analytics/shippers/fullstory/README.md +++ b/packages/analytics/shippers/fullstory/README.md @@ -4,7 +4,7 @@ FullStory implementation as a shipper for the `@kbn/analytics-client`. ## How to use it -This module is intended to be used on the UI only. It does not support server-side events. +This module is intended to be used **on the browser only**. It does not support server-side events. ```typescript import { FullStoryShipper } from "@kbn/analytics-shippers-fullstory"; @@ -25,3 +25,7 @@ analytics.registerShipper(FullStoryShipper, { fullStoryOrgId: '12345' }) ## FullStory Custom Events Rate Limits FullStory limits the number of custom events that can be sent per second ([docs](https://help.fullstory.com/hc/en-us/articles/360020623234#custom-property-rate-limiting)). In order to comply with that limit, this shipper will only emit the event types registered in the allow-list defined in the constant [CUSTOM_EVENT_TYPES_ALLOWLIST](./src/fullstory_shipper.ts). We may change this behaviour in the future to a remotely-controlled list of events or rely on the opt-in _cherry-pick_ config mechanism of the Analytics Client. + +## Transmission protocol + +This shipper relies on FullStory official snippet. The internals about how it transfers the data are not documented. diff --git a/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts b/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts index ad970564c6845..48e8d7e6fa246 100644 --- a/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts +++ b/packages/analytics/shippers/fullstory/src/fullstory_shipper.ts @@ -128,4 +128,8 @@ export class FullStoryShipper implements IShipper { this.fullStoryApi.event(event.event_type, formatPayload(event.properties)); }); } + + public shutdown() { + // No need to do anything here for now. + } } diff --git a/packages/kbn-bazel-packages/src/bazel_package_dirs.ts b/packages/kbn-bazel-packages/src/bazel_package_dirs.ts index f09883994feca..1027883df10dd 100644 --- a/packages/kbn-bazel-packages/src/bazel_package_dirs.ts +++ b/packages/kbn-bazel-packages/src/bazel_package_dirs.ts @@ -24,6 +24,7 @@ export const BAZEL_PACKAGE_DIRS = [ 'packages/shared-ux/*', 'packages/analytics', 'packages/analytics/shippers', + 'packages/analytics/shippers/elastic_v3', ]; /** diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 422fe12f11b28..876bc347a21c5 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -94,7 +94,7 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: module: { // no parse rules for a few known large packages which have no require() statements // or which have require() statements that should be ignored because the file is - // already bundled with all its necessary depedencies + // already bundled with all its necessary dependencies noParse: [ /[\/\\]node_modules[\/\\]lodash[\/\\]index\.js$/, /[\/\\]node_modules[\/\\]vega[\/\\]build[\/\\]vega\.js$/, diff --git a/src/core/public/analytics/analytics_service.mock.ts b/src/core/public/analytics/analytics_service.mock.ts index c14d4a8216850..9037a756473c3 100644 --- a/src/core/public/analytics/analytics_service.mock.ts +++ b/src/core/public/analytics/analytics_service.mock.ts @@ -40,6 +40,7 @@ const createAnalyticsServiceMock = (): jest.Mocked => return { setup: jest.fn().mockImplementation(createAnalyticsServiceSetup), start: jest.fn().mockImplementation(createAnalyticsServiceStart), + stop: jest.fn(), }; }; diff --git a/src/core/public/analytics/analytics_service.ts b/src/core/public/analytics/analytics_service.ts index 89e83c7e3c85b..86b0977faa0c0 100644 --- a/src/core/public/analytics/analytics_service.ts +++ b/src/core/public/analytics/analytics_service.ts @@ -16,7 +16,7 @@ import { createLogger } from './logger'; * {@link AnalyticsClient} * @public */ -export type AnalyticsServiceSetup = AnalyticsClient; +export type AnalyticsServiceSetup = Omit; /** * Exposes the public APIs of the AnalyticsClient during the start phase * {@link AnalyticsClient} @@ -58,4 +58,7 @@ export class AnalyticsService { telemetryCounter$: this.analyticsClient.telemetryCounter$, }; } + public stop() { + this.analyticsClient.shutdown(); + } } diff --git a/src/core/public/core_system.ts b/src/core/public/core_system.ts index 726f53a345208..9334dd579f0f3 100644 --- a/src/core/public/core_system.ts +++ b/src/core/public/core_system.ts @@ -300,6 +300,7 @@ export class CoreSystem { this.application.stop(); this.deprecations.stop(); this.theme.stop(); + this.analytics.stop(); this.rootDomElement.textContent = ''; } } diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 2a662e3f7f8bd..3e431f07bd1cf 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -69,7 +69,7 @@ export { AnalyticsClient } // Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver // // @public -export type AnalyticsServiceSetup = AnalyticsClient; +export type AnalyticsServiceSetup = Omit; // Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver // diff --git a/src/core/server/analytics/analytics_service.mock.ts b/src/core/server/analytics/analytics_service.mock.ts index 74f675ac37b8f..7a00e573f3e7b 100644 --- a/src/core/server/analytics/analytics_service.mock.ts +++ b/src/core/server/analytics/analytics_service.mock.ts @@ -54,6 +54,7 @@ const createAnalyticsServiceMock = (): jest.Mocked => preboot: jest.fn().mockImplementation(createAnalyticsServicePreboot), setup: jest.fn().mockImplementation(createAnalyticsServiceSetup), start: jest.fn().mockImplementation(createAnalyticsServiceStart), + stop: jest.fn(), }; }; diff --git a/src/core/server/analytics/analytics_service.ts b/src/core/server/analytics/analytics_service.ts index 4262a966ceb10..3afc997fd52ea 100644 --- a/src/core/server/analytics/analytics_service.ts +++ b/src/core/server/analytics/analytics_service.ts @@ -15,13 +15,13 @@ import type { CoreContext } from '../core_context'; * {@link AnalyticsClient} * @public */ -export type AnalyticsServicePreboot = AnalyticsClient; +export type AnalyticsServicePreboot = Omit; /** * Exposes the public APIs of the AnalyticsClient during the setup phase. * {@link AnalyticsClient} * @public */ -export type AnalyticsServiceSetup = AnalyticsClient; +export type AnalyticsServiceSetup = Omit; /** * Exposes the public APIs of the AnalyticsClient during the start phase * {@link AnalyticsClient} @@ -74,4 +74,7 @@ export class AnalyticsService { telemetryCounter$: this.analyticsClient.telemetryCounter$, }; } + public stop() { + this.analyticsClient.shutdown(); + } } diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index ea83e210cc4e1..4ff42f95b571a 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -77,12 +77,12 @@ export { AnalyticsClient } // Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver // // @public -export type AnalyticsServicePreboot = AnalyticsClient; +export type AnalyticsServicePreboot = Omit; // Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver // // @public -export type AnalyticsServiceSetup = AnalyticsClient; +export type AnalyticsServiceSetup = Omit; // Warning: (ae-unresolved-link) The @link reference could not be resolved: This type of declaration is not supported yet by the resolver // diff --git a/src/core/server/server.ts b/src/core/server/server.ts index c73e98f4bb6c4..bc5048de45cba 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -358,6 +358,7 @@ export class Server { public async stop() { this.log.debug('stopping server'); + this.analytics.stop(); await this.http.stop(); // HTTP server has to stop before savedObjects and ES clients are closed to be able to gracefully attempt to resolve any pending requests await this.plugins.stop(); await this.savedObjects.stop(); diff --git a/src/plugins/telemetry/common/constants.ts b/src/plugins/telemetry/common/constants.ts index 7b7d0a0db5057..78887c27fbcfb 100644 --- a/src/plugins/telemetry/common/constants.ts +++ b/src/plugins/telemetry/common/constants.ts @@ -12,6 +12,12 @@ */ export const REPORT_INTERVAL_MS = 86400000; +/** + * How often we poll for the opt-in status. + * Currently, 10 seconds. + */ +export const OPT_IN_POLL_INTERVAL_MS = 10000; + /** * Key for the localStorage service */ diff --git a/src/plugins/telemetry/public/plugin.test.ts b/src/plugins/telemetry/public/plugin.test.ts index 5d9e03fcbae20..f25bf92340ba6 100644 --- a/src/plugins/telemetry/public/plugin.test.ts +++ b/src/plugins/telemetry/public/plugin.test.ts @@ -6,17 +6,18 @@ * Side Public License, v 1. */ -import { TelemetryPlugin } from './plugin'; +import { ElasticV3BrowserShipper } from '@kbn/analytics-shippers-elastic-v3-browser'; import { coreMock } from '@kbn/core/public/mocks'; import { homePluginMock } from '@kbn/home-plugin/public/mocks'; import { screenshotModePluginMock } from '@kbn/screenshot-mode-plugin/public/mocks'; import { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public'; - -let screenshotMode: ScreenshotModePluginSetup; -let home: HomePublicPluginSetup; +import { TelemetryPlugin } from './plugin'; describe('TelemetryPlugin', () => { + let screenshotMode: ScreenshotModePluginSetup; + let home: HomePublicPluginSetup; + beforeEach(() => { screenshotMode = screenshotModePluginMock.createSetupContract(); home = homePluginMock.createSetupContract(); @@ -56,5 +57,18 @@ describe('TelemetryPlugin', () => { }); }); }); + describe('EBT shipper registration', () => { + it('registers the UI telemetry shipper', () => { + const initializerContext = coreMock.createPluginInitializerContext(); + const coreSetupMock = coreMock.createSetup(); + + new TelemetryPlugin(initializerContext).setup(coreSetupMock, { screenshotMode, home }); + + expect(coreSetupMock.analytics.registerShipper).toHaveBeenCalledWith( + ElasticV3BrowserShipper, + { channelName: 'kibana-browser', version: 'version' } + ); + }); + }); }); }); diff --git a/src/plugins/telemetry/public/plugin.ts b/src/plugins/telemetry/public/plugin.ts index 133b2c6157c3c..6fe7fe4138a31 100644 --- a/src/plugins/telemetry/public/plugin.ts +++ b/src/plugins/telemetry/public/plugin.ts @@ -6,6 +6,8 @@ * Side Public License, v 1. */ +import { ElasticV3BrowserShipper } from '@kbn/analytics-shippers-elastic-v3-browser'; + import type { Plugin, CoreStart, @@ -20,7 +22,7 @@ import type { import type { ScreenshotModePluginSetup } from '@kbn/screenshot-mode-plugin/public'; -import { HomePublicPluginSetup } from '@kbn/home-plugin/public'; +import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import { TelemetrySender, TelemetryService, TelemetryNotifications } from './services'; import type { TelemetrySavedObjectAttributes, @@ -153,6 +155,11 @@ export class TelemetryPlugin implements Plugin { await this.refreshConfig(); analytics.optIn({ global: { enabled: this.telemetryService!.isOptedIn } }); diff --git a/src/plugins/telemetry/server/plugin.test.ts b/src/plugins/telemetry/server/plugin.test.ts new file mode 100644 index 0000000000000..c31e78722abf5 --- /dev/null +++ b/src/plugins/telemetry/server/plugin.test.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ElasticV3ServerShipper } from '@kbn/analytics-shippers-elastic-v3-server'; +import { coreMock } from '@kbn/core/server/mocks'; +import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/server/mocks'; +import { telemetryCollectionManagerPluginMock } from '@kbn/telemetry-collection-manager-plugin/server/mocks'; +import { TelemetryPlugin } from './plugin'; + +describe('TelemetryPlugin', () => { + describe('setup', () => { + describe('EBT shipper registration', () => { + it('registers the Server telemetry shipper', () => { + const initializerContext = coreMock.createPluginInitializerContext(); + const coreSetupMock = coreMock.createSetup(); + + new TelemetryPlugin(initializerContext).setup(coreSetupMock, { + usageCollection: usageCollectionPluginMock.createSetupContract(), + telemetryCollectionManager: telemetryCollectionManagerPluginMock.createSetupContract(), + }); + + expect(coreSetupMock.analytics.registerShipper).toHaveBeenCalledWith( + ElasticV3ServerShipper, + { channelName: 'kibana-server', version: 'version' } + ); + }); + }); + }); +}); diff --git a/src/plugins/telemetry/server/plugin.ts b/src/plugins/telemetry/server/plugin.ts index 7c01b85130977..c3c2604dc9a03 100644 --- a/src/plugins/telemetry/server/plugin.ts +++ b/src/plugins/telemetry/server/plugin.ts @@ -8,7 +8,18 @@ import { URL } from 'url'; import type { Observable } from 'rxjs'; -import { firstValueFrom, ReplaySubject } from 'rxjs'; +import { + BehaviorSubject, + firstValueFrom, + ReplaySubject, + exhaustMap, + timer, + distinctUntilChanged, + filter, +} from 'rxjs'; + +import { ElasticV3ServerShipper } from '@kbn/analytics-shippers-elastic-v3-server'; + import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; import type { TelemetryCollectionManagerPluginSetup, @@ -33,6 +44,7 @@ import { import type { TelemetryConfigType } from './config'; import { FetcherTask } from './fetcher'; import { getTelemetrySavedObject, TelemetrySavedObject } from './telemetry_repository'; +import { OPT_IN_POLL_INTERVAL_MS } from '../common/constants'; import { getTelemetryOptIn, getTelemetryChannelEndpoint } from '../common/telemetry_config'; interface TelemetryPluginsDepsSetup { @@ -74,6 +86,7 @@ export class TelemetryPlugin implements Plugin; + private readonly isOptedIn$ = new BehaviorSubject(undefined); private readonly isDev: boolean; private readonly fetcherTask: FetcherTask; /** @@ -91,6 +104,17 @@ export class TelemetryPlugin implements Plugin(1); + /** + * Poll for the opt-in status and update the `isOptedIn$` subject. + * @private + */ + private readonly optInPollerSubscription = timer(0, OPT_IN_POLL_INTERVAL_MS) + .pipe( + exhaustMap(() => this.getOptInStatus()), + distinctUntilChanged() + ) + .subscribe((isOptedIn) => this.isOptedIn$.next(isOptedIn)); + private security?: SecurityPluginStart; constructor(initializerContext: PluginInitializerContext) { @@ -102,13 +126,29 @@ export class TelemetryPlugin implements Plugin typeof isOptedIn === 'boolean')) + .subscribe((isOptedIn) => analytics.optIn({ global: { enabled: isOptedIn } })); + const savedObjectsInternalRepository = savedObjects.createInternalRepository(); this.savedObjectsInternalRepository = savedObjectsInternalRepository; this.savedObjectsInternalClient$.next(new SavedObjectsClient(savedObjectsInternalRepository)); @@ -155,31 +200,46 @@ export class TelemetryPlugin implements Plugin { - const internalRepositoryClient = await firstValueFrom(this.savedObjectsInternalClient$); - let telemetrySavedObject: TelemetrySavedObject = false; // if an error occurs while fetching opt-in status, a `false` result indicates that Kibana cannot opt-in - try { - telemetrySavedObject = await getTelemetrySavedObject(internalRepositoryClient); - } catch (err) { - this.logger.debug('Failed to check telemetry opt-in status: ' + err.message); - } - - const config = await firstValueFrom(this.config$); - const allowChangingOptInStatus = config.allowChangingOptInStatus; - const configTelemetryOptIn = typeof config.optIn === 'undefined' ? null : config.optIn; - const currentKibanaVersion = this.currentKibanaVersion; - const isOptedIn = getTelemetryOptIn({ - currentKibanaVersion, - telemetrySavedObject, - allowChangingOptInStatus, - configTelemetryOptIn, - }); - - return isOptedIn === true; - }, + getIsOptedIn: async () => this.isOptedIn$.value === true, }; } + public stop() { + this.optInPollerSubscription.unsubscribe(); + this.isOptedIn$.complete(); + } + + private async getOptInStatus(): Promise { + const internalRepositoryClient = await firstValueFrom(this.savedObjectsInternalClient$); + + let telemetrySavedObject: TelemetrySavedObject | undefined; + try { + telemetrySavedObject = await getTelemetrySavedObject(internalRepositoryClient); + } catch (err) { + this.logger.debug('Failed to check telemetry opt-in status: ' + err.message); + } + + // If we can't get the saved object due to permissions or other error other than 404, skip this round. + if (typeof telemetrySavedObject === 'undefined' || telemetrySavedObject === false) { + return; + } + + const config = await firstValueFrom(this.config$); + const allowChangingOptInStatus = config.allowChangingOptInStatus; + const configTelemetryOptIn = typeof config.optIn === 'undefined' ? null : config.optIn; + const currentKibanaVersion = this.currentKibanaVersion; + const isOptedIn = getTelemetryOptIn({ + currentKibanaVersion, + telemetrySavedObject, + allowChangingOptInStatus, + configTelemetryOptIn, + }); + + if (typeof isOptedIn === 'boolean') { + return isOptedIn; + } + } + private startFetcher( core: CoreStart, telemetryCollectionManager: TelemetryCollectionManagerPluginStart diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/custom_shipper.ts b/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/custom_shipper.ts index 31c9302e5ece8..ad45ba871f2c7 100644 --- a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/custom_shipper.ts +++ b/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/public/custom_shipper.ts @@ -20,4 +20,5 @@ export class CustomShipper implements IShipper { }); } optIn(isOptedIn: boolean) {} + shutdown() {} } diff --git a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/custom_shipper.ts b/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/custom_shipper.ts index 0feb1f2d13e7c..ed63f9a8db02f 100644 --- a/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/custom_shipper.ts +++ b/test/analytics/__fixtures__/plugins/analytics_ftr_helpers/server/custom_shipper.ts @@ -20,4 +20,5 @@ export class CustomShipper implements IShipper { }); } optIn(isOptedIn: boolean) {} + shutdown() {} } diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/custom_shipper.ts b/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/custom_shipper.ts index e94e34126c7d4..075f5bcdb99a1 100644 --- a/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/custom_shipper.ts +++ b/test/analytics/__fixtures__/plugins/analytics_plugin_a/public/custom_shipper.ts @@ -40,4 +40,5 @@ export class CustomShipper implements IShipper { extendContext(newContext: EventContext) { this.actions$.next({ action: 'extendContext', meta: newContext }); } + shutdown() {} } diff --git a/test/analytics/__fixtures__/plugins/analytics_plugin_a/server/custom_shipper.ts b/test/analytics/__fixtures__/plugins/analytics_plugin_a/server/custom_shipper.ts index 7d0b2bb1b6db2..dd3b99a154968 100644 --- a/test/analytics/__fixtures__/plugins/analytics_plugin_a/server/custom_shipper.ts +++ b/test/analytics/__fixtures__/plugins/analytics_plugin_a/server/custom_shipper.ts @@ -40,4 +40,5 @@ export class CustomShipper implements IShipper { extendContext(newContext: EventContext) { this.actions$.next({ action: 'extendContext', meta: newContext }); } + shutdown() {} } diff --git a/yarn.lock b/yarn.lock index 426588b11a9c4..2b4a4c4cebaa6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2932,6 +2932,18 @@ version "0.0.0" uid "" +"@kbn/analytics-shippers-elastic-v3-common@link:bazel-bin/packages/analytics/shippers/elastic_v3/common": + version "0.0.0" + uid "" + +"@kbn/analytics-shippers-elastic-v3-server@link:bazel-bin/packages/analytics/shippers/elastic_v3/server": + version "0.0.0" + uid "" + +"@kbn/analytics-shippers-elastic-v3-browser@link:bazel-bin/packages/analytics/shippers/elastic_v3/browser": + version "0.0.0" + uid "" + "@kbn/analytics-shippers-fullstory@link:bazel-bin/packages/analytics/shippers/fullstory": version "0.0.0" uid "" @@ -6032,6 +6044,18 @@ version "0.0.0" uid "" +"@types/kbn__analytics-shippers-elastic-v3-common@link:bazel-bin/packages/analytics/shippers/elastic_v3/common/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__analytics-shippers-elastic-v3-server@link:bazel-bin/packages/analytics/shippers/elastic_v3/server/npm_module_types": + version "0.0.0" + uid "" + +"@types/kbn__analytics-shippers-elastic-v3-browser@link:bazel-bin/packages/analytics/shippers/elastic_v3/browser/npm_module_types": + version "0.0.0" + uid "" + "@types/kbn__analytics-shippers-fullstory@link:bazel-bin/packages/analytics/shippers/fullstory/npm_module_types": version "0.0.0" uid "" From 57fc34e595d706206ad6357e4babe2e65e8e9f1e Mon Sep 17 00:00:00 2001 From: Abdul Wahab Zahid Date: Wed, 4 May 2022 18:39:02 +0200 Subject: [PATCH 37/68] [Synthetics] Create empty state and routes (#131431) --- .../synthetics/common/constants/plugin.ts | 1 + .../synthetics_date_picker.test.tsx | 106 +++++ .../date_picker/synthetics_date_picker.tsx | 92 +++++ .../components/common/header/action_menu.tsx | 20 + .../header/action_menu_content.test.tsx | 55 +++ .../common/header/action_menu_content.tsx | 125 ++++++ .../common/header/inspector_header_link.tsx | 42 ++ .../common/pages/not_found.test.tsx | 19 + .../components/common/pages/not_found.tsx | 52 +++ .../pages/synthetics_page_template.test.tsx | 42 ++ .../common/pages/synthetics_page_template.tsx | 91 +++++ .../wrappers/service_allowed_wrapper.tsx | 64 +++ .../monitor_add_edit_page.tsx | 22 ++ .../monitor_add_edit/use_breadcrumbs.ts | 30 ++ .../monitor_management_page.tsx | 22 ++ .../monitor_management/use_breadcrumbs.ts | 30 ++ .../synthetics_alerts_flyout_wrapper.tsx | 33 ++ .../toggle_alert_flyout_button.tsx | 31 ++ .../synthetics_alerts_flyout_wrapper.tsx | 45 +++ .../toggle_alert_flyout_button.test.tsx | 64 +++ .../alerts/toggle_alert_flyout_button.tsx | 164 ++++++++ .../overview/alerts/translations.ts | 345 +++++++++++++++++ .../empty_state/empty_state_error.tsx | 62 +++ .../empty_state/empty_state_loading.tsx | 28 ++ .../overview/empty_state/use_has_data.tsx | 37 ++ .../overview/filter_group/labels.ts | 24 ++ .../components/overview/overview_page.tsx | 33 ++ .../components/overview/use_breadcrumbs.ts | 26 ++ .../public/apps/synthetics/contexts/index.ts | 12 + .../contexts/synthetics_data_view_context.tsx | 32 ++ .../contexts/synthetics_refresh_context.tsx | 39 ++ .../contexts/synthetics_settings_context.tsx | 109 ++++++ .../synthetics_startup_plugins_context.tsx | 18 + .../contexts/synthetics_theme_context.tsx | 98 +++++ .../public/apps/synthetics/hooks/index.ts | 14 + .../synthetics/hooks/use_breadcrumbs.test.tsx | 72 ++++ .../apps/synthetics/hooks/use_breadcrumbs.ts | 86 +++++ .../synthetics}/hooks/use_breakpoints.test.ts | 0 .../synthetics}/hooks/use_breakpoints.ts | 0 .../hooks/use_filter_update.test.ts | 32 ++ .../synthetics/hooks/use_filter_update.ts | 76 ++++ .../synthetics/hooks/use_no_data_config.ts | 47 +++ .../synthetics/hooks/use_service_allowed.ts | 23 ++ .../apps/synthetics/hooks/use_telemetry.ts | 46 +++ .../synthetics/hooks/use_url_params.test.tsx | 68 ++++ .../apps/synthetics/hooks/use_url_params.ts | 94 +++++ .../public/apps/synthetics/render_app.tsx | 61 ++- .../public/apps/synthetics/routes.tsx | 184 +++++++++ .../public/apps/synthetics/state/index.ts | 13 + .../synthetics/state/index_status/actions.ts | 14 + .../apps/synthetics/state/index_status/api.ts | 14 + .../synthetics/state/index_status/effects.ts | 18 + .../synthetics/state/index_status/index.ts | 43 +++ .../state/index_status/selectors.ts | 12 + .../apps/synthetics/state/root_effect.ts | 13 + .../apps/synthetics/state/root_reducer.ts | 18 + .../public/apps/synthetics/state/store.ts | 26 ++ .../apps/synthetics/state/ui/actions.ts | 29 ++ .../public/apps/synthetics/state/ui/index.ts | 66 ++++ .../apps/synthetics/state/ui/selectors.ts | 33 ++ .../synthetics/state/utils/fetch_effect.ts | 45 +++ .../public/apps/synthetics/synthetics_app.tsx | 123 ++++++ .../utils/adapters/capabilities_adapter.ts | 21 + .../utils/adapters/index.ts} | 5 +- .../utils/api_service/api_service.ts | 127 ++++++ .../synthetics/utils/api_service/index.ts | 8 + .../synthetics/utils/kibana_service/index.ts | 8 + .../utils/kibana_service/kibana_service.ts | 49 +++ .../__mocks__/syncthetics_store.mock.ts | 30 ++ .../__mocks__/synthetics_plugin_start_mock.ts | 24 ++ .../testing/get_supported_url_params.test.ts | 118 ++++++ .../utils/testing/get_supported_url_params.ts | 106 +++++ .../utils/testing/helper_with_redux.tsx | 42 ++ .../apps/synthetics/utils/testing/index.ts | 8 + .../synthetics/utils/testing/rtl_helpers.tsx | 363 ++++++++++++++++++ .../get_supported_url_params.test.ts | 118 ++++++ .../url_params/get_supported_url_params.ts | 107 ++++++ .../apps/synthetics/utils/url_params/index.ts | 10 + .../url_params/parse_absolute_date.test.ts | 0 .../utils}/url_params/parse_absolute_date.ts | 0 .../utils}/url_params/parse_is_paused.test.ts | 0 .../utils}/url_params/parse_is_paused.ts | 0 .../utils}/url_params/parse_url_int.test.ts | 0 .../utils}/url_params/parse_url_int.ts | 0 .../url_params}/stringify_url_params.test.ts | 0 .../utils/url_params}/stringify_url_params.ts | 6 +- .../public/legacy_uptime/app/render_app.tsx | 2 +- .../app/uptime_page_template.test.tsx | 4 +- .../app/uptime_page_template.tsx | 2 +- .../common/header/action_menu_content.tsx | 2 +- .../components/common/header/page_tabs.tsx | 2 +- .../ping_timestamp/step_image_caption.tsx | 2 +- .../monitor_list/monitor_list.tsx | 2 +- .../monitor_list/columns/monitor_name_col.tsx | 2 +- .../monitor_list_drawer/most_recent_error.tsx | 2 +- .../public/legacy_uptime/hooks/index.ts | 1 - .../legacy_uptime/hooks/use_breadcrumbs.ts | 4 +- .../legacy_uptime/lib/helper/rtl_helpers.tsx | 2 +- .../url_params/get_supported_url_params.ts | 6 +- .../pages/synthetics/checks_navigation.tsx | 2 +- .../public/legacy_uptime/routes.tsx | 2 +- 101 files changed, 4442 insertions(+), 28 deletions(-) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.test.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.test.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/inspector_header_link.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.test.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/common/wrappers/service_allowed_wrapper.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_add_edit_page.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/use_breadcrumbs.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/monitor_management_page.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/use_breadcrumbs.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/synthetics_alerts_flyout_wrapper.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/synthetics_alerts_flyout_wrapper.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.test.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/translations.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_error.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_loading.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/use_has_data.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/filter_group/labels.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/overview_page.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/components/overview/use_breadcrumbs.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/contexts/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_data_view_context.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_refresh_context.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_startup_plugins_context.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_theme_context.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts rename x-pack/plugins/synthetics/public/{legacy_uptime => apps/synthetics}/hooks/use_breakpoints.test.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime => apps/synthetics}/hooks/use_breakpoints.ts (100%) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.test.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_no_data_config.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_service_allowed.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_telemetry.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.test.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/actions.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/api.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/effects.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/selectors.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/store.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/ui/actions.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/ui/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/ui/selectors.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/adapters/capabilities_adapter.ts rename x-pack/plugins/synthetics/public/apps/{synthetics_app.tsx => synthetics/utils/adapters/index.ts} (71%) create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/api_service.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/kibana_service.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/syncthetics_store.mock.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_plugin_start_mock.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.test.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/helper_with_redux.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/index.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.test.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.ts create mode 100644 x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/index.ts rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils}/url_params/parse_absolute_date.test.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils}/url_params/parse_absolute_date.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils}/url_params/parse_is_paused.test.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils}/url_params/parse_is_paused.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils}/url_params/parse_url_int.test.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils}/url_params/parse_url_int.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils/url_params}/stringify_url_params.test.ts (100%) rename x-pack/plugins/synthetics/public/{legacy_uptime/lib/helper => apps/synthetics/utils/url_params}/stringify_url_params.ts (86%) diff --git a/x-pack/plugins/synthetics/common/constants/plugin.ts b/x-pack/plugins/synthetics/common/constants/plugin.ts index c0a6ed02477f5..3ebf5227961c8 100644 --- a/x-pack/plugins/synthetics/common/constants/plugin.ts +++ b/x-pack/plugins/synthetics/common/constants/plugin.ts @@ -14,6 +14,7 @@ export const PLUGIN = { description: 'The description text that will appear in the feature catalogue.', }), ID: 'uptime', + SYNTHETICS_PLUGIN_ID: 'synthetics', LOCAL_STORAGE_KEY: 'xpack.synthetics.', NAME: i18n.translate('xpack.synthetics.featureRegistry.syntheticsFeatureName', { defaultMessage: 'Synthetics and Uptime', diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.test.tsx new file mode 100644 index 0000000000000..7040da99c39a3 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.test.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { SyntheticsDatePicker } from './synthetics_date_picker'; +import { startPlugins } from '../../../utils/testing/__mocks__/synthetics_plugin_start_mock'; +import { createMemoryHistory } from 'history'; +import { render } from '../../../utils/testing'; +import { fireEvent } from '@testing-library/dom'; + +describe('SyntheticsDatePicker component', () => { + jest.setTimeout(10_000); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('renders properly with mock data', async () => { + const { findByText } = render(); + expect(await findByText('Last 15 minutes')).toBeInTheDocument(); + expect(await findByText('Refresh')).toBeInTheDocument(); + }); + + it('uses shared date range state when there is no url date range state', async () => { + const customHistory = createMemoryHistory({ + initialEntries: ['/?dateRangeStart=now-15m&dateRangeEnd=now'], + }); + + jest.spyOn(customHistory, 'push'); + + const { findByText } = render(, { + history: customHistory, + core: startPlugins, + }); + + expect(await findByText('~ 15 minutes ago')).toBeInTheDocument(); + + expect(await findByText('~ 30 minutes ago')).toBeInTheDocument(); + + expect(customHistory.push).toHaveBeenCalledWith({ + pathname: '/', + search: 'dateRangeEnd=now-15m&dateRangeStart=now-30m', + }); + }); + + it('should use url date range even if shared date range is present', async () => { + const customHistory = createMemoryHistory({ + initialEntries: ['/?g=%22%22&dateRangeStart=now-10m&dateRangeEnd=now'], + }); + + jest.spyOn(customHistory, 'push'); + + const { findByText } = render(, { + history: customHistory, + core: startPlugins, + }); + + expect(await findByText('Last 10 minutes')).toBeInTheDocument(); + + // it should update shared state + + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenCalledWith({ + from: 'now-10m', + to: 'now', + }); + }); + + it('should handle on change', async () => { + const customHistory = createMemoryHistory({ + initialEntries: ['/?g=%22%22&dateRangeStart=now-10m&dateRangeEnd=now'], + }); + + jest.spyOn(customHistory, 'push'); + + const { findByText, getByTestId, findByTestId } = render(, { + history: customHistory, + core: startPlugins, + }); + + expect(await findByText('Last 10 minutes')).toBeInTheDocument(); + + fireEvent.click(getByTestId('superDatePickerToggleQuickMenuButton')); + + fireEvent.click(await findByTestId('superDatePickerCommonlyUsed_Today')); + + expect(await findByText('Today')).toBeInTheDocument(); + + // it should update shared state + + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenCalledTimes(2); + + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenCalledWith({ + from: 'now-10m', + to: 'now', + }); + + expect(startPlugins.data.query.timefilter.timefilter.setTime).toHaveBeenLastCalledWith({ + from: 'now/d', + to: 'now', + }); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx new file mode 100644 index 0000000000000..b9da1c098716d --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useContext, useEffect } from 'react'; +import { EuiSuperDatePicker } from '@elastic/eui'; +import { useUrlParams } from '../../../hooks'; +import { CLIENT_DEFAULTS } from '../../../../../../common/constants'; +import { + SyntheticsSettingsContext, + SyntheticsStartupPluginsContext, + SyntheticsRefreshContext, +} from '../../../contexts'; + +const isSyntheticsDefaultDateRange = (dateRangeStart: string, dateRangeEnd: string) => { + const { DATE_RANGE_START, DATE_RANGE_END } = CLIENT_DEFAULTS; + + return dateRangeStart === DATE_RANGE_START && dateRangeEnd === DATE_RANGE_END; +}; + +export const SyntheticsDatePicker = () => { + const [getUrlParams, updateUrl] = useUrlParams(); + const { commonlyUsedRanges } = useContext(SyntheticsSettingsContext); + const { refreshApp } = useContext(SyntheticsRefreshContext); + + const { data } = useContext(SyntheticsStartupPluginsContext); + + // read time from state and update the url + const sharedTimeState = data?.query.timefilter.timefilter.getTime(); + + const { + autorefreshInterval, + autorefreshIsPaused, + dateRangeStart: start, + dateRangeEnd: end, + } = getUrlParams(); + + useEffect(() => { + const { from, to } = sharedTimeState ?? {}; + // if it's synthetics default range, and we have shared state from kibana, let's use that + if (isSyntheticsDefaultDateRange(start, end) && (from !== start || to !== end)) { + updateUrl({ dateRangeStart: from, dateRangeEnd: to }); + } else if (from !== start || to !== end) { + // if it's coming url. let's update shared state + data?.query.timefilter.timefilter.setTime({ from: start, to: end }); + } + + // only need at start, rest date picker on change fucn will take care off + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const euiCommonlyUsedRanges = commonlyUsedRanges + ? commonlyUsedRanges.map( + ({ from, to, display }: { from: string; to: string; display: string }) => { + return { + start: from, + end: to, + label: display, + }; + } + ) + : CLIENT_DEFAULTS.COMMONLY_USED_DATE_RANGES; + + return ( + { + if (data?.query?.timefilter?.timefilter) { + data?.query.timefilter.timefilter.setTime({ from: startN, to: endN }); + } + + updateUrl({ dateRangeStart: startN, dateRangeEnd: endN }); + refreshApp(); + }} + onRefresh={refreshApp} + onRefreshChange={({ isPaused, refreshInterval }) => { + updateUrl({ + autorefreshInterval: + refreshInterval === undefined ? autorefreshInterval : refreshInterval, + autorefreshIsPaused: isPaused, + }); + }} + /> + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu.tsx new file mode 100644 index 0000000000000..69821360aab8b --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu.tsx @@ -0,0 +1,20 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { HeaderMenuPortal } from '@kbn/observability-plugin/public'; +import { AppMountParameters } from '@kbn/core/public'; +import { ActionMenuContent } from './action_menu_content'; + +export const ActionMenu = ({ appMountParameters }: { appMountParameters: AppMountParameters }) => ( + + + +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.test.tsx new file mode 100644 index 0000000000000..3137862025f15 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.test.tsx @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { fireEvent, waitFor } from '@testing-library/react'; +import { render } from '../../../utils/testing/rtl_helpers'; +import { ActionMenuContent } from './action_menu_content'; + +describe('ActionMenuContent', () => { + it('renders alerts dropdown', async () => { + const { getByLabelText, getByText } = render(); + + const alertsDropdown = getByLabelText('Open alerts and rules context menu'); + fireEvent.click(alertsDropdown); + + await waitFor(() => { + expect(getByText('Create rule')); + expect(getByText('Manage rules')); + }); + }); + + it('renders settings link', () => { + const { getByRole, getByText } = render(); + + const settingsAnchor = getByRole('link', { name: 'Navigate to the Uptime settings page' }); + expect(settingsAnchor.getAttribute('href')).toBe('/settings'); + expect(getByText('Settings')); + }); + + it('renders exploratory view link', () => { + const { getByLabelText, getByText } = render(); + + const analyzeAnchor = getByLabelText( + 'Navigate to the "Explore Data" view to visualize Synthetics/User data' + ); + + expect(analyzeAnchor.getAttribute('href')).toContain('/app/observability/exploratory-view'); + expect(getByText('Explore data')); + }); + + it('renders Add Data link', () => { + const { getByLabelText, getByText } = render(); + + const addDataAnchor = getByLabelText('Navigate to a tutorial about adding Uptime data'); + + // this href value is mocked, so it doesn't correspond to the real link + // that Kibana core services will provide + expect(addDataAnchor.getAttribute('href')).toBe('/home#/tutorial/uptimeMonitors'); + expect(getByText('Add data')); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.tsx new file mode 100644 index 0000000000000..6d3d83146a42c --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/action_menu_content.tsx @@ -0,0 +1,125 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiHeaderLinks, EuiToolTip, EuiHeaderLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { useHistory, useRouteMatch } from 'react-router-dom'; +import { createExploratoryViewUrl } from '@kbn/observability-plugin/public'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useSyntheticsSettingsContext } from '../../../contexts'; +import { useGetUrlParams } from '../../../hooks'; +import { ToggleAlertFlyoutButton } from '../../overview/alerts/alerts_containers/toggle_alert_flyout_button'; +import { MONITOR_ROUTE, SETTINGS_ROUTE } from '../../../../../../common/constants'; +import { stringifyUrlParams } from '../../../utils/url_params'; +import { InspectorHeaderLink } from './inspector_header_link'; +// import { monitorStatusSelector } from '../../../state/selectors'; +// import { ManageMonitorsBtn } from './manage_monitors_btn'; + +const ADD_DATA_LABEL = i18n.translate('xpack.synthetics.addDataButtonLabel', { + defaultMessage: 'Add data', +}); + +const ANALYZE_DATA = i18n.translate('xpack.synthetics.analyzeDataButtonLabel', { + defaultMessage: 'Explore data', +}); + +const ANALYZE_MESSAGE = i18n.translate('xpack.synthetics.analyzeDataButtonLabel.message', { + defaultMessage: + 'Explore Data allows you to select and filter result data in any dimension and look for the cause or impact of performance problems.', +}); + +export function ActionMenuContent(): React.ReactElement { + const kibana = useKibana(); + const { basePath } = useSyntheticsSettingsContext(); + const params = useGetUrlParams(); + const { dateRangeStart, dateRangeEnd } = params; + const history = useHistory(); + + const selectedMonitor = { + monitor: { id: undefined, name: 'test' }, + }; /* useSelector(monitorStatusSelector) TODO: Implement state for monitor status */ + + const detailRouteMatch = useRouteMatch(MONITOR_ROUTE); + const monitorId = selectedMonitor?.monitor?.id; + + const syntheticExploratoryViewLink = createExploratoryViewUrl( + { + reportType: 'kpi-over-time', + allSeries: [ + { + dataType: 'synthetics', + seriesType: 'area', + selectedMetricField: 'monitor.duration.us', + time: { from: dateRangeStart, to: dateRangeEnd }, + breakdown: monitorId ? 'observer.geo.name' : 'monitor.type', + reportDefinitions: { + 'monitor.name': + selectedMonitor?.monitor?.name && detailRouteMatch?.isExact === true + ? [selectedMonitor?.monitor?.name] + : [], + 'url.full': ['ALL_VALUES'], + }, + name: monitorId ? `${monitorId}-response-duration` : 'All monitors response duration', + }, + ], + }, + basePath + ); + + return ( + + {/* TODO: See if it's needed for new Synthetics App */} + + + + + + + + {ANALYZE_MESSAGE}

}> + + {ANALYZE_DATA} + +
+ + + {ADD_DATA_LABEL} + + +
+ ); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/inspector_header_link.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/inspector_header_link.tsx new file mode 100644 index 0000000000000..b1166d342ff3e --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/header/inspector_header_link.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiHeaderLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { enableInspectEsQueries, useInspectorContext } from '@kbn/observability-plugin/public'; +import { ClientPluginsStart } from '../../../../../plugin'; +import { useSyntheticsSettingsContext } from '../../../contexts'; + +export function InspectorHeaderLink() { + const { + services: { inspector, uiSettings }, + } = useKibana(); + + const { isDev } = useSyntheticsSettingsContext(); + + const { inspectorAdapters } = useInspectorContext(); + + const isInspectorEnabled = uiSettings?.get(enableInspectEsQueries); + + const inspect = () => { + inspector.open(inspectorAdapters); + }; + + if (!isInspectorEnabled && !isDev) { + return null; + } + + return ( + + {i18n.translate('xpack.synthetics.inspectButtonText', { + defaultMessage: 'Inspect', + })} + + ); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.test.tsx new file mode 100644 index 0000000000000..0bade3c639a5e --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.test.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { NotFoundPage } from './not_found'; +import { render } from '../../../utils/testing'; + +describe('NotFoundPage', () => { + it('render component', async () => { + const { findByText } = render(); + + expect(await findByText('Page not found')).toBeInTheDocument(); + expect(await findByText('Back to home')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.tsx new file mode 100644 index 0000000000000..c94a7a7a06b6a --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/not_found.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiEmptyPrompt, + EuiPanel, + EuiTitle, + EuiFlexGroup, + EuiFlexItem, + EuiButton, +} from '@elastic/eui'; +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { FormattedMessage } from '@kbn/i18n-react'; + +export const NotFoundPage = () => { + const history = useHistory(); + return ( + + + + +

+ +

+ + } + body={ + + + + } + /> +
+
+
+ ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx new file mode 100644 index 0000000000000..2c8201a175159 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.test.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// app.test.js +import React from 'react'; +import 'jest-styled-components'; +import { render } from '../../../utils/testing/rtl_helpers'; +import { SyntheticsPageTemplateComponent } from './synthetics_page_template'; +import { OVERVIEW_ROUTE } from '../../../../../../common/constants'; +import { useBreakpoints } from '../../../hooks/use_breakpoints'; + +jest.mock('../../../hooks/use_breakpoints', () => { + const down = jest.fn().mockReturnValue(false); + return { + useBreakpoints: () => ({ down }), + }; +}); + +describe('SyntheticsPageTemplateComponent', () => { + describe('styling', () => { + // In this test we use snapshots because we're asserting on generated + // styles. Writing assertions manually here could make this test really + // convoluted, and it require us to manually update styling strings + // according to `styled-components` generator, which is counter-productive. + // In general, however, we avoid snaphshot tests. + + it('does not apply header centering on bigger resolutions', () => { + const { container } = render(); + expect(container.firstChild).toBeDefined(); + }); + + it('applies the header centering on mobile', () => { + (useBreakpoints().down as jest.Mock).mockReturnValue(true); + const { container } = render(); + expect(container.firstChild).toBeDefined(); + }); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx new file mode 100644 index 0000000000000..0e6c5565b842e --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/pages/synthetics_page_template.tsx @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useEffect, useMemo } from 'react'; +import styled from 'styled-components'; +import { EuiPageHeaderProps, EuiPageTemplateProps } from '@elastic/eui'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useInspectorContext } from '@kbn/observability-plugin/public'; +import { CERTIFICATES_ROUTE, OVERVIEW_ROUTE } from '../../../../../../common/constants'; +import { ClientPluginsStart } from '../../../../../plugin'; +import { useNoDataConfig } from '../../../hooks/use_no_data_config'; +import { EmptyStateLoading } from '../../overview/empty_state/empty_state_loading'; +import { EmptyStateError } from '../../overview/empty_state/empty_state_error'; +import { useHasData } from '../../overview/empty_state/use_has_data'; +import { useBreakpoints } from '../../../hooks'; + +interface Props { + path: string; + pageHeader?: EuiPageHeaderProps; +} + +const mobileCenteredHeader = ` + .euiPageHeaderContent > .euiFlexGroup > .euiFlexItem { + align-items: center; + } +`; + +export const SyntheticsPageTemplateComponent: React.FC = ({ + path, + pageHeader, + children, + ...pageTemplateProps +}) => { + const { + services: { observability }, + } = useKibana(); + const { down } = useBreakpoints(); + const isMobile = down('s'); + + const PageTemplateComponent = observability.navigation.PageTemplate; + const StyledPageTemplateComponent = useMemo(() => { + return styled(PageTemplateComponent)<{ isMobile: boolean }>` + .euiPageHeaderContent > .euiFlexGroup { + flex-wrap: wrap; + } + + ${(props) => (props.isMobile ? mobileCenteredHeader : '')} + `; + }, [PageTemplateComponent]); + + const noDataConfig = useNoDataConfig(); + + const { loading, error, data } = useHasData(); + const { inspectorAdapters } = useInspectorContext(); + + useEffect(() => { + inspectorAdapters.requests.reset(); + }, [inspectorAdapters.requests]); + + if (error) { + return ; + } + + const isMainRoute = path === OVERVIEW_ROUTE || path === CERTIFICATES_ROUTE; + + const showLoading = loading && isMainRoute && !data; + + return ( + <> + + {showLoading && } +
+ {children} +
+
+ + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/common/wrappers/service_allowed_wrapper.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/wrappers/service_allowed_wrapper.tsx new file mode 100644 index 0000000000000..163ed0d37b7c3 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/common/wrappers/service_allowed_wrapper.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiEmptyPrompt, EuiLoadingLogo } from '@elastic/eui'; +import { useSyntheticsServiceAllowed } from '../../../hooks/use_service_allowed'; + +export const ServiceAllowedWrapper: React.FC = ({ children }) => { + const { isAllowed, signupUrl, loading } = useSyntheticsServiceAllowed(); + + if (loading) { + return ( + } + title={

{LOADING_MONITOR_MANAGEMENT_LABEL}

} + /> + ); + } + + // checking for explicit false + if (isAllowed === false) { + return ( + {MONITOR_MANAGEMENT_LABEL}} + body={

{PUBLIC_BETA_DESCRIPTION}

} + actions={[ + + {REQUEST_ACCESS_LABEL} + , + ]} + /> + ); + } + + return <>{children}; +}; + +const REQUEST_ACCESS_LABEL = i18n.translate('xpack.synthetics.monitorManagement.requestAccess', { + defaultMessage: 'Request access', +}); + +export const MONITOR_MANAGEMENT_LABEL = i18n.translate('xpack.synthetics.monitorManagement.label', { + defaultMessage: 'Monitor Management', +}); + +const LOADING_MONITOR_MANAGEMENT_LABEL = i18n.translate( + 'xpack.synthetics.monitorManagement.loading.label', + { + defaultMessage: 'Loading Monitor Management', + } +); + +export const PUBLIC_BETA_DESCRIPTION = i18n.translate( + 'xpack.synthetics.monitorManagement.publicBetaDescription', + { + defaultMessage: + "We've got a brand new app on the way. In the meantime, we're excited to give you early access to our globally managed testing infrastructure. This will allow you to upload synthetic monitors using our new point and click script recorder and manage your monitors with a new UI.", + } +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_add_edit_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_add_edit_page.tsx new file mode 100644 index 0000000000000..d0a0c04150f8d --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/monitor_add_edit_page.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { useTrackPageview } from '@kbn/observability-plugin/public'; +import { useMonitorAddEditBreadcrumbs } from './use_breadcrumbs'; + +export const MonitorAddEditPage: React.FC = () => { + useTrackPageview({ app: 'synthetics', path: 'add-monitor' }); + useTrackPageview({ app: 'synthetics', path: 'add-monitor', delay: 15000 }); + useMonitorAddEditBreadcrumbs(); + + return ( + <> +

Monitor Add or Edit page

+ + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/use_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/use_breadcrumbs.ts new file mode 100644 index 0000000000000..2fb17340c25fc --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_add_edit/use_breadcrumbs.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { i18n } from '@kbn/i18n'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; +import { MONITOR_ADD_ROUTE } from '../../../../../common/constants'; +import { PLUGIN } from '../../../../../common/constants/plugin'; + +export const useMonitorAddEditBreadcrumbs = () => { + const kibana = useKibana(); + const appPath = kibana.services.application?.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) ?? ''; + + useBreadcrumbs([ + { + text: ADD_MONITOR_CRUMB, + href: `${appPath}/${MONITOR_ADD_ROUTE}`, + }, + ]); +}; + +export const ADD_MONITOR_CRUMB = i18n.translate( + 'xpack.synthetics.monitorManagement.addMonitorCrumb', + { + defaultMessage: 'Add monitor', + } +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/monitor_management_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/monitor_management_page.tsx new file mode 100644 index 0000000000000..c4ca665563f0d --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/monitor_management_page.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { useTrackPageview } from '@kbn/observability-plugin/public'; +import { useMonitorManagementBreadcrumbs } from './use_breadcrumbs'; + +export const MonitorManagementPage: React.FC = () => { + useTrackPageview({ app: 'synthetics', path: 'manage-monitors' }); + useTrackPageview({ app: 'synthetics', path: 'manage-monitors', delay: 15000 }); + useMonitorManagementBreadcrumbs(); + + return ( + <> +

Monitor Management List page (Monitor Management Page)

+ + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/use_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/use_breadcrumbs.ts new file mode 100644 index 0000000000000..ab44c1b7c37a2 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/monitor_management/use_breadcrumbs.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { i18n } from '@kbn/i18n'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; +import { MONITOR_MANAGEMENT_ROUTE } from '../../../../../common/constants'; +import { PLUGIN } from '../../../../../common/constants/plugin'; + +export const useMonitorManagementBreadcrumbs = () => { + const kibana = useKibana(); + const appPath = kibana.services.application?.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) ?? ''; + + useBreadcrumbs([ + { + text: MONITOR_MANAGEMENT_CRUMB, + href: `${appPath}/${MONITOR_MANAGEMENT_ROUTE}/all`, + }, + ]); +}; + +const MONITOR_MANAGEMENT_CRUMB = i18n.translate( + 'xpack.synthetics.monitorManagementPage.monitorManagementCrumb', + { + defaultMessage: 'Monitor Management', + } +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/synthetics_alerts_flyout_wrapper.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/synthetics_alerts_flyout_wrapper.tsx new file mode 100644 index 0000000000000..7271e8cd2e998 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/synthetics_alerts_flyout_wrapper.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { + selectAlertFlyoutVisibility, + selectAlertFlyoutType, + setAlertFlyoutVisible, +} from '../../../../state'; +import { SyntheticsAlertsFlyoutWrapperComponent } from '../synthetics_alerts_flyout_wrapper'; + +export const SyntheticsAlertsFlyoutWrapper: React.FC = () => { + const dispatch = useDispatch(); + const setAddFlyoutVisibility = (value: React.SetStateAction) => + // @ts-ignore the value here is a boolean, and it works with the action creator function + dispatch(setAlertFlyoutVisible(value)); + + const alertFlyoutVisible = useSelector(selectAlertFlyoutVisibility); + const alertTypeId = useSelector(selectAlertFlyoutType); + + return ( + + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx new file mode 100644 index 0000000000000..2fea38d99d094 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/alerts_containers/toggle_alert_flyout_button.tsx @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { useDispatch } from 'react-redux'; +import { setAlertFlyoutType, setAlertFlyoutVisible } from '../../../../state'; +import { + ToggleAlertFlyoutButtonComponent, + ToggleAlertFlyoutButtonProps, +} from '../toggle_alert_flyout_button'; + +export const ToggleAlertFlyoutButton: React.FC = (props) => { + const dispatch = useDispatch(); + return ( + { + if (typeof value === 'string') { + dispatch(setAlertFlyoutType(value)); + dispatch(setAlertFlyoutVisible(true)); + } else { + dispatch(setAlertFlyoutVisible(value)); + } + }} + /> + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/synthetics_alerts_flyout_wrapper.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/synthetics_alerts_flyout_wrapper.tsx new file mode 100644 index 0000000000000..33c76176787cf --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/synthetics_alerts_flyout_wrapper.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; + +interface Props { + alertFlyoutVisible: boolean; + alertTypeId?: string; + setAlertFlyoutVisibility: React.Dispatch>; +} + +interface KibanaDeps { + triggersActionsUi: TriggersAndActionsUIPublicPluginStart; +} + +export const SyntheticsAlertsFlyoutWrapperComponent = ({ + alertFlyoutVisible, + alertTypeId, + setAlertFlyoutVisibility, +}: Props) => { + const { triggersActionsUi } = useKibana().services; + const onCloseAlertFlyout = useCallback( + () => setAlertFlyoutVisibility(false), + [setAlertFlyoutVisibility] + ); + const AddAlertFlyout = useMemo( + () => + triggersActionsUi.getAddAlertFlyout({ + consumer: 'synthetics', + onClose: onCloseAlertFlyout, + ruleTypeId: alertTypeId, + canChangeTrigger: !alertTypeId, + }), + // eslint-disable-next-line react-hooks/exhaustive-deps + [onCloseAlertFlyout, alertTypeId] + ); + + return <>{alertFlyoutVisible && AddAlertFlyout}; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.test.tsx new file mode 100644 index 0000000000000..b185d3897d243 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.test.tsx @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import userEvent from '@testing-library/user-event'; +import { render, forNearestButton, makeSyntheticsPermissionsCore } from '../../../utils/testing'; +import { ToggleAlertFlyoutButtonComponent } from './toggle_alert_flyout_button'; +import { ToggleFlyoutTranslations } from './translations'; + +describe('ToggleAlertFlyoutButtonComponent', () => { + describe('when users have write access to synthetics', () => { + it('enables the button to create a rule', () => { + const { getByText } = render( + , + { core: makeSyntheticsPermissionsCore({ save: true }) } + ); + userEvent.click(getByText('Alerts and rules')); + expect( + forNearestButton(getByText)(ToggleFlyoutTranslations.openAlertContextPanelLabel) + ).toBeEnabled(); + }); + + it("does not contain a tooltip explaining why the user can't create alerts", async () => { + const { getByText, findByText } = render( + , + { core: makeSyntheticsPermissionsCore({ save: true }) } + ); + userEvent.click(getByText('Alerts and rules')); + userEvent.hover(getByText(ToggleFlyoutTranslations.openAlertContextPanelLabel)); + await expect(() => + findByText('You need read-write access to Synthetics to create alerts in this app.') + ).rejects.toEqual(expect.anything()); + }); + }); + + describe("when users don't have write access to uptime", () => { + it('disables the button to create a rule', () => { + const { getByText } = render( + , + { core: makeSyntheticsPermissionsCore({ save: false }) } + ); + userEvent.click(getByText('Alerts and rules')); + expect( + forNearestButton(getByText)(ToggleFlyoutTranslations.openAlertContextPanelLabel) + ).toBeDisabled(); + }); + + it("contains a tooltip explaining why users can't create rules", async () => { + const { getByText, findByText } = render( + , + { core: makeSyntheticsPermissionsCore({ save: false }) } + ); + userEvent.click(getByText('Alerts and rules')); + userEvent.hover(getByText(ToggleFlyoutTranslations.openAlertContextPanelLabel)); + expect( + await findByText('You need read-write access to Uptime to create alerts in this app.') + ).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.tsx new file mode 100644 index 0000000000000..f29fe0941ee82 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/toggle_alert_flyout_button.tsx @@ -0,0 +1,164 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiHeaderLink, + EuiContextMenu, + EuiContextMenuPanelDescriptor, + EuiContextMenuPanelItemDescriptor, + EuiLink, + EuiPopover, +} from '@elastic/eui'; +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { CLIENT_ALERT_TYPES } from '../../../../../../common/constants/alerts'; +import { ClientPluginsStart } from '../../../../../plugin'; + +import { ToggleFlyoutTranslations } from './translations'; + +interface ComponentProps { + setAlertFlyoutVisible: (value: boolean | string) => void; +} + +export interface ToggleAlertFlyoutButtonProps { + alertOptions?: string[]; +} + +type Props = ComponentProps & ToggleAlertFlyoutButtonProps; + +const ALERT_CONTEXT_MAIN_PANEL_ID = 0; +const ALERT_CONTEXT_SELECT_TYPE_PANEL_ID = 1; + +const noWritePermissionsTooltipContent = i18n.translate( + 'xpack.synthetics.alertDropdown.noWritePermissions', + { + defaultMessage: 'You need read-write access to Uptime to create alerts in this app.', + } +); + +export const ToggleAlertFlyoutButtonComponent: React.FC = ({ + alertOptions, + setAlertFlyoutVisible, +}) => { + const [isOpen, setIsOpen] = useState(false); + const kibana = useKibana(); + const { + services: { observability }, + } = useKibana(); + const manageRulesUrl = observability.useRulesLink(); + const hasUptimeWrite = kibana.services.application?.capabilities.uptime?.save ?? false; + + const monitorStatusAlertContextMenuItem: EuiContextMenuPanelItemDescriptor = { + 'aria-label': ToggleFlyoutTranslations.toggleMonitorStatusAriaLabel, + 'data-test-subj': 'xpack.synthetics.toggleAlertFlyout', + name: ToggleFlyoutTranslations.toggleMonitorStatusContent, + onClick: () => { + setAlertFlyoutVisible(CLIENT_ALERT_TYPES.MONITOR_STATUS); + setIsOpen(false); + }, + }; + + const tlsAlertContextMenuItem: EuiContextMenuPanelItemDescriptor = { + 'aria-label': ToggleFlyoutTranslations.toggleTlsAriaLabel, + 'data-test-subj': 'xpack.synthetics.toggleTlsAlertFlyout', + name: ToggleFlyoutTranslations.toggleTlsContent, + onClick: () => { + setAlertFlyoutVisible(CLIENT_ALERT_TYPES.TLS); + setIsOpen(false); + }, + }; + + const managementContextItem: EuiContextMenuPanelItemDescriptor = { + 'aria-label': ToggleFlyoutTranslations.navigateToAlertingUIAriaLabel, + 'data-test-subj': 'xpack.synthetics.navigateToAlertingUi', + name: ( + + + + ), + icon: 'tableOfContents', + }; + + let selectionItems: EuiContextMenuPanelItemDescriptor[] = []; + if (!alertOptions) { + selectionItems = [monitorStatusAlertContextMenuItem, tlsAlertContextMenuItem]; + } else { + alertOptions.forEach((option) => { + if (option === CLIENT_ALERT_TYPES.MONITOR_STATUS) + selectionItems.push(monitorStatusAlertContextMenuItem); + else if (option === CLIENT_ALERT_TYPES.TLS) selectionItems.push(tlsAlertContextMenuItem); + }); + } + + if (selectionItems.length === 1) { + selectionItems[0].icon = 'bell'; + } + + let panels: EuiContextMenuPanelDescriptor[]; + if (selectionItems.length === 1) { + panels = [ + { + id: ALERT_CONTEXT_MAIN_PANEL_ID, + items: [...selectionItems, managementContextItem], + }, + ]; + } else { + panels = [ + { + id: ALERT_CONTEXT_MAIN_PANEL_ID, + items: [ + { + 'aria-label': ToggleFlyoutTranslations.openAlertContextPanelAriaLabel, + 'data-test-subj': 'xpack.synthetics.openAlertContextPanel', + name: ToggleFlyoutTranslations.openAlertContextPanelLabel, + icon: 'bell', + panel: ALERT_CONTEXT_SELECT_TYPE_PANEL_ID, + toolTipContent: !hasUptimeWrite ? noWritePermissionsTooltipContent : null, + disabled: !hasUptimeWrite, + }, + managementContextItem, + ], + }, + { + id: ALERT_CONTEXT_SELECT_TYPE_PANEL_ID, + title: ToggleFlyoutTranslations.toggleAlertFlyoutButtonLabel, + items: selectionItems, + }, + ]; + } + + return ( + setIsOpen(!isOpen)} + > + + + } + closePopover={() => setIsOpen(false)} + isOpen={isOpen} + ownFocus + panelPaddingSize="none" + > + + + ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/translations.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/translations.ts new file mode 100644 index 0000000000000..0580528b6b38c --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/alerts/translations.ts @@ -0,0 +1,345 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const SECONDS_TIME_RANGE = i18n.translate( + 'xpack.synthetics.alerts.timerangeUnitSelectable.secondsOption.ariaLabel', + { + defaultMessage: '"Seconds" time range select item', + } +); + +export const SECONDS = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.timerangeOption.seconds', + { + defaultMessage: 'seconds', + } +); + +export const MINUTES_TIME_RANGE = i18n.translate( + 'xpack.synthetics.alerts.timerangeUnitSelectable.minutesOption.ariaLabel', + { + defaultMessage: '"Minutes" time range select item', + } +); + +export const MINUTES = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.timerangeOption.minutes', + { + defaultMessage: 'minutes', + } +); + +export const HOURS_TIME_RANGE = i18n.translate( + 'xpack.synthetics.alerts.timerangeUnitSelectable.hoursOption.ariaLabel', + { + defaultMessage: '"Hours" time range select item', + } +); + +export const HOURS = i18n.translate('xpack.synthetics.alerts.monitorStatus.timerangeOption.hours', { + defaultMessage: 'hours', +}); + +export const DAYS_TIME_RANGE = i18n.translate( + 'xpack.synthetics.alerts.timerangeUnitSelectable.daysOption.ariaLabel', + { + defaultMessage: '"Days" time range select item', + } +); + +export const DAYS = i18n.translate('xpack.synthetics.alerts.monitorStatus.timerangeOption.days', { + defaultMessage: 'days', +}); + +export const WEEKS_TIME_RANGE = i18n.translate( + 'xpack.synthetics.alerts.timerangeUnitSelectable.weeksOption.ariaLabel', + { + defaultMessage: '"Weeks" time range select item', + } +); + +export const WEEKS = i18n.translate('xpack.synthetics.alerts.monitorStatus.timerangeOption.weeks', { + defaultMessage: 'weeks', +}); + +export const MONTHS_TIME_RANGE = i18n.translate( + 'xpack.synthetics.alerts.timerangeUnitSelectable.monthsOption.ariaLabel', + { + defaultMessage: '"Months" time range select item', + } +); + +export const MONTHS = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.timerangeOption.months', + { + defaultMessage: 'months', + } +); + +export const YEARS_TIME_RANGE = i18n.translate( + 'xpack.synthetics.alerts.timerangeUnitSelectable.yearsOption.ariaLabel', + { + defaultMessage: '"Years" time range select item', + } +); + +export const YEARS = i18n.translate('xpack.synthetics.alerts.monitorStatus.timerangeOption.years', { + defaultMessage: 'years', +}); + +export const ALERT_KUERY_BAR_ARIA = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.filterBar.ariaLabel', + { + defaultMessage: 'Input that allows filtering criteria for the monitor status alert', + } +); + +export const OPEN_THE_POPOVER_DOWN_COUNT = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.numTimesExpression.ariaLabel', + { + defaultMessage: 'Open the popover for down count input', + } +); + +export const ENTER_NUMBER_OF_DOWN_COUNTS = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.numTimesField.ariaLabel', + { + defaultMessage: 'Enter number of down counts required to trigger the alert', + } +); + +export const MATCHING_MONITORS_DOWN = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.numTimesExpression.matchingMonitors.description', + { + defaultMessage: 'matching monitors are down >', + } +); + +export const ANY_MONITOR_DOWN = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.numTimesExpression.anyMonitors.description', + { + defaultMessage: 'any monitor is down >', + } +); + +export const OPEN_THE_POPOVER_TIME_RANGE_VALUE = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.timerangeValueExpression.ariaLabel', + { + defaultMessage: 'Open the popover for time range value field', + } +); + +export const ENTER_NUMBER_OF_TIME_UNITS = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.timerangeValueField.ariaLabel', + { + defaultMessage: `Enter the number of time units for the alert's range`, + } +); + +export const ENTER_NUMBER_OF_TIME_UNITS_DESCRIPTION = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.timerangeValueField.expression', + { + defaultMessage: 'within', + } +); + +export const ENTER_NUMBER_OF_TIME_UNITS_VALUE = (value: number) => + i18n.translate('xpack.synthetics.alerts.monitorStatus.timerangeValueField.value', { + defaultMessage: 'last {value}', + values: { value }, + }); + +export const ENTER_AVAILABILITY_RANGE_ENABLED = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.isEnabledCheckbox.label', + { + defaultMessage: 'Availability', + } +); + +export const ENTER_AVAILABILITY_RANGE_POPOVER_ARIA_LABEL = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.timerangeValueField.popover.ariaLabel', + { + defaultMessage: 'Specify availability tracking time range', + } +); + +export const ENTER_AVAILABILITY_RANGE_UNITS_ARIA_LABEL = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.timerangeValueField.ariaLabel', + { + defaultMessage: `Enter the number of units for the alert's availability check.`, + } +); + +export const ENTER_AVAILABILITY_RANGE_UNITS_DESCRIPTION = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.timerangeValueField.expression', + { + defaultMessage: 'within the last', + } +); + +export const ENTER_AVAILABILITY_THRESHOLD_ARIA_LABEL = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.threshold.ariaLabel', + { + defaultMessage: 'Specify availability thresholds for this alert', + } +); + +export const ENTER_AVAILABILITY_THRESHOLD_INPUT_ARIA_LABEL = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.threshold.input.ariaLabel', + { + defaultMessage: 'Input an availability threshold to check for this alert', + } +); + +export const ENTER_AVAILABILITY_THRESHOLD_DESCRIPTION = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.threshold.description', + { + defaultMessage: 'matching monitors are up in', + description: + 'This fragment explains that an alert will fire for monitors matching user-specified criteria', + } +); + +export const ENTER_ANY_AVAILABILITY_THRESHOLD_DESCRIPTION = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.threshold.anyMonitorDescription', + { + defaultMessage: 'any monitor is up in', + description: + 'This fragment explains that an alert will fire for monitors matching user-specified criteria', + } +); + +export const ENTER_AVAILABILITY_THRESHOLD_VALUE = (value: string) => + i18n.translate('xpack.synthetics.alerts.monitorStatus.availability.threshold.value', { + defaultMessage: '< {value}% of checks', + description: + 'This fragment specifies criteria that will cause an alert to fire for uptime monitors', + values: { value }, + }); + +export const ENTER_AVAILABILITY_RANGE_SELECT_ARIA = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.unit.selectable', + { + defaultMessage: 'Use this select to set the availability range units for this alert', + } +); + +export const ENTER_AVAILABILITY_RANGE_SELECT_HEADLINE = i18n.translate( + 'xpack.synthetics.alerts.monitorStatus.availability.unit.headline', + { + defaultMessage: 'Select time range unit', + } +); + +export const ADD_FILTER = i18n.translate('xpack.synthetics.alerts.monitorStatus.addFilter', { + defaultMessage: `Add filter`, +}); + +export const LOCATION = i18n.translate('xpack.synthetics.alerts.monitorStatus.addFilter.location', { + defaultMessage: `Location`, +}); + +export const TAG = i18n.translate('xpack.synthetics.alerts.monitorStatus.addFilter.tag', { + defaultMessage: `Tag`, +}); + +export const PORT = i18n.translate('xpack.synthetics.alerts.monitorStatus.addFilter.port', { + defaultMessage: `Port`, +}); + +export const TYPE = i18n.translate('xpack.synthetics.alerts.monitorStatus.addFilter.type', { + defaultMessage: `Type`, +}); + +export const TlsTranslations = { + criteriaAriaLabel: i18n.translate('xpack.synthetics.alerts.tls.criteriaExpression.ariaLabel', { + defaultMessage: + 'An expression displaying the criteria for monitor that are watched by this alert', + }), + criteriaDescription: i18n.translate( + 'xpack.synthetics.alerts.tls.criteriaExpression.description', + { + defaultMessage: 'when', + description: + 'The context of this `when` is in the conditional sense, like "when there are three cookies, eat them all".', + } + ), + criteriaValue: i18n.translate('xpack.synthetics.alerts.tls.criteriaExpression.value', { + defaultMessage: 'any monitor', + }), + expirationAriaLabel: i18n.translate( + 'xpack.synthetics.alerts.tls.expirationExpression.ariaLabel', + { + defaultMessage: + 'An expression displaying the threshold that will trigger the TLS alert for certificate expiration', + } + ), + expirationDescription: i18n.translate( + 'xpack.synthetics.alerts.tls.expirationExpression.description', + { + defaultMessage: 'has a certificate expiring within', + } + ), + expirationValue: (value?: number) => + i18n.translate('xpack.synthetics.alerts.tls.expirationExpression.value', { + defaultMessage: '{value} days', + values: { value }, + }), + ageAriaLabel: i18n.translate('xpack.synthetics.alerts.tls.ageExpression.ariaLabel', { + defaultMessage: + 'An expressing displaying the threshold that will trigger the TLS alert for old certificates', + }), + ageDescription: i18n.translate('xpack.synthetics.alerts.tls.ageExpression.description', { + defaultMessage: 'or older than', + }), + ageValue: (value?: number) => + i18n.translate('xpack.synthetics.alerts.tls.ageExpression.value', { + defaultMessage: '{value} days', + values: { value }, + }), +}; + +export const ToggleFlyoutTranslations = { + toggleButtonAriaLabel: i18n.translate('xpack.synthetics.alertsPopover.toggleButton.ariaLabel', { + defaultMessage: 'Open alerts and rules context menu', + }), + openAlertContextPanelAriaLabel: i18n.translate( + 'xpack.synthetics.openAlertContextPanel.ariaLabel', + { + defaultMessage: 'Open the rule context panel so you can choose a rule type', + } + ), + openAlertContextPanelLabel: i18n.translate('xpack.synthetics.openAlertContextPanel.label', { + defaultMessage: 'Create rule', + }), + toggleTlsAriaLabel: i18n.translate('xpack.synthetics.toggleTlsAlertButton.ariaLabel', { + defaultMessage: 'Open TLS rule flyout', + }), + toggleTlsContent: i18n.translate('xpack.synthetics.toggleTlsAlertButton.content', { + defaultMessage: 'TLS rule', + }), + toggleMonitorStatusAriaLabel: i18n.translate('xpack.synthetics.toggleAlertFlyout.ariaLabel', { + defaultMessage: 'Open add rule flyout', + }), + toggleMonitorStatusContent: i18n.translate('xpack.synthetics.toggleAlertButton.content', { + defaultMessage: 'Monitor status rule', + }), + navigateToAlertingUIAriaLabel: i18n.translate('xpack.synthetics.navigateToAlertingUi', { + defaultMessage: 'Leave Uptime and go to Alerting Management page', + }), + navigateToAlertingButtonContent: i18n.translate( + 'xpack.synthetics.navigateToAlertingButton.content', + { + defaultMessage: 'Manage rules', + } + ), + toggleAlertFlyoutButtonLabel: i18n.translate('xpack.synthetics.alerts.createRulesPanel.title', { + defaultMessage: 'Create rules', + }), +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_error.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_error.tsx new file mode 100644 index 0000000000000..3f2150169e2df --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_error.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiEmptyPrompt, EuiPanel, EuiTitle, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React, { Fragment } from 'react'; +import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; + +interface EmptyStateErrorProps { + errors: Array>; +} + +export const EmptyStateError = ({ errors }: EmptyStateErrorProps) => { + const unauthorized = errors.find( + (error) => error.message && error.message.includes('unauthorized') + ); + + return ( + + + + + {unauthorized ? ( +

+ {i18n.translate('xpack.synthetics.emptyStateError.notAuthorized', { + defaultMessage: + 'You are not authorized to view Uptime data, please contact your system administrator.', + })} +

+ ) : ( +

+ {i18n.translate('xpack.synthetics.emptyStateError.title', { + defaultMessage: 'Error', + })} +

+ )} + + } + body={ + + {!unauthorized && + errors.map((error) => ( +

+ {error.body?.message || error.message} +

+ ))} +
+ } + /> +
+
+
+ ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_loading.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_loading.tsx new file mode 100644 index 0000000000000..0f71c9bafa962 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/empty_state_loading.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React, { Fragment } from 'react'; + +export const EmptyStateLoading = () => ( + + + + +

+ {i18n.translate('xpack.synthetics.emptyState.loadingMessage', { + defaultMessage: 'Loading…', + })} +

+
+ + } + /> +); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/use_has_data.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/use_has_data.tsx new file mode 100644 index 0000000000000..3561d841c7564 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/empty_state/use_has_data.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useContext, useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { getIndexStatus, selectIndexState } from '../../../state'; +import { SyntheticsRefreshContext } from '../../../contexts'; +// import { getDynamicSettings } from '../../../state/actions/dynamic_settings'; + +export const useHasData = () => { + const { loading, error, data } = useSelector(selectIndexState); + const { lastRefresh } = useContext(SyntheticsRefreshContext); + + // const { settings } = useSelector(selectDynamicSettings); // TODO: Add state for dynamicSettings + const settings = { heartbeatIndices: 'synthetics-*' }; + + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(getIndexStatus()); + }, [dispatch, lastRefresh]); + + /* useEffect(() => { + dispatch(getDynamicSettings()); + }, [dispatch]);*/ + + return { + data, + error, + loading, + settings, + }; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/filter_group/labels.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/filter_group/labels.ts new file mode 100644 index 0000000000000..e1cf5e20e14c3 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/filter_group/labels.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const filterLabels = { + LOCATION: i18n.translate('xpack.synthetics.filterBar.options.location.name', { + defaultMessage: 'Location', + }), + + PORT: i18n.translate('xpack.synthetics.filterBar.options.portLabel', { defaultMessage: 'Port' }), + + SCHEME: i18n.translate('xpack.synthetics.filterBar.options.schemeLabel', { + defaultMessage: 'Scheme', + }), + + TAG: i18n.translate('xpack.synthetics.filterBar.options.tagsLabel', { + defaultMessage: 'Tag', + }), +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/overview_page.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/overview_page.tsx new file mode 100644 index 0000000000000..4a370fc024423 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/overview_page.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; +import React from 'react'; +import { useTrackPageview } from '@kbn/observability-plugin/public'; +import { useSyntheticsSettingsContext } from '../../contexts'; +import { useOverviewBreadcrumbs } from './use_breadcrumbs'; + +export const OverviewPage: React.FC = () => { + useTrackPageview({ app: 'synthetics', path: 'overview' }); + useTrackPageview({ app: 'synthetics', path: 'overview', delay: 15000 }); + useOverviewBreadcrumbs(); + const { basePath } = useSyntheticsSettingsContext(); + + return ( + + +

This page should show empty state or overview

+
+ + Monitor Management + + + Add Monitor + +
+ ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/use_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/use_breadcrumbs.ts new file mode 100644 index 0000000000000..d33a0fd3c20cc --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/components/overview/use_breadcrumbs.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { i18n } from '@kbn/i18n'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { useBreadcrumbs } from '../../hooks/use_breadcrumbs'; +import { PLUGIN } from '../../../../../common/constants/plugin'; + +export const useOverviewBreadcrumbs = () => { + const kibana = useKibana(); + const appPath = kibana.services.application?.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) ?? ''; + + useBreadcrumbs([ + { + text: OVERVIEW_PAGE_CRUMB, + href: `${appPath}`, + }, + ]); +}; + +export const OVERVIEW_PAGE_CRUMB = i18n.translate('xpack.synthetics.overviewPage.overviewCrumb', { + defaultMessage: 'Overview', +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/contexts/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/index.ts new file mode 100644 index 0000000000000..6a2e0226671fe --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/index.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './synthetics_refresh_context'; +export * from './synthetics_settings_context'; +export * from './synthetics_theme_context'; +export * from './synthetics_startup_plugins_context'; +export * from './synthetics_data_view_context'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_data_view_context.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_data_view_context.tsx new file mode 100644 index 0000000000000..af657abd77540 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_data_view_context.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { createContext, useContext } from 'react'; +import { useFetcher } from '@kbn/observability-plugin/public'; +import { DataViewsPublicPluginStart, DataView } from '@kbn/data-views-plugin/public'; +import { useHasData } from '../components/overview/empty_state/use_has_data'; + +export const SyntheticsDataViewContext = createContext({} as DataView); + +export const SyntheticsDataViewContextProvider: React.FC<{ + dataViews: DataViewsPublicPluginStart; +}> = ({ children, dataViews }) => { + const { settings, data: indexStatus } = useHasData(); + + const heartbeatIndices = settings?.heartbeatIndices || ''; + + const { data } = useFetcher>(async () => { + if (heartbeatIndices && indexStatus?.indexExists) { + // this only creates an dateView in memory, not as saved object + return dataViews.create({ title: heartbeatIndices }); + } + }, [heartbeatIndices, indexStatus?.indexExists]); + + return ; +}; + +export const useSyntheticsDataView = () => useContext(SyntheticsDataViewContext); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_refresh_context.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_refresh_context.tsx new file mode 100644 index 0000000000000..696054eeb618b --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_refresh_context.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { createContext, useContext, useMemo, useState } from 'react'; + +interface SyntheticsRefreshContext { + lastRefresh: number; + refreshApp: () => void; +} + +const defaultContext: SyntheticsRefreshContext = { + lastRefresh: 0, + refreshApp: () => { + throw new Error('App refresh was not initialized, set it when you invoke the context'); + }, +}; + +export const SyntheticsRefreshContext = createContext(defaultContext); + +export const SyntheticsRefreshContextProvider: React.FC = ({ children }) => { + const [lastRefresh, setLastRefresh] = useState(Date.now()); + + const refreshApp = () => { + const refreshTime = Date.now(); + setLastRefresh(refreshTime); + }; + + const value = useMemo(() => { + return { lastRefresh, refreshApp }; + }, [lastRefresh]); + + return ; +}; + +export const useSyntheticsRefreshContext = () => useContext(SyntheticsRefreshContext); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx new file mode 100644 index 0000000000000..61231cfde6dfe --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx @@ -0,0 +1,109 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + AppMountParameters, + ChromeBadge, + ChromeBreadcrumb, + CoreStart, + I18nStart, +} from '@kbn/core/public'; +import React, { createContext, useContext, useMemo } from 'react'; +import { ClientPluginsSetup, ClientPluginsStart } from '../../../plugin'; +import { CLIENT_DEFAULTS, CONTEXT_DEFAULTS } from '../../../../common/constants'; +import { useGetUrlParams } from '../hooks'; + +export interface CommonlyUsedDateRange { + from: string; + to: string; + display: string; +} + +export interface SyntheticsAppProps { + basePath: string; + canSave: boolean; + core: CoreStart; + darkMode: boolean; + i18n: I18nStart; + isApmAvailable: boolean; + isInfraAvailable: boolean; + isLogsAvailable: boolean; + plugins: ClientPluginsSetup; + startPlugins: ClientPluginsStart; + setBadge: (badge?: ChromeBadge) => void; + renderGlobalHelpControls(): void; + commonlyUsedRanges: CommonlyUsedDateRange[]; + setBreadcrumbs: (crumbs: ChromeBreadcrumb[]) => void; + appMountParameters: AppMountParameters; + isDev: boolean; +} + +export interface SyntheticsSettingsContextValues { + basePath: string; + dateRangeStart: string; + dateRangeEnd: string; + isApmAvailable: boolean; + isInfraAvailable: boolean; + isLogsAvailable: boolean; + commonlyUsedRanges?: CommonlyUsedDateRange[]; + isDev?: boolean; +} + +const { BASE_PATH } = CONTEXT_DEFAULTS; + +const { DATE_RANGE_START, DATE_RANGE_END } = CLIENT_DEFAULTS; + +/** + * These are default values for the context. These defaults are typically + * overwritten by the Synthetics App upon its invocation. + */ +const defaultContext: SyntheticsSettingsContextValues = { + basePath: BASE_PATH, + dateRangeStart: DATE_RANGE_START, + dateRangeEnd: DATE_RANGE_END, + isApmAvailable: true, + isInfraAvailable: true, + isLogsAvailable: true, + isDev: false, +}; +export const SyntheticsSettingsContext = createContext(defaultContext); + +export const SyntheticsSettingsContextProvider: React.FC = ({ + children, + ...props +}) => { + const { basePath, isApmAvailable, isInfraAvailable, isLogsAvailable, commonlyUsedRanges, isDev } = + props; + + const { dateRangeStart, dateRangeEnd } = useGetUrlParams(); + + const value = useMemo(() => { + return { + isDev, + basePath, + isApmAvailable, + isInfraAvailable, + isLogsAvailable, + commonlyUsedRanges, + dateRangeStart: dateRangeStart ?? DATE_RANGE_START, + dateRangeEnd: dateRangeEnd ?? DATE_RANGE_END, + }; + }, [ + isDev, + basePath, + isApmAvailable, + isInfraAvailable, + isLogsAvailable, + dateRangeStart, + dateRangeEnd, + commonlyUsedRanges, + ]); + + return ; +}; + +export const useSyntheticsSettingsContext = () => useContext(SyntheticsSettingsContext); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_startup_plugins_context.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_startup_plugins_context.tsx new file mode 100644 index 0000000000000..75ee7b3d6ae67 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_startup_plugins_context.tsx @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { createContext, useContext } from 'react'; +import { ClientPluginsStart } from '../../../plugin'; + +export const SyntheticsStartupPluginsContext = createContext>({}); + +export const SyntheticsStartupPluginsContextProvider: React.FC> = ({ + children, + ...props +}) => ; + +export const useSyntheticsStartPlugins = () => useContext(SyntheticsStartupPluginsContext); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_theme_context.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_theme_context.tsx new file mode 100644 index 0000000000000..32844de9d04c2 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/contexts/synthetics_theme_context.tsx @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { euiLightVars, euiDarkVars } from '@kbn/ui-theme'; +import React, { createContext, useMemo } from 'react'; +import { EUI_CHARTS_THEME_DARK, EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme'; +import { DARK_THEME, LIGHT_THEME, PartialTheme, Theme } from '@elastic/charts'; + +export interface SyntheticsAppColors { + danger: string; + dangerBehindText: string; + success: string; + gray: string; + range: string; + mean: string; + warning: string; + lightestShade: string; +} + +export interface SyntheticsThemeContextValues { + colors: SyntheticsAppColors; + chartTheme: { + baseTheme?: Theme; + theme?: PartialTheme; + }; +} + +/** + * These are default values for the context. These defaults are typically + * overwritten by the Synthetics App upon its invocation. + */ +const defaultContext: SyntheticsThemeContextValues = { + colors: { + danger: euiLightVars.euiColorDanger, + dangerBehindText: euiDarkVars.euiColorVis9_behindText, + mean: euiLightVars.euiColorPrimary, + range: euiLightVars.euiFocusBackgroundColor, + success: euiLightVars.euiColorSuccess, + warning: euiLightVars.euiColorWarning, + gray: euiLightVars.euiColorLightShade, + lightestShade: euiLightVars.euiColorLightestShade, + }, + chartTheme: { + baseTheme: LIGHT_THEME, + theme: EUI_CHARTS_THEME_LIGHT.theme, + }, +}; + +export const SyntheticsThemeContext = createContext(defaultContext); + +interface ThemeContextProps { + darkMode: boolean; +} + +export const SyntheticsThemeContextProvider: React.FC = ({ + darkMode, + children, +}) => { + let colors: SyntheticsAppColors; + if (darkMode) { + colors = { + danger: euiDarkVars.euiColorVis9, + dangerBehindText: euiDarkVars.euiColorVis9_behindText, + mean: euiDarkVars.euiColorPrimary, + gray: euiDarkVars.euiColorLightShade, + range: euiDarkVars.euiFocusBackgroundColor, + success: euiDarkVars.euiColorSuccess, + warning: euiDarkVars.euiColorWarning, + lightestShade: euiDarkVars.euiColorLightestShade, + }; + } else { + colors = { + danger: euiLightVars.euiColorVis9, + dangerBehindText: euiLightVars.euiColorVis9_behindText, + mean: euiLightVars.euiColorPrimary, + gray: euiLightVars.euiColorLightShade, + range: euiLightVars.euiFocusBackgroundColor, + success: euiLightVars.euiColorSuccess, + warning: euiLightVars.euiColorWarning, + lightestShade: euiLightVars.euiColorLightestShade, + }; + } + const value = useMemo(() => { + return { + colors, + chartTheme: { + baseTheme: darkMode ? DARK_THEME : LIGHT_THEME, + theme: darkMode ? EUI_CHARTS_THEME_DARK.theme : EUI_CHARTS_THEME_LIGHT.theme, + }, + }; + }, [colors, darkMode]); + + return ; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts new file mode 100644 index 0000000000000..a7df47d7a0f71 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './use_url_params'; +export * from './use_filter_update'; +export * from './use_breadcrumbs'; +export * from './use_telemetry'; +export * from './use_breakpoints'; +export * from './use_service_allowed'; +export * from './use_no_data_config'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx new file mode 100644 index 0000000000000..d2639da47e79e --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.test.tsx @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ChromeBreadcrumb } from '@kbn/core/public'; +import { render } from '../utils/testing'; +import React from 'react'; +import { Route } from 'react-router-dom'; +import { OVERVIEW_ROUTE } from '../../../../common/constants'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { + SyntheticsUrlParams, + getSupportedUrlParams, +} from '../utils/url_params/get_supported_url_params'; +import { makeBaseBreadcrumb, useBreadcrumbs } from './use_breadcrumbs'; + +describe('useBreadcrumbs', () => { + it('sets the given breadcrumbs', () => { + const [getBreadcrumbs, core] = mockCore(); + + const expectedCrumbs: ChromeBreadcrumb[] = [ + { text: 'Crumb: ', href: 'http://href.example.net' }, + { text: 'Crumb II: Son of Crumb', href: 'http://href2.example.net' }, + ]; + + const Component = () => { + useBreadcrumbs(expectedCrumbs); + return <>Hello; + }; + + render( + + + + + + ); + + const urlParams: SyntheticsUrlParams = getSupportedUrlParams({}); + expect(JSON.stringify(getBreadcrumbs())).toEqual( + JSON.stringify( + makeBaseBreadcrumb('/app/synthetics', '/app/observability', urlParams).concat( + expectedCrumbs + ) + ) + ); + }); +}); + +const mockCore: () => [() => ChromeBreadcrumb[], any] = () => { + let breadcrumbObj: ChromeBreadcrumb[] = []; + const get = () => { + return breadcrumbObj; + }; + const core = { + application: { + getUrlForApp: (app: string) => + app === 'synthetics' ? '/app/synthetics' : '/app/observability', + navigateToUrl: jest.fn(), + }, + chrome: { + setBreadcrumbs: (newBreadcrumbs: ChromeBreadcrumb[]) => { + breadcrumbObj = newBreadcrumbs; + }, + }, + }; + + return [get, core]; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts new file mode 100644 index 0000000000000..0902481c51a9c --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breadcrumbs.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ChromeBreadcrumb } from '@kbn/core/public'; +import { i18n } from '@kbn/i18n'; +import { MouseEvent, useEffect } from 'react'; +import { EuiBreadcrumb } from '@elastic/eui'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { SyntheticsUrlParams, stringifyUrlParams } from '../utils/url_params'; +import { useUrlParams } from './use_url_params'; +import { PLUGIN } from '../../../../common/constants/plugin'; + +const EMPTY_QUERY = '?'; + +function handleBreadcrumbClick( + breadcrumbs: ChromeBreadcrumb[], + navigateToHref?: (url: string) => Promise +) { + return breadcrumbs.map((bc) => ({ + ...bc, + ...(bc.href + ? { + onClick: (event: MouseEvent) => { + if (navigateToHref && bc.href) { + event.preventDefault(); + navigateToHref(bc.href); + } + }, + } + : {}), + })); +} + +export const makeBaseBreadcrumb = ( + uptimePath: string, + observabilityPath: string, + params?: SyntheticsUrlParams +): [EuiBreadcrumb, EuiBreadcrumb] => { + if (params) { + const crumbParams: Partial = { ...params }; + + delete crumbParams.statusFilter; + const query = stringifyUrlParams(crumbParams, true); + uptimePath += query === EMPTY_QUERY ? '' : query; + } + + return [ + { + text: i18n.translate('xpack.synthetics.breadcrumbs.observabilityText', { + defaultMessage: 'Observability', + }), + href: observabilityPath, + }, + { + text: i18n.translate('xpack.synthetics.breadcrumbs.overviewBreadcrumbText', { + defaultMessage: 'Synthetics', + }), + href: uptimePath, + }, + ]; +}; + +export const useBreadcrumbs = (extraCrumbs: ChromeBreadcrumb[]) => { + const params = useUrlParams()[0](); + const kibana = useKibana(); + const setBreadcrumbs = kibana.services.chrome?.setBreadcrumbs; + const uptimePath = kibana.services.application?.getUrlForApp(PLUGIN.SYNTHETICS_PLUGIN_ID) ?? ''; + const observabilityPath = + kibana.services.application?.getUrlForApp('observability-overview') ?? ''; + const navigate = kibana.services.application?.navigateToUrl; + + useEffect(() => { + if (setBreadcrumbs) { + setBreadcrumbs( + handleBreadcrumbClick( + makeBaseBreadcrumb(uptimePath, observabilityPath, params).concat(extraCrumbs), + navigate + ) + ); + } + }, [uptimePath, observabilityPath, extraCrumbs, navigate, params, setBreadcrumbs]); +}; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breakpoints.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breakpoints.test.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breakpoints.test.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breakpoints.test.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breakpoints.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breakpoints.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breakpoints.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_breakpoints.ts diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.test.ts new file mode 100644 index 0000000000000..da3a25a5fc9df --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { addUpdatedField } from './use_filter_update'; + +describe('useFilterUpdate', () => { + describe('addUpdatedField', () => { + it('conditionally adds fields if they are new', () => { + const testVal = {}; + addUpdatedField('a val', 'newField', 'a new val', testVal); + expect(testVal).toEqual({ + newField: 'a new val', + }); + }); + + it('will add a field if the value is the same but not the default', () => { + const testVal = {}; + addUpdatedField('a val', 'newField', 'a val', testVal); + expect(testVal).toEqual({ newField: 'a val' }); + }); + + it(`won't add a field if the current value is empty`, () => { + const testVal = {}; + addUpdatedField('', 'newField', '', testVal); + expect(testVal).toEqual({}); + }); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.ts new file mode 100644 index 0000000000000..5578230ab2cf0 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_filter_update.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect } from 'react'; +import { useUrlParams } from './use_url_params'; + +export const parseFiltersMap = (currentFilters: string): Map => { + try { + return new Map(JSON.parse(currentFilters)); + } catch { + return new Map(); + } +}; + +const getUpdateFilters = ( + filterKueries: Map, + fieldName: string, + values?: string[] +): string => { + // add new term to filter map, toggle it off if already present + const updatedFilterMap = new Map(filterKueries); + updatedFilterMap.set(fieldName, values ?? []); + updatedFilterMap.forEach((value, key) => { + if (typeof value !== 'undefined' && value.length === 0) { + updatedFilterMap.delete(key); + } + }); + + // store the new set of filters + const persistedFilters = Array.from(updatedFilterMap); + return persistedFilters.length === 0 ? '' : JSON.stringify(persistedFilters); +}; + +export function addUpdatedField( + current: string, + key: string, + updated: string, + objToUpdate: { [key: string]: string } +): void { + if (current !== updated || current !== '') { + objToUpdate[key] = updated; + } +} + +export const useFilterUpdate = ( + fieldName: string, + values: string[], + notValues: string[], + shouldUpdateUrl: boolean = true +) => { + const [getUrlParams, updateUrl] = useUrlParams(); + + const { filters, excludedFilters } = getUrlParams(); + + useEffect(() => { + const currentFiltersMap: Map = parseFiltersMap(filters); + const currentExclusionsMap: Map = parseFiltersMap(excludedFilters); + const newFiltersString = getUpdateFilters(currentFiltersMap, fieldName, values); + const newExclusionsString = getUpdateFilters(currentExclusionsMap, fieldName, notValues); + + const update: { [key: string]: string } = {}; + + addUpdatedField(filters, 'filters', newFiltersString, update); + addUpdatedField(excludedFilters, 'excludedFilters', newExclusionsString, update); + + if (shouldUpdateUrl && Object.keys(update).length > 0) { + // reset pagination whenever filters change + updateUrl({ ...update, pagination: '' }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [fieldName, values, notValues]); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_no_data_config.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_no_data_config.ts new file mode 100644 index 0000000000000..6243d2f5d8c8a --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_no_data_config.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { useContext } from 'react'; +import { useSelector } from 'react-redux'; +import { KibanaPageTemplateProps, useKibana } from '@kbn/kibana-react-plugin/public'; +import { SyntheticsSettingsContext } from '../contexts'; +import { ClientPluginsStart } from '../../../plugin'; +import { selectIndexState } from '../state'; + +export function useNoDataConfig(): KibanaPageTemplateProps['noDataConfig'] { + const { basePath } = useContext(SyntheticsSettingsContext); + + const { + services: { docLinks }, + } = useKibana(); + + const { data } = useSelector(selectIndexState); + + // Returns no data config when there is no historical data + if (data && !data.indexExists) { + return { + solution: i18n.translate('xpack.synthetics.noDataConfig.solutionName', { + defaultMessage: 'Observability', + }), + actions: { + beats: { + title: i18n.translate('xpack.synthetics.noDataConfig.beatsCard.title', { + defaultMessage: 'Add monitors with Heartbeat', + }), + description: i18n.translate('xpack.synthetics.noDataConfig.beatsCard.description', { + defaultMessage: + 'Proactively monitor the availability of your sites and services. Receive alerts and resolve issues faster to optimize your users experience.', + }), + href: basePath + `/app/home#/tutorial/uptimeMonitors`, + }, + }, + docsLink: docLinks!.links.observability.guide, + }; + } +} +// TODO: Change no data config for Synthetics diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_service_allowed.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_service_allowed.ts new file mode 100644 index 0000000000000..12a2ed7043973 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_service_allowed.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useDispatch } from 'react-redux'; +import { useEffect } from 'react'; +// import { syntheticsServiceAllowedSelector } from '../../../state/selectors'; +// import { getSyntheticsServiceAllowed } from '../../../state/actions'; + +export const useSyntheticsServiceAllowed = () => { + const dispatch = useDispatch(); + + useEffect(() => { + // dispatch(getSyntheticsServiceAllowed.get()); + }, [dispatch]); + + // return useSelector(syntheticsServiceAllowedSelector); + // TODO Implement for Synthetics App + return { isAllowed: true, signupUrl: 'https://example.com', loading: false }; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_telemetry.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_telemetry.ts new file mode 100644 index 0000000000000..f97e4c4b2be09 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_telemetry.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEffect } from 'react'; +import { useGetUrlParams } from './use_url_params'; +import { apiService } from '../utils/api_service'; +// import { API_URLS } from '../../../common/constants'; + +export enum SyntheticsPage { + Overview = 'Overview', + Monitor = 'Monitor', + MonitorAdd = 'AddMonitor', + MonitorEdit = 'EditMonitor', + MonitorManagement = 'MonitorManagement', + Settings = 'Settings', + Certificates = 'Certificates', + StepDetail = 'StepDetail', + SyntheticCheckStepsPage = 'SyntheticCheckStepsPage', + NotFound = '__not-found__', +} + +export const useSyntheticsTelemetry = (page?: SyntheticsPage) => { + const { dateRangeStart, dateRangeEnd, autorefreshInterval, autorefreshIsPaused } = + useGetUrlParams(); + + useEffect(() => { + if (!apiService.http) throw new Error('Core http services are not defined'); + + /* + TODO: Add/Modify telemetry endpoint for synthetics + const params = { + page, + autorefreshInterval: autorefreshInterval / 1000, // divide by 1000 to keep it in secs + dateStart: dateRangeStart, + dateEnd: dateRangeEnd, + autoRefreshEnabled: !autorefreshIsPaused, + };*/ + setTimeout(() => { + // apiService.post(API_URLS.LOG_PAGE_VIEW, params); + }, 100); + }, [autorefreshInterval, autorefreshIsPaused, dateRangeEnd, dateRangeStart, page]); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.test.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.test.tsx new file mode 100644 index 0000000000000..d1e9ceae998b5 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.test.tsx @@ -0,0 +1,68 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import DateMath from '@kbn/datemath'; +import userEvent from '@testing-library/user-event'; +import { render } from '../utils/testing'; +import React, { useState, Fragment } from 'react'; +import { useUrlParams, SyntheticsUrlParamsHook } from './use_url_params'; +import { SyntheticsRefreshContext } from '../contexts'; + +interface MockUrlParamsComponentProps { + hook: SyntheticsUrlParamsHook; + updateParams?: { [key: string]: any }; +} + +const UseUrlParamsTestComponent = ({ hook, updateParams }: MockUrlParamsComponentProps) => { + const [params, setParams] = useState({}); + const [getUrlParams, updateUrlParams] = hook(); + const queryParams = getUrlParams(); + return ( + + {Object.keys(params).length > 0 ?
{JSON.stringify(params)}
: null} + + +
+ ); +}; + +describe('useUrlParams', () => { + let dateMathSpy: any; + const MOCK_DATE_VALUE = 20; + + beforeEach(() => { + dateMathSpy = jest.spyOn(DateMath, 'parse'); + dateMathSpy.mockReturnValue(MOCK_DATE_VALUE); + }); + + it('accepts router props, updates URL params, and returns the current params', async () => { + const { findByText, history } = render( + + + + ); + + const pushSpy = jest.spyOn(history, 'push'); + + const setUrlParamsButton = await findByText('Set url params'); + userEvent.click(setUrlParamsButton); + expect(pushSpy).toHaveBeenCalledWith({ + pathname: '/', + search: 'dateRangeEnd=now&dateRangeStart=now-12d', + }); + pushSpy.mockClear(); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.ts b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.ts new file mode 100644 index 0000000000000..ec31c711cffc7 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/hooks/use_url_params.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback, useEffect } from 'react'; +import { stringify } from 'query-string'; +import { useLocation, useHistory } from 'react-router-dom'; +import { useDispatch, useSelector } from 'react-redux'; +import { SyntheticsUrlParams, getSupportedUrlParams } from '../utils/url_params'; + +// TODO: Create the following imports for new Synthetics App +import { selectedFiltersSelector } from '../../../legacy_uptime/state/selectors'; +import { setSelectedFilters } from '../../../legacy_uptime/state/actions/selected_filters'; +import { getFiltersFromMap } from '../../../legacy_uptime/hooks/use_selected_filters'; +import { getParsedParams } from '../../../legacy_uptime/lib/helper/parse_search'; + +export type GetUrlParams = () => SyntheticsUrlParams; +export type UpdateUrlParams = (updatedParams: { + [key: string]: string | number | boolean | undefined; +}) => void; + +export type SyntheticsUrlParamsHook = () => [GetUrlParams, UpdateUrlParams]; + +export const useGetUrlParams: GetUrlParams = () => { + const { search } = useLocation(); + + return getSupportedUrlParams(getParsedParams(search)); +}; + +const getMapFromFilters = (value: any): Map | undefined => { + try { + return new Map(JSON.parse(value)); + } catch { + return undefined; + } +}; + +export const useUrlParams: SyntheticsUrlParamsHook = () => { + const { pathname, search } = useLocation(); + const history = useHistory(); + const dispatch = useDispatch(); + const selectedFilters = useSelector(selectedFiltersSelector); + const { filters } = useGetUrlParams(); + + useEffect(() => { + if (selectedFilters === null) { + const filterMap = getMapFromFilters(filters); + if (filterMap) { + dispatch(setSelectedFilters(getFiltersFromMap(filterMap))); + } + } + }, [dispatch, filters, selectedFilters]); + + const updateUrlParams: UpdateUrlParams = useCallback( + (updatedParams) => { + const currentParams = getParsedParams(search); + const mergedParams = { + ...currentParams, + ...updatedParams, + }; + + const updatedSearch = stringify( + // drop any parameters that have no value + Object.keys(mergedParams).reduce((params, key) => { + const value = mergedParams[key]; + if (value === undefined || value === '') { + return params; + } + return { + ...params, + [key]: value, + }; + }, {}) + ); + + // only update the URL if the search has actually changed + if (search !== updatedSearch) { + history.push({ pathname, search: updatedSearch }); + } + const filterMap = getMapFromFilters(mergedParams.filters); + if (!filterMap) { + dispatch(setSelectedFilters(null)); + } else { + dispatch(setSelectedFilters(getFiltersFromMap(filterMap))); + } + }, + [dispatch, history, pathname, search] + ); + + return [useGetUrlParams, updateUrlParams]; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/render_app.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/render_app.tsx index c4b05ea7a2e0c..76b86c0b82383 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics/render_app.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/render_app.tsx @@ -7,9 +7,17 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import { i18n as i18nFormatter } from '@kbn/i18n'; import { AppMountParameters, CoreStart } from '@kbn/core/public'; +import { SyntheticsAppProps } from './contexts'; +import { getIntegratedAppAvailability } from './utils/adapters'; +import { + DEFAULT_DARK_MODE, + DEFAULT_TIMEPICKER_QUICK_RANGES, + INTEGRATED_SOLUTIONS, +} from '../../../common/constants'; +import { SyntheticsApp } from './synthetics_app'; import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin'; -import { SyntheticsApp } from '../synthetics_app'; export function renderApp( core: CoreStart, @@ -18,7 +26,56 @@ export function renderApp( appMountParameters: AppMountParameters, isDev: boolean ) { - ReactDOM.render(, appMountParameters.element); + const { + application: { capabilities }, + chrome: { setBadge, setHelpExtension }, + docLinks, + http: { basePath }, + i18n, + } = core; + + const { apm, infrastructure, logs } = getIntegratedAppAvailability( + capabilities, + INTEGRATED_SOLUTIONS + ); + + const canSave = (capabilities.uptime.save ?? false) as boolean; // TODO: Determine for synthetics + + const props: SyntheticsAppProps = { + isDev, + plugins, + canSave, + core, + i18n, + startPlugins, + basePath: basePath.get(), + darkMode: core.uiSettings.get(DEFAULT_DARK_MODE), + commonlyUsedRanges: core.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES), + isApmAvailable: apm, + isInfraAvailable: infrastructure, + isLogsAvailable: logs, + renderGlobalHelpControls: () => + setHelpExtension({ + appName: i18nFormatter.translate('xpack.synthetics.header.appName', { + defaultMessage: 'Synthetics', + }), + links: [ + { + linkType: 'documentation', + href: `${docLinks.links.observability.monitorUptime}`, // TODO: Include synthetics link + }, + { + linkType: 'discuss', + href: 'https://discuss.elastic.co/c/uptime', // TODO: Include synthetics link + }, + ], + }), + setBadge, + appMountParameters, + setBreadcrumbs: core.chrome.setBreadcrumbs, + }; + + ReactDOM.render(, appMountParameters.element); return () => { ReactDOM.unmountComponentAtNode(appMountParameters.element); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx new file mode 100644 index 0000000000000..d20c390c84b59 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/routes.tsx @@ -0,0 +1,184 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC, useEffect } from 'react'; +import { EuiPageTemplateProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { Route, Switch } from 'react-router-dom'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; +import { APP_WRAPPER_CLASS } from '@kbn/core/public'; +import { useInspectorContext } from '@kbn/observability-plugin/public'; +import { MonitorAddEditPage } from './components/monitor_add_edit/monitor_add_edit_page'; +import { OverviewPage } from './components/overview/overview_page'; +import { SyntheticsPageTemplateComponent } from './components/common/pages/synthetics_page_template'; +import { NotFoundPage } from './components/common/pages/not_found'; +import { ServiceAllowedWrapper } from './components/common/wrappers/service_allowed_wrapper'; +import { + MONITOR_ADD_ROUTE, + MONITOR_MANAGEMENT_ROUTE, + OVERVIEW_ROUTE, +} from '../../../common/constants'; +import { MonitorManagementPage } from './components/monitor_management/monitor_management_page'; +import { apiService } from './utils/api_service'; +import { SyntheticsPage, useSyntheticsTelemetry } from './hooks/use_telemetry'; + +type RouteProps = { + path: string; + component: React.FC; + dataTestSubj: string; + title: string; + telemetryId: SyntheticsPage; + pageHeader: { + pageTitle: string | JSX.Element; + children?: JSX.Element; + rightSideItems?: JSX.Element[]; + }; +} & EuiPageTemplateProps; + +const baseTitle = i18n.translate('xpack.synthetics.routes.baseTitle', { + defaultMessage: 'Synthetics - Kibana', +}); + +export const MONITOR_MANAGEMENT_LABEL = i18n.translate( + 'xpack.synthetics.monitorManagement.heading', + { + defaultMessage: 'Monitor Management', + } +); + +const getRoutes = (): RouteProps[] => { + return [ + { + title: i18n.translate('xpack.synthetics.overviewRoute.title', { + defaultMessage: 'Synthetics Overview | {baseTitle}', + values: { baseTitle }, + }), + path: OVERVIEW_ROUTE, + component: () => , + dataTestSubj: 'syntheticsOverviewPage', + telemetryId: SyntheticsPage.Overview, + pageHeader: { + pageTitle: ( + + + + + + ), + rightSideItems: [ + /* */ + ], + }, + }, + { + title: i18n.translate('xpack.synthetics.monitorManagementRoute.title', { + defaultMessage: 'Monitor Management | {baseTitle}', + values: { baseTitle }, + }), + path: MONITOR_MANAGEMENT_ROUTE, + component: () => ( + + + + ), + dataTestSubj: 'syntheticsMonitorManagementPage', + telemetryId: SyntheticsPage.MonitorManagement, + pageHeader: { + pageTitle: ( + + + + + + ), + rightSideItems: [ + /* */ + ], + }, + }, + { + title: i18n.translate('xpack.synthetics.addMonitorRoute.title', { + defaultMessage: 'Add Monitor | {baseTitle}', + values: { baseTitle }, + }), + path: MONITOR_ADD_ROUTE, + component: () => ( + + + + ), + dataTestSubj: 'syntheticsMonitorAddPage', + telemetryId: SyntheticsPage.MonitorAdd, + pageHeader: { + pageTitle: ( + + ), + }, + // bottomBar: , + bottomBarProps: { paddingSize: 'm' as const }, + }, + ]; +}; + +const RouteInit: React.FC> = ({ + path, + title, + telemetryId, +}) => { + useSyntheticsTelemetry(telemetryId); + useEffect(() => { + document.title = title; + }, [path, title]); + return null; +}; + +export const PageRouter: FC = () => { + const routes = getRoutes(); + const { addInspectorRequest } = useInspectorContext(); + + apiService.addInspectorRequest = addInspectorRequest; + + return ( + + {routes.map( + ({ + title, + path, + component: RouteComponent, + dataTestSubj, + telemetryId, + pageHeader, + ...pageTemplateProps + }) => ( + +
+ {/* TODO: See if the callout is needed for Synthetics App as well */} + + + + +
+
+ ) + )} + +
+ ); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/index.ts new file mode 100644 index 0000000000000..153eab7415cd5 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/index.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { store, storage } from './store'; + +export type { RooState as AppState } from './root_reducer'; + +export * from './ui'; +export * from './index_status'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/actions.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/actions.ts new file mode 100644 index 0000000000000..0b359a52502fa --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/actions.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IHttpFetchError } from '@kbn/core/public'; +import { createAction } from '@reduxjs/toolkit'; +import { StatesIndexStatus } from '../../../../../common/runtime_types'; + +export const getIndexStatus = createAction('[INDEX STATUS] GET'); +export const getIndexStatusSuccess = createAction('[INDEX STATUS] GET SUCCESS'); +export const getIndexStatusFail = createAction('[INDEX STATUS] GET FAIL'); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/api.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/api.ts new file mode 100644 index 0000000000000..f2d5e326ba2ab --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/api.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { API_URLS } from '../../../../../common/constants'; +import { StatesIndexStatus, StatesIndexStatusType } from '../../../../../common/runtime_types'; +import { apiService } from '../../utils/api_service'; + +export const fetchIndexStatus = async (): Promise => { + return await apiService.get(API_URLS.INDEX_STATUS, undefined, StatesIndexStatusType); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/effects.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/effects.ts new file mode 100644 index 0000000000000..cf0eaf83e5c2c --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/effects.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { takeLeading } from 'redux-saga/effects'; +import { getIndexStatus, getIndexStatusSuccess, getIndexStatusFail } from './actions'; +import { fetchEffectFactory } from '../utils/fetch_effect'; +import { fetchIndexStatus } from './api'; + +export function* fetchIndexStatusEffect() { + yield takeLeading( + getIndexStatus, + fetchEffectFactory(fetchIndexStatus, getIndexStatusSuccess, getIndexStatusFail) + ); +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/index.ts new file mode 100644 index 0000000000000..e140145bb324a --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/index.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; +import { createReducer } from '@reduxjs/toolkit'; +import { StatesIndexStatus } from '../../../../../common/runtime_types'; + +import { getIndexStatus, getIndexStatusSuccess, getIndexStatusFail } from './actions'; + +export interface IndexStatusState { + data: StatesIndexStatus | null; + loading: boolean; + error: IHttpFetchError | null; +} + +const initialState: IndexStatusState = { + data: null, + loading: false, + error: null, +}; + +export const indexStatusReducer = createReducer(initialState, (builder) => { + builder + .addCase(getIndexStatus, (state) => { + state.loading = true; + }) + .addCase(getIndexStatusSuccess, (state, action) => { + state.data = action.payload; + state.loading = false; + }) + .addCase(getIndexStatusFail, (state, action) => { + state.error = action.payload as IHttpFetchError; + state.loading = false; + }); +}); + +export * from './actions'; +export * from './effects'; +export * from './selectors'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/selectors.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/selectors.ts new file mode 100644 index 0000000000000..7d7da80b692a2 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/index_status/selectors.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createSelector } from 'reselect'; +import type { RooState } from '../root_reducer'; + +const getState = (appState: RooState) => appState.indexStatus; +export const selectIndexState = createSelector(getState, (state) => state); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts new file mode 100644 index 0000000000000..7d1aaa60aa4f3 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_effect.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { all, fork } from 'redux-saga/effects'; +import { fetchIndexStatusEffect } from './index_status'; + +export const rootEffect = function* root(): Generator { + yield all([fork(fetchIndexStatusEffect)]); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts new file mode 100644 index 0000000000000..a57c0af9e6fdb --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { combineReducers } from '@reduxjs/toolkit'; + +import { uiReducer } from './ui'; +import { indexStatusReducer } from './index_status'; + +export const rootReducer = combineReducers({ + ui: uiReducer, + indexStatus: indexStatusReducer, +}); + +export type RooState = ReturnType; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/store.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/store.ts new file mode 100644 index 0000000000000..19320f0102a99 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/store.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { configureStore } from '@reduxjs/toolkit'; +import createSagaMiddleware from 'redux-saga'; +import { Storage } from '@kbn/kibana-utils-plugin/public'; +import { rootEffect } from './root_effect'; +import { rootReducer } from './root_reducer'; + +const sagaMW = createSagaMiddleware(); + +export const store = configureStore({ + reducer: rootReducer, + middleware: (getDefaultMiddleware) => getDefaultMiddleware({ thunk: false }).concat(sagaMW), + devTools: process.env.NODE_ENV !== 'production', + preloadedState: {}, + enhancers: [], +}); + +sagaMW.run(rootEffect); + +export const storage = new Storage(window.localStorage); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/actions.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/actions.ts new file mode 100644 index 0000000000000..d613b3f3d3509 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/actions.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createAction } from '@reduxjs/toolkit'; + +export interface PopoverState { + id: string; + open: boolean; +} + +export const setAlertFlyoutVisible = createAction('[UI] TOGGLE ALERT FLYOUT'); + +export const setAlertFlyoutType = createAction('[UI] SET ALERT FLYOUT TYPE'); + +export const setBasePath = createAction('[UI] SET BASE PATH'); + +export const setEsKueryString = createAction('[UI] SET ES KUERY STRING'); + +export const setSearchTextAction = createAction('[UI] SET SEARCH'); + +export const toggleIntegrationsPopover = createAction( + '[UI] TOGGLE INTEGRATION POPOVER STATE' +); + +export const setSelectedMonitorId = createAction('[UI] SET MONITOR ID'); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/index.ts new file mode 100644 index 0000000000000..618e6dd524767 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/index.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createReducer } from '@reduxjs/toolkit'; + +import { + PopoverState, + toggleIntegrationsPopover, + setBasePath, + setEsKueryString, + setAlertFlyoutType, + setAlertFlyoutVisible, + setSearchTextAction, + setSelectedMonitorId, +} from './actions'; + +export interface UiState { + alertFlyoutVisible: boolean; + alertFlyoutType?: string; + basePath: string; + esKuery: string; + searchText: string; + integrationsPopoverOpen: PopoverState | null; + monitorId: string; +} + +const initialState: UiState = { + alertFlyoutVisible: false, + basePath: '', + esKuery: '', + searchText: '', + integrationsPopoverOpen: null, + monitorId: '', +}; + +export const uiReducer = createReducer(initialState, (builder) => { + builder + .addCase(toggleIntegrationsPopover, (state, action) => { + state.integrationsPopoverOpen = action.payload; + }) + .addCase(setAlertFlyoutVisible, (state, action) => { + state.alertFlyoutVisible = action.payload ?? !state.alertFlyoutVisible; + }) + .addCase(setAlertFlyoutType, (state, action) => { + state.alertFlyoutType = action.payload; + }) + .addCase(setBasePath, (state, action) => { + state.basePath = action.payload; + }) + .addCase(setEsKueryString, (state, action) => { + state.esKuery = action.payload; + }) + .addCase(setSearchTextAction, (state, action) => { + state.searchText = action.payload; + }) + .addCase(setSelectedMonitorId, (state, action) => { + state.monitorId = action.payload; + }); +}); + +export * from './actions'; +export * from './selectors'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/selectors.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/selectors.ts new file mode 100644 index 0000000000000..52d9841cde961 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/ui/selectors.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createSelector } from 'reselect'; +import type { RooState } from '../root_reducer'; + +const uiStateSelector = (appState: RooState) => appState.ui; +export const selectBasePath = createSelector(uiStateSelector, ({ basePath }) => basePath); + +export const selectIsIntegrationsPopupOpen = createSelector( + uiStateSelector, + ({ integrationsPopoverOpen }) => integrationsPopoverOpen +); + +export const selectAlertFlyoutVisibility = createSelector( + uiStateSelector, + ({ alertFlyoutVisible }) => alertFlyoutVisible +); + +export const selectAlertFlyoutType = createSelector( + uiStateSelector, + ({ alertFlyoutType }) => alertFlyoutType +); + +export const selectEsKuery = createSelector(uiStateSelector, ({ esKuery }) => esKuery); + +export const selectSearchText = createSelector(uiStateSelector, ({ searchText }) => searchText); + +export const selectMonitorId = createSelector(uiStateSelector, ({ monitorId }) => monitorId); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts b/x-pack/plugins/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts new file mode 100644 index 0000000000000..387ceeb56a514 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { call, put } from 'redux-saga/effects'; +import { Action } from 'redux-actions'; +import { IHttpFetchError } from '@kbn/core/public'; + +/** + * Factory function for a fetch effect. It expects three action creators, + * one to call for a fetch, one to call for success, and one to handle failures. + * @param fetch creates a fetch action + * @param success creates a success action + * @param fail creates a failure action + * @template T the action type expected by the fetch action + * @template R the type that the API request should return on success + * @template S the type of the success action + * @template F the type of the failure action + */ +export function fetchEffectFactory( + fetch: (request: T) => Promise, + success: (response: R) => Action, + fail: (error: IHttpFetchError) => Action +) { + return function* (action: Action): Generator { + try { + const response = yield call(fetch, action.payload); + if (response instanceof Error) { + // eslint-disable-next-line no-console + console.error(response); + + yield put(fail(response as IHttpFetchError)); + } else { + yield put(success(response as R)); + } + } catch (error) { + // eslint-disable-next-line no-console + console.error(error); + yield put(fail(error as IHttpFetchError)); + } + }; +} diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx new file mode 100644 index 0000000000000..614f77ddff5d7 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/synthetics_app.tsx @@ -0,0 +1,123 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useEffect } from 'react'; +import { Provider as ReduxProvider } from 'react-redux'; +import { Router } from 'react-router-dom'; +import { EuiErrorBoundary } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { APP_WRAPPER_CLASS } from '@kbn/core/public'; +import { + KibanaContextProvider, + KibanaThemeProvider, + RedirectAppLinks, +} from '@kbn/kibana-react-plugin/public'; +import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; +import { InspectorContextProvider } from '@kbn/observability-plugin/public'; +import { SyntheticsAlertsFlyoutWrapper } from './components/overview/alerts/alerts_containers/synthetics_alerts_flyout_wrapper'; +import { SyntheticsAppProps } from './contexts'; + +import { + SyntheticsRefreshContextProvider, + SyntheticsSettingsContextProvider, + SyntheticsThemeContextProvider, + SyntheticsStartupPluginsContextProvider, + SyntheticsDataViewContextProvider, +} from './contexts'; + +import { PageRouter } from './routes'; +import { store, storage, setBasePath } from './state'; +import { kibanaService } from './utils/kibana_service'; +import { ActionMenu } from './components/common/header/action_menu'; + +const Application = (props: SyntheticsAppProps) => { + const { + basePath, + canSave, + core, + darkMode, + i18n: i18nCore, + plugins, + renderGlobalHelpControls, + setBadge, + startPlugins, + appMountParameters, + } = props; + + useEffect(() => { + renderGlobalHelpControls(); + setBadge( + !canSave + ? { + text: i18n.translate('xpack.synthetics.badge.readOnly.text', { + defaultMessage: 'Read only', + }), + tooltip: i18n.translate('xpack.synthetics.badge.readOnly.tooltip', { + defaultMessage: 'Unable to save', + }), + iconType: 'glasses', + } + : undefined + ); + }, [canSave, renderGlobalHelpControls, setBadge]); + + kibanaService.core = core; + kibanaService.theme = props.appMountParameters.theme$; + + store.dispatch(setBasePath(basePath)); + + return ( + + + + + + + + + + + + +
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+ ); +}; + +export const SyntheticsApp = (props: SyntheticsAppProps) => ; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/adapters/capabilities_adapter.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/adapters/capabilities_adapter.ts new file mode 100644 index 0000000000000..c00be7d8b0ca0 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/adapters/capabilities_adapter.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +interface IntegratedAppsAvailability { + [key: string]: boolean; +} + +export const getIntegratedAppAvailability = ( + capabilities: any, + integratedApps: string[] +): IntegratedAppsAvailability => { + return integratedApps.reduce((supportedSolutions: IntegratedAppsAvailability, solutionName) => { + supportedSolutions[solutionName] = + capabilities[solutionName] && capabilities[solutionName].show === true; + return supportedSolutions; + }, {}); +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics_app.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/utils/adapters/index.ts similarity index 71% rename from x-pack/plugins/synthetics/public/apps/synthetics_app.tsx rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/adapters/index.ts index 92531041157a7..2d0e4b7b2ba6f 100644 --- a/x-pack/plugins/synthetics/public/apps/synthetics_app.tsx +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/adapters/index.ts @@ -4,8 +4,5 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; -export const SyntheticsApp = () => { - return
Synthetics App
; -}; +export * from './capabilities_adapter'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/api_service.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/api_service.ts new file mode 100644 index 0000000000000..cbba8cf02cf22 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/api_service.ts @@ -0,0 +1,127 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isRight } from 'fp-ts/lib/Either'; +import { formatErrors } from '@kbn/securitysolution-io-ts-utils'; +import { HttpFetchQuery, HttpSetup } from '@kbn/core/public'; +import { FETCH_STATUS, AddInspectorRequest } from '@kbn/observability-plugin/public'; + +class ApiService { + private static instance: ApiService; + private _http!: HttpSetup; + private _addInspectorRequest!: AddInspectorRequest; + + public get http() { + return this._http; + } + + public set http(httpSetup: HttpSetup) { + this._http = httpSetup; + } + + public get addInspectorRequest() { + return this._addInspectorRequest; + } + + public set addInspectorRequest(addInspectorRequest: AddInspectorRequest) { + this._addInspectorRequest = addInspectorRequest; + } + + private constructor() {} + + static getInstance(): ApiService { + if (!ApiService.instance) { + ApiService.instance = new ApiService(); + } + + return ApiService.instance; + } + + public async get( + apiUrl: string, + params?: HttpFetchQuery, + decodeType?: any, + asResponse = false + ) { + const response = await this._http!.fetch({ + path: apiUrl, + query: params, + asResponse, + }); + + this.addInspectorRequest?.({ data: response, status: FETCH_STATUS.SUCCESS, loading: false }); + + if (decodeType) { + const decoded = decodeType.decode(response); + if (isRight(decoded)) { + return decoded.right as T; + } else { + // eslint-disable-next-line no-console + console.error( + `API ${apiUrl} is not returning expected response, ${formatErrors( + decoded.left + )} for response`, + response + ); + } + } + + return response; + } + + public async post(apiUrl: string, data?: any, decodeType?: any) { + const response = await this._http!.post(apiUrl, { + method: 'POST', + body: JSON.stringify(data), + }); + + this.addInspectorRequest?.({ data: response, status: FETCH_STATUS.SUCCESS, loading: false }); + + if (decodeType) { + const decoded = decodeType.decode(response); + if (isRight(decoded)) { + return decoded.right as T; + } else { + // eslint-disable-next-line no-console + console.warn( + `API ${apiUrl} is not returning expected response, ${formatErrors(decoded.left)}` + ); + } + } + return response; + } + + public async put(apiUrl: string, data?: any, decodeType?: any) { + const response = await this._http!.put(apiUrl, { + method: 'PUT', + body: JSON.stringify(data), + }); + + if (decodeType) { + const decoded = decodeType.decode(response); + if (isRight(decoded)) { + return decoded.right as T; + } else { + // eslint-disable-next-line no-console + console.warn( + `API ${apiUrl} is not returning expected response, ${formatErrors(decoded.left)}` + ); + } + } + return response; + } + + public async delete(apiUrl: string) { + const response = await this._http!.delete(apiUrl); + if (response instanceof Error) { + throw response; + } + return response; + } +} + +export const apiService = ApiService.getInstance(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/index.ts new file mode 100644 index 0000000000000..566bde2d4b777 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/api_service/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './api_service'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/index.ts new file mode 100644 index 0000000000000..c623088ee9ba4 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './kibana_service'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/kibana_service.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/kibana_service.ts new file mode 100644 index 0000000000000..06fa2b892b4a0 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/kibana_service/kibana_service.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Observable } from 'rxjs'; +import type { CoreStart, CoreTheme } from '@kbn/core/public'; +import { apiService } from '../api_service/api_service'; + +class KibanaService { + private static instance: KibanaService; + private _core!: CoreStart; + private _theme!: Observable; + + public get core() { + return this._core; + } + + public set core(coreStart: CoreStart) { + this._core = coreStart; + apiService.http = this._core.http; + } + + public get theme() { + return this._theme; + } + + public set theme(coreTheme: Observable) { + this._theme = coreTheme; + } + + public get toasts() { + return this._core.notifications.toasts; + } + + private constructor() {} + + static getInstance(): KibanaService { + if (!KibanaService.instance) { + KibanaService.instance = new KibanaService(); + } + + return KibanaService.instance; + } +} + +export const kibanaService = KibanaService.getInstance(); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/syncthetics_store.mock.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/syncthetics_store.mock.ts new file mode 100644 index 0000000000000..adf2a15e70fa6 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/syncthetics_store.mock.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AppState } from '../../../state'; + +/** + * NOTE: This variable name MUST start with 'mock*' in order for + * Jest to accept its use within a jest.mock() + */ +export const mockState: AppState = { + ui: { + alertFlyoutVisible: false, + basePath: 'yyz', + esKuery: '', + integrationsPopoverOpen: null, + searchText: '', + monitorId: '', + }, + indexStatus: { + data: null, + error: null, + loading: false, + }, +}; + +// TODO: Complete mock state diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_plugin_start_mock.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_plugin_start_mock.ts new file mode 100644 index 0000000000000..981e6a5e2ae3b --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_plugin_start_mock.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +interface InputTimeRange { + from: string; + to: string; +} + +export const startPlugins = { + data: { + query: { + timefilter: { + timefilter: { + getTime: () => ({ to: 'now-15m', from: 'now-30m' }), + setTime: jest.fn(({ from, to }: InputTimeRange) => {}), + }, + }, + }, + }, +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.test.ts new file mode 100644 index 0000000000000..89419ca61ed43 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.test.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import DateMath from '@kbn/datemath'; +import { getSupportedUrlParams } from '../url_params'; +import { CLIENT_DEFAULTS } from '../../../../../common/constants'; + +describe('getSupportedUrlParams', () => { + let dateMathSpy: any; + const MOCK_DATE_VALUE = 20; + + beforeEach(() => { + dateMathSpy = jest.spyOn(DateMath, 'parse'); + dateMathSpy.mockReturnValue(MOCK_DATE_VALUE); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('returns custom values', () => { + const customValues = { + autorefreshInterval: '23', + autorefreshIsPaused: 'false', + dateRangeStart: 'now-15m', + dateRangeEnd: 'now', + monitorListPageIndex: '23', + monitorListPageSize: '50', + monitorListSortDirection: 'desc', + monitorListSortField: 'monitor.status', + search: 'monitor.status: down', + selectedPingStatus: 'up', + }; + + const expected = { + absoluteDateRangeEnd: 20, + absoluteDateRangeStart: 20, + autorefreshInterval: 23, + autorefreshIsPaused: false, + dateRangeEnd: 'now', + dateRangeStart: 'now-15m', + search: 'monitor.status: down', + }; + + const result = getSupportedUrlParams(customValues); + expect(result).toMatchObject(expected); + }); + + it('returns default values', () => { + const { + AUTOREFRESH_INTERVAL, + AUTOREFRESH_IS_PAUSED, + DATE_RANGE_START, + DATE_RANGE_END, + FILTERS, + SEARCH, + STATUS_FILTER, + } = CLIENT_DEFAULTS; + const result = getSupportedUrlParams({}); + expect(result).toEqual({ + absoluteDateRangeStart: MOCK_DATE_VALUE, + absoluteDateRangeEnd: MOCK_DATE_VALUE, + autorefreshInterval: AUTOREFRESH_INTERVAL, + autorefreshIsPaused: AUTOREFRESH_IS_PAUSED, + dateRangeStart: DATE_RANGE_START, + dateRangeEnd: DATE_RANGE_END, + excludedFilters: '', + filters: FILTERS, + focusConnectorField: false, + pagination: undefined, + search: SEARCH, + statusFilter: STATUS_FILTER, + query: '', + }); + }); + + it('returns the first item for string arrays', () => { + const result = getSupportedUrlParams({ + dateRangeStart: ['now-18d', 'now-11d', 'now-5m'], + }); + + const expected = { + absoluteDateRangeEnd: 20, + absoluteDateRangeStart: 20, + autorefreshInterval: 60000, + }; + + expect(result).toMatchObject(expected); + }); + + it('provides defaults for undefined values', () => { + const result = getSupportedUrlParams({ + dateRangeStart: undefined, + }); + + const expected = { + absoluteDateRangeStart: 20, + }; + + expect(result).toMatchObject(expected); + }); + + it('provides defaults for empty string array values', () => { + const result = getSupportedUrlParams({ + dateRangeStart: [], + }); + + const expected = { + absoluteDateRangeStart: 20, + }; + + expect(result).toMatchObject(expected); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.ts new file mode 100644 index 0000000000000..c9badbcf7f728 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/get_supported_url_params.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { parseIsPaused } from '../url_params/parse_is_paused'; +import { parseUrlInt } from '../url_params/parse_url_int'; +import { CLIENT_DEFAULTS } from '../../../../../common/constants'; +import { parseAbsoluteDate } from '../url_params/parse_absolute_date'; + +export interface SyntheticsUrlParams { + absoluteDateRangeStart: number; + absoluteDateRangeEnd: number; + autorefreshInterval: number; + autorefreshIsPaused: boolean; + dateRangeStart: string; + dateRangeEnd: string; + pagination?: string; + filters: string; + excludedFilters: string; + search: string; + statusFilter: string; + focusConnectorField?: boolean; + query?: string; +} + +const { + ABSOLUTE_DATE_RANGE_START, + ABSOLUTE_DATE_RANGE_END, + AUTOREFRESH_INTERVAL, + AUTOREFRESH_IS_PAUSED, + DATE_RANGE_START, + DATE_RANGE_END, + SEARCH, + FILTERS, + STATUS_FILTER, +} = CLIENT_DEFAULTS; + +/** + * Gets the current URL values for the application. If no item is present + * for the URL, a default value is supplied. + * + * @param params A set of key-value pairs where the value is either + * undefined or a string/string array. If a string array is passed, + * only the first item is chosen. Support for lists in the URL will + * require further development. + */ +export const getSupportedUrlParams = (params: { + [key: string]: string | string[] | undefined | null; +}): SyntheticsUrlParams => { + const filteredParams: { [key: string]: string | undefined } = {}; + Object.keys(params).forEach((key) => { + let value: string | undefined; + if (params[key] === undefined) { + value = undefined; + } else if (Array.isArray(params[key])) { + // @ts-ignore this must be an array, and it's ok if the + // 0th element is undefined + value = params[key][0]; + } else { + // @ts-ignore this will not be an array because the preceding + // block tests for that + value = params[key]; + } + filteredParams[key] = value; + }); + + const { + autorefreshInterval, + autorefreshIsPaused, + dateRangeStart, + dateRangeEnd, + filters, + excludedFilters, + search, + statusFilter, + pagination, + focusConnectorField, + query, + } = filteredParams; + + return { + pagination, + absoluteDateRangeStart: parseAbsoluteDate( + dateRangeStart || DATE_RANGE_START, + ABSOLUTE_DATE_RANGE_START + ), + absoluteDateRangeEnd: parseAbsoluteDate( + dateRangeEnd || DATE_RANGE_END, + ABSOLUTE_DATE_RANGE_END, + { roundUp: true } + ), + autorefreshInterval: parseUrlInt(autorefreshInterval, AUTOREFRESH_INTERVAL), + autorefreshIsPaused: parseIsPaused(autorefreshIsPaused, AUTOREFRESH_IS_PAUSED), + dateRangeStart: dateRangeStart || DATE_RANGE_START, + dateRangeEnd: dateRangeEnd || DATE_RANGE_END, + filters: filters || FILTERS, + excludedFilters: excludedFilters || '', + search: search || SEARCH, + statusFilter: statusFilter || STATUS_FILTER, + focusConnectorField: !!focusConnectorField, + query: query || '', + }; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/helper_with_redux.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/helper_with_redux.tsx new file mode 100644 index 0000000000000..23831b1a4bc25 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/helper_with_redux.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { Store } from 'redux'; +import { createStore as createReduxStore, applyMiddleware } from 'redux'; + +import { Provider as ReduxProvider } from 'react-redux'; +import createSagaMiddleware from 'redux-saga'; + +import { AppState } from '../../state'; +import { rootReducer } from '../../state/root_reducer'; +import { rootEffect } from '../../state/root_effect'; + +const createRealStore = (): Store => { + const sagaMW = createSagaMiddleware(); + const store = createReduxStore(rootReducer, applyMiddleware(sagaMW)); + sagaMW.run(rootEffect); + return store; +}; + +export const MountWithReduxProvider: React.FC<{ state?: AppState; useRealStore?: boolean }> = ({ + children, + state, + useRealStore, +}) => { + const store = useRealStore + ? createRealStore() + : { + dispatch: jest.fn(), + getState: jest.fn().mockReturnValue(state || { selectedFilters: null }), + subscribe: jest.fn(), + replaceReducer: jest.fn(), + [Symbol.observable]: jest.fn(), + }; + + return {children}; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/index.ts new file mode 100644 index 0000000000000..cebc9f5030293 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './rtl_helpers'; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx new file mode 100644 index 0000000000000..51c186c352a5b --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx @@ -0,0 +1,363 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { ReactElement, ReactNode } from 'react'; +import { of } from 'rxjs'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { + render as reactTestLibRender, + MatcherFunction, + RenderOptions, +} from '@testing-library/react'; +import { Router, Route } from 'react-router-dom'; +import { merge } from 'lodash'; +import { createMemoryHistory, History } from 'history'; +import { CoreStart } from '@kbn/core/public'; +import { I18nProvider } from '@kbn/i18n-react'; +import { EuiPageTemplate } from '@elastic/eui'; +import { coreMock } from '@kbn/core/public/mocks'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { configure } from '@testing-library/dom'; +import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; +import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; +import { KibanaContextProvider, KibanaServices } from '@kbn/kibana-react-plugin/public'; +import { triggersActionsUiMock } from '@kbn/triggers-actions-ui-plugin/public/mocks'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { mockState } from './__mocks__/syncthetics_store.mock'; +import { MountWithReduxProvider } from './helper_with_redux'; +import { AppState } from '../../state'; +import { stringifyUrlParams } from '../url_params'; +import { ClientPluginsStart } from '../../../../plugin'; +import { + SyntheticsRefreshContextProvider, + SyntheticsStartupPluginsContextProvider, +} from '../../contexts'; +import { kibanaService } from '../kibana_service'; + +type DeepPartial = { + [P in keyof T]?: DeepPartial; +}; + +interface KibanaProps { + services?: KibanaServices; +} + +export interface KibanaProviderOptions { + core?: DeepPartial & Partial; + kibanaProps?: KibanaProps; +} + +interface MockKibanaProviderProps extends KibanaProviderOptions { + children: ReactElement | ReactNode; +} + +interface MockRouterProps extends MockKibanaProviderProps { + history?: History; + path?: string; +} + +type Url = + | string + | { + path: string; + queryParams: Record; + }; + +interface RenderRouterOptions extends KibanaProviderOptions { + history?: History; + renderOptions?: Omit; + state?: Partial | DeepPartial; + url?: Url; + path?: string; +} + +function getSetting(key: string): T { + return 'MMM D, YYYY @ HH:mm:ss.SSS' as unknown as T; +} + +function setSetting$(key: string): T { + return of('MMM D, YYYY @ HH:mm:ss.SSS') as unknown as T; +} + +const createMockStore = () => { + let store: Record = {}; + return { + get: jest.fn().mockImplementation((key) => store[key]), + set: jest.fn().mockImplementation((key, value) => (store[key] = value)), + remove: jest.fn().mockImplementation((key: string) => delete store[key]), + clear: jest.fn().mockImplementation(() => (store = {})), + }; +}; + +const mockAppUrls: Record = { + uptime: '/app/uptime', + observability: '/app/observability', + '/home#/tutorial/uptimeMonitors': '/home#/tutorial/uptimeMonitors', +}; + +/* default mock core */ +export const defaultCore = coreMock.createStart(); +export const mockCore: () => Partial = () => { + const core: Partial = { + ...defaultCore, + application: { + ...defaultCore.application, + getUrlForApp: (app: string) => mockAppUrls[app], + navigateToUrl: jest.fn(), + capabilities: { + ...defaultCore.application.capabilities, + uptime: { + 'alerting:save': true, + configureSettings: true, + save: true, + show: true, + }, + actions: { + save: true, + }, + }, + }, + uiSettings: { + ...defaultCore.uiSettings, + get: getSetting, + get$: setSetting$, + }, + usageCollection: { + reportUiCounter: () => {}, + }, + triggersActionsUi: triggersActionsUiMock.createStart(), + storage: createMockStore(), + data: dataPluginMock.createStartContract(), + observability: { + useRulesLink: () => ({ href: 'newRuleLink' }), + navigation: { + // @ts-ignore + PageTemplate: EuiPageTemplate, + }, + ExploratoryViewEmbeddable: () =>
Embeddable exploratory view
, + }, + }; + + return core; +}; + +/* Mock Provider Components */ +export function MockKibanaProvider({ + children, + core, + kibanaProps, +}: MockKibanaProviderProps) { + const coreOptions = merge({}, mockCore(), core); + + kibanaService.core = coreOptions as any; + + return ( + + + + + {children} + + + + + ); +} + +export function MockRouter({ + children, + core, + path, + history = createMemoryHistory(), + kibanaProps, +}: MockRouterProps) { + return ( + + + {children} + + + ); +} +configure({ testIdAttribute: 'data-test-subj' }); + +export const MockRedux = ({ + state, + history = createMemoryHistory(), + children, + path, +}: { + state: Partial; + history?: History; + children: React.ReactNode; + path?: string; + useRealStore?: boolean; +}) => { + const testState: AppState = { + ...mockState, + ...state, + }; + + return ( + + + {children} + + + ); +}; + +export function WrappedHelper({ + children, + core, + kibanaProps, + state, + url, + useRealStore, + path, + history = createMemoryHistory(), +}: RenderRouterOptions & { children: ReactElement; useRealStore?: boolean }) { + const testState: AppState = merge({}, mockState, state); + + return ( + + + {children} + + + ); +} + +/* Custom react testing library render */ +export function render( + ui: ReactElement, + { + history = createMemoryHistory(), + core, + kibanaProps, + renderOptions, + state, + url, + path, + useRealStore, + }: RenderRouterOptions & { useRealStore?: boolean } = {} +) { + if (url) { + history = getHistoryFromUrl(url); + } + + return { + ...reactTestLibRender( + + {ui} + , + renderOptions + ), + history, + }; +} + +const getHistoryFromUrl = (url: Url) => { + if (typeof url === 'string') { + return createMemoryHistory({ + initialEntries: [url], + }); + } + + return createMemoryHistory({ + initialEntries: [url.path + stringifyUrlParams(url.queryParams)], + }); +}; + +const forNearestTag = + (tag: string) => + (getByText: (f: MatcherFunction) => HTMLElement | null) => + (text: string): HTMLElement | null => + getByText((_content: string, node: Element | null) => { + if (!node) return false; + const noOtherButtonHasText = Array.from(node.children).every( + (child) => child && (child.textContent !== text || child.tagName.toLowerCase() !== tag) + ); + return ( + noOtherButtonHasText && node.textContent === text && node.tagName.toLowerCase() === tag + ); + }); + +// This function allows us to query for the nearest button with test +// no matter whether it has nested tags or not (as EuiButton elements do). +export const forNearestButton = forNearestTag('button'); + +export const forNearestAnchor = forNearestTag('a'); + +export const makeSyntheticsPermissionsCore = ( + permissions: Partial<{ + 'alerting:save': boolean; + configureSettings: boolean; + save: boolean; + show: boolean; + }> +) => { + return { + application: { + capabilities: { + uptime: { + 'alerting:save': true, + configureSettings: true, + save: true, + show: true, + ...permissions, + }, + }, + }, + }; +}; + +// This function filters out the queried elements which appear only +// either on mobile or desktop. +// +// It does so by filtering those with the class passed as the `classWrapper`. +// For mobile, we filter classes which tell elements to be hidden on desktop. +// For desktop, we do the opposite. +// +// We have this function because EUI will manipulate the visibility of some +// elements through pure CSS, which we can't assert on tests. Therefore, +// we look for the corresponding class wrapper. +const finderWithClassWrapper = + (classWrapper: string) => + ( + getterFn: (f: MatcherFunction) => HTMLElement | null, + customAttribute?: keyof Element | keyof HTMLElement + ) => + (text: string): HTMLElement | null => + getterFn((_content: string, node: Element | null) => { + if (!node) return false; + // There are actually properties that are not in Element but which + // appear on the `node`, so we must cast the customAttribute as a keyof Element + const content = node[(customAttribute as keyof Element) ?? 'innerHTML']; + if (content === text && wrappedInClass(node, classWrapper)) return true; + return false; + }); + +const wrappedInClass = (element: HTMLElement | Element, classWrapper: string): boolean => { + if (element.className.includes(classWrapper)) return true; + if (element.parentElement) return wrappedInClass(element.parentElement, classWrapper); + return false; +}; + +export const forMobileOnly = finderWithClassWrapper('hideForDesktop'); +export const forDesktopOnly = finderWithClassWrapper('hideForMobile'); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.test.ts new file mode 100644 index 0000000000000..5e67d8f0e6026 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.test.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import DateMath from '@kbn/datemath'; +import { getSupportedUrlParams } from './get_supported_url_params'; +import { CLIENT_DEFAULTS } from '../../../../../common/constants'; + +describe('getSupportedUrlParams', () => { + let dateMathSpy: any; + const MOCK_DATE_VALUE = 20; + + beforeEach(() => { + dateMathSpy = jest.spyOn(DateMath, 'parse'); + dateMathSpy.mockReturnValue(MOCK_DATE_VALUE); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('returns custom values', () => { + const customValues = { + autorefreshInterval: '23', + autorefreshIsPaused: 'false', + dateRangeStart: 'now-15m', + dateRangeEnd: 'now', + monitorListPageIndex: '23', + monitorListPageSize: '50', + monitorListSortDirection: 'desc', + monitorListSortField: 'monitor.status', + search: 'monitor.status: down', + selectedPingStatus: 'up', + }; + + const expected = { + absoluteDateRangeEnd: 20, + absoluteDateRangeStart: 20, + autorefreshInterval: 23, + autorefreshIsPaused: false, + dateRangeEnd: 'now', + dateRangeStart: 'now-15m', + search: 'monitor.status: down', + }; + + const result = getSupportedUrlParams(customValues); + expect(result).toMatchObject(expected); + }); + + it('returns default values', () => { + const { + AUTOREFRESH_INTERVAL, + AUTOREFRESH_IS_PAUSED, + DATE_RANGE_START, + DATE_RANGE_END, + FILTERS, + SEARCH, + STATUS_FILTER, + } = CLIENT_DEFAULTS; + const result = getSupportedUrlParams({}); + expect(result).toEqual({ + absoluteDateRangeStart: MOCK_DATE_VALUE, + absoluteDateRangeEnd: MOCK_DATE_VALUE, + autorefreshInterval: AUTOREFRESH_INTERVAL, + autorefreshIsPaused: AUTOREFRESH_IS_PAUSED, + dateRangeStart: DATE_RANGE_START, + dateRangeEnd: DATE_RANGE_END, + excludedFilters: '', + filters: FILTERS, + focusConnectorField: false, + pagination: undefined, + search: SEARCH, + statusFilter: STATUS_FILTER, + query: '', + }); + }); + + it('returns the first item for string arrays', () => { + const result = getSupportedUrlParams({ + dateRangeStart: ['now-18d', 'now-11d', 'now-5m'], + }); + + const expected = { + absoluteDateRangeEnd: 20, + absoluteDateRangeStart: 20, + autorefreshInterval: 60000, + }; + + expect(result).toMatchObject(expected); + }); + + it('provides defaults for undefined values', () => { + const result = getSupportedUrlParams({ + dateRangeStart: undefined, + }); + + const expected = { + absoluteDateRangeStart: 20, + }; + + expect(result).toMatchObject(expected); + }); + + it('provides defaults for empty string array values', () => { + const result = getSupportedUrlParams({ + dateRangeStart: [], + }); + + const expected = { + absoluteDateRangeStart: 20, + }; + + expect(result).toMatchObject(expected); + }); +}); diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.ts new file mode 100644 index 0000000000000..1036c07973b27 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/get_supported_url_params.ts @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { parseIsPaused } from './parse_is_paused'; +import { parseUrlInt } from './parse_url_int'; +import { CLIENT_DEFAULTS } from '../../../../../common/constants'; +import { parseAbsoluteDate } from './parse_absolute_date'; + +// TODO: Change for Synthetics App if needed (Copied from legacy_uptime) +export interface SyntheticsUrlParams { + absoluteDateRangeStart: number; + absoluteDateRangeEnd: number; + autorefreshInterval: number; + autorefreshIsPaused: boolean; + dateRangeStart: string; + dateRangeEnd: string; + pagination?: string; + filters: string; + excludedFilters: string; + search: string; + statusFilter: string; + focusConnectorField?: boolean; + query?: string; +} + +const { + ABSOLUTE_DATE_RANGE_START, + ABSOLUTE_DATE_RANGE_END, + AUTOREFRESH_INTERVAL, + AUTOREFRESH_IS_PAUSED, + DATE_RANGE_START, + DATE_RANGE_END, + SEARCH, + FILTERS, + STATUS_FILTER, +} = CLIENT_DEFAULTS; + +/** + * Gets the current URL values for the application. If no item is present + * for the URL, a default value is supplied. + * + * @param params A set of key-value pairs where the value is either + * undefined or a string/string array. If a string array is passed, + * only the first item is chosen. Support for lists in the URL will + * require further development. + */ +export const getSupportedUrlParams = (params: { + [key: string]: string | string[] | undefined | null; +}): SyntheticsUrlParams => { + const filteredParams: { [key: string]: string | undefined } = {}; + Object.keys(params).forEach((key) => { + let value: string | undefined; + if (params[key] === undefined) { + value = undefined; + } else if (Array.isArray(params[key])) { + // @ts-ignore this must be an array, and it's ok if the + // 0th element is undefined + value = params[key][0]; + } else { + // @ts-ignore this will not be an array because the preceding + // block tests for that + value = params[key]; + } + filteredParams[key] = value; + }); + + const { + autorefreshInterval, + autorefreshIsPaused, + dateRangeStart, + dateRangeEnd, + filters, + excludedFilters, + search, + statusFilter, + pagination, + focusConnectorField, + query, + } = filteredParams; + + return { + pagination, + absoluteDateRangeStart: parseAbsoluteDate( + dateRangeStart || DATE_RANGE_START, + ABSOLUTE_DATE_RANGE_START + ), + absoluteDateRangeEnd: parseAbsoluteDate( + dateRangeEnd || DATE_RANGE_END, + ABSOLUTE_DATE_RANGE_END, + { roundUp: true } + ), + autorefreshInterval: parseUrlInt(autorefreshInterval, AUTOREFRESH_INTERVAL), + autorefreshIsPaused: parseIsPaused(autorefreshIsPaused, AUTOREFRESH_IS_PAUSED), + dateRangeStart: dateRangeStart || DATE_RANGE_START, + dateRangeEnd: dateRangeEnd || DATE_RANGE_END, + filters: filters || FILTERS, + excludedFilters: excludedFilters || '', + search: search || SEARCH, + statusFilter: statusFilter || STATUS_FILTER, + focusConnectorField: !!focusConnectorField, + query: query || '', + }; +}; diff --git a/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/index.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/index.ts new file mode 100644 index 0000000000000..a3f27112b0e81 --- /dev/null +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type { SyntheticsUrlParams } from './get_supported_url_params'; +export { getSupportedUrlParams } from './get_supported_url_params'; +export * from './stringify_url_params'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_absolute_date.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_absolute_date.test.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_absolute_date.test.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_absolute_date.test.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_absolute_date.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_absolute_date.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_absolute_date.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_absolute_date.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_is_paused.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_is_paused.test.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_is_paused.test.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_is_paused.test.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_is_paused.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_is_paused.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_is_paused.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_is_paused.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_url_int.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_url_int.test.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_url_int.test.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_url_int.test.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_url_int.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_url_int.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/parse_url_int.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/parse_url_int.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/stringify_url_params.test.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/stringify_url_params.test.ts similarity index 100% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/stringify_url_params.test.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/stringify_url_params.test.ts diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/stringify_url_params.ts b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/stringify_url_params.ts similarity index 86% rename from x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/stringify_url_params.ts rename to x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/stringify_url_params.ts index 2bb5f9a3c13e3..59c71af795cce 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/stringify_url_params.ts +++ b/x-pack/plugins/synthetics/public/apps/synthetics/utils/url_params/stringify_url_params.ts @@ -6,8 +6,8 @@ */ import { stringify } from 'query-string'; -import { UptimeUrlParams } from './url_params'; -import { CLIENT_DEFAULTS } from '../../../../common/constants'; +import { SyntheticsUrlParams } from './get_supported_url_params'; +import { CLIENT_DEFAULTS } from '../../../../../common/constants'; const { AUTOREFRESH_INTERVAL, @@ -17,7 +17,7 @@ const { FOCUS_CONNECTOR_FIELD, } = CLIENT_DEFAULTS; -export const stringifyUrlParams = (params: Partial, ignoreEmpty = false) => { +export const stringifyUrlParams = (params: Partial, ignoreEmpty = false) => { if (ignoreEmpty) { // We don't want to encode this values because they are often set to Date.now(), the relative // values in dateRangeStart are better for a URL. diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/app/render_app.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/app/render_app.tsx index efb35813201ae..446a329901815 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/app/render_app.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/app/render_app.tsx @@ -55,7 +55,7 @@ export function renderApp( isLogsAvailable: logs, renderGlobalHelpControls: () => setHelpExtension({ - appName: i18nFormatter.translate('xpack.synthetics.header.appName', { + appName: i18nFormatter.translate('xpack.synthetics.legacyHeader.appName', { defaultMessage: 'Uptime', }), links: [ diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.test.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.test.tsx index 38105052f352e..57ae3a6514505 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.test.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.test.tsx @@ -11,9 +11,9 @@ import 'jest-styled-components'; import { render } from '../lib/helper/rtl_helpers'; import { UptimePageTemplateComponent } from './uptime_page_template'; import { OVERVIEW_ROUTE } from '../../../common/constants'; -import { useBreakpoints } from '../hooks/use_breakpoints'; +import { useBreakpoints } from '../../apps/synthetics/hooks/use_breakpoints'; -jest.mock('../hooks/use_breakpoints', () => { +jest.mock('../../apps/synthetics/hooks/use_breakpoints', () => { const down = jest.fn().mockReturnValue(false); return { useBreakpoints: () => ({ down }), diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx index 08ebd5f06a69b..ade54e1e6f61a 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/app/uptime_page_template.tsx @@ -16,7 +16,7 @@ import { useNoDataConfig } from './use_no_data_config'; import { EmptyStateLoading } from '../components/overview/empty_state/empty_state_loading'; import { EmptyStateError } from '../components/overview/empty_state/empty_state_error'; import { useHasData } from '../components/overview/empty_state/use_has_data'; -import { useBreakpoints } from '../hooks/use_breakpoints'; +import { useBreakpoints } from '../../apps/synthetics/hooks/use_breakpoints'; interface Props { path: string; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/action_menu_content.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/action_menu_content.tsx index 1fb150bd9e70e..e1330d9924261 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/action_menu_content.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/action_menu_content.tsx @@ -17,7 +17,7 @@ import { useUptimeSettingsContext } from '../../../contexts/uptime_settings_cont import { useGetUrlParams } from '../../../hooks'; import { ToggleAlertFlyoutButton } from '../../overview/alerts/alerts_containers'; import { MONITOR_ROUTE, SETTINGS_ROUTE } from '../../../../../common/constants'; -import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params'; +import { stringifyUrlParams } from '../../../../apps/synthetics/utils/url_params/stringify_url_params'; import { InspectorHeaderLink } from './inspector_header_link'; import { monitorStatusSelector } from '../../../state/selectors'; import { ManageMonitorsBtn } from './manage_monitors_btn'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/page_tabs.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/page_tabs.tsx index 9711a9d7acb9e..08725ac203bab 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/page_tabs.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/common/header/page_tabs.tsx @@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n'; import { useHistory, useRouteMatch } from 'react-router-dom'; import { CERTIFICATES_ROUTE, OVERVIEW_ROUTE } from '../../../../../common/constants'; import { useGetUrlParams } from '../../../hooks'; -import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params'; +import { stringifyUrlParams } from '../../../../apps/synthetics/utils/url_params/stringify_url_params'; const tabs = [ { diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx index 1003b51319136..0e4d03e3ce438 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor/ping_list/columns/ping_timestamp/step_image_caption.tsx @@ -10,7 +10,7 @@ import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText, useEuiTheme } from import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { ScreenshotRefImageData } from '../../../../../../../common/runtime_types'; -import { useBreakpoints } from '../../../../../hooks'; +import { useBreakpoints } from '../../../../../../apps/synthetics/hooks/use_breakpoints'; import { nextAriaLabel, prevAriaLabel } from './translations'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx index fbd21fe09c1ec..0c1d56be587a4 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/monitor_management/monitor_list/monitor_list.tsx @@ -27,7 +27,7 @@ import { TCPSimpleFields, } from '../../../../../common/runtime_types'; import { UptimeSettingsContext } from '../../../contexts'; -import { useBreakpoints } from '../../../hooks'; +import { useBreakpoints } from '../../../../apps/synthetics/hooks/use_breakpoints'; import { MonitorManagementList as MonitorManagementListState } from '../../../state/reducers/monitor_management'; import * as labels from '../../overview/monitor_list/translations'; import { Actions } from './actions'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/columns/monitor_name_col.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/columns/monitor_name_col.tsx index 00590f46b51f1..0b6cc173acde1 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/columns/monitor_name_col.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/columns/monitor_name_col.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { EuiButtonEmpty, EuiText } from '@elastic/eui'; import { MonitorPageLink } from '../../../common/monitor_page_link'; import { useGetUrlParams } from '../../../../hooks'; -import { stringifyUrlParams } from '../../../../lib/helper/stringify_url_params'; +import { stringifyUrlParams } from '../../../../../apps/synthetics/utils/url_params/stringify_url_params'; import { MonitorSummary } from '../../../../../../common/runtime_types/monitor'; import { useFilterUpdate } from '../../../../hooks/use_filter_update'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list_drawer/most_recent_error.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list_drawer/most_recent_error.tsx index 00484b8c40070..c5cdc60253f94 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list_drawer/most_recent_error.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/components/overview/monitor_list/monitor_list_drawer/most_recent_error.tsx @@ -15,7 +15,7 @@ import moment from 'moment'; import { i18n } from '@kbn/i18n'; import { MonitorPageLink } from '../../../common/monitor_page_link'; import { useGetUrlParams } from '../../../../hooks'; -import { stringifyUrlParams } from '../../../../lib/helper/stringify_url_params'; +import { stringifyUrlParams } from '../../../../../apps/synthetics/utils/url_params/stringify_url_params'; import { PingError } from '../../../../../../common/runtime_types'; interface MostRecentErrorProps { diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/hooks/index.ts b/x-pack/plugins/synthetics/public/legacy_uptime/hooks/index.ts index b93373481f9f3..6d2a826caa4b4 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/hooks/index.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/hooks/index.ts @@ -12,5 +12,4 @@ export * from './use_search_text'; export * from './use_cert_status'; export * from './use_telemetry'; export * from './use_url_params'; -export * from './use_breakpoints'; export { useUptimeDataView } from '../contexts/uptime_data_view_context'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breadcrumbs.ts b/x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breadcrumbs.ts index 26e9d2d0fd285..0befbeb14832c 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breadcrumbs.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/hooks/use_breadcrumbs.ts @@ -11,7 +11,7 @@ import { MouseEvent, useEffect } from 'react'; import { EuiBreadcrumb } from '@elastic/eui'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { UptimeUrlParams } from '../lib/helper'; -import { stringifyUrlParams } from '../lib/helper/stringify_url_params'; +import { stringifyUrlParams } from '../../apps/synthetics/utils/url_params/stringify_url_params'; import { useUrlParams } from '.'; import { PLUGIN } from '../../../common/constants/plugin'; @@ -57,7 +57,7 @@ export const makeBaseBreadcrumb = ( href: observabilityPath, }, { - text: i18n.translate('xpack.synthetics.breadcrumbs.overviewBreadcrumbText', { + text: i18n.translate('xpack.synthetics.breadcrumbs.legacyOverviewBreadcrumbText', { defaultMessage: 'Uptime', }), href: uptimePath, diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx index db55ee3805ef1..3a1fed73b90d6 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/rtl_helpers.tsx @@ -30,7 +30,7 @@ import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { mockState } from '../__mocks__/uptime_store.mock'; import { MountWithReduxProvider } from './helper_with_redux'; import { AppState } from '../../state'; -import { stringifyUrlParams } from './stringify_url_params'; +import { stringifyUrlParams } from '../../../apps/synthetics/utils/url_params/stringify_url_params'; import { ClientPluginsStart } from '../../../plugin'; import { UptimeRefreshContextProvider, UptimeStartupPluginsContextProvider } from '../../contexts'; import { kibanaService } from '../../state/kibana_service'; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/get_supported_url_params.ts b/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/get_supported_url_params.ts index 703b2257ee176..246db87b983fe 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/get_supported_url_params.ts +++ b/x-pack/plugins/synthetics/public/legacy_uptime/lib/helper/url_params/get_supported_url_params.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { parseIsPaused } from './parse_is_paused'; -import { parseUrlInt } from './parse_url_int'; +import { parseIsPaused } from '../../../../apps/synthetics/utils/url_params/parse_is_paused'; +import { parseUrlInt } from '../../../../apps/synthetics/utils/url_params/parse_url_int'; import { CLIENT_DEFAULTS } from '../../../../../common/constants'; -import { parseAbsoluteDate } from './parse_absolute_date'; +import { parseAbsoluteDate } from '../../../../apps/synthetics/utils/url_params/parse_absolute_date'; export interface UptimeUrlParams { absoluteDateRangeStart: number; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx index ee33191c3799e..c09da77a6f559 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/pages/synthetics/checks_navigation.tsx @@ -12,7 +12,7 @@ import { useHistory } from 'react-router-dom'; import moment from 'moment'; import { SyntheticsJourneyApiResponse } from '../../../../common/runtime_types/ping'; import { getShortTimeStamp } from '../../components/overview/monitor_list/columns/monitor_status_column'; -import { useBreakpoints } from '../../hooks/use_breakpoints'; +import { useBreakpoints } from '../../../apps/synthetics/hooks/use_breakpoints'; interface Props { timestamp: string; diff --git a/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx b/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx index 1b8706ad4cb00..ac9ffdd2b70e7 100644 --- a/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx +++ b/x-pack/plugins/synthetics/public/legacy_uptime/routes.tsx @@ -72,7 +72,7 @@ type RouteProps = { }; } & EuiPageTemplateProps; -const baseTitle = i18n.translate('xpack.synthetics.routes.baseTitle', { +const baseTitle = i18n.translate('xpack.synthetics.routes.legacyBaseTitle', { defaultMessage: 'Uptime - Kibana', }); From 486bf6d50a7bb76b57b2f3834392578a19d18dda Mon Sep 17 00:00:00 2001 From: Gabriel Landau <42078554+gabriellandau@users.noreply.github.com> Date: Wed, 4 May 2022 12:48:05 -0400 Subject: [PATCH 38/68] Add some missing Endpoint telemetry fields (#131529) * Add some missing Endpoint telemetry fields * Update test case * Fix syntax * Get all of process.pe * lint * Add more token and DLL fields * Alphabetical * Add --- .../lib/telemetry/filterlists/endpoint_alerts.ts | 14 ++++++++------ .../server/lib/telemetry/sender.test.ts | 12 ++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/endpoint_alerts.ts b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/endpoint_alerts.ts index 5a62513b1ab38..41394144e9c66 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/endpoint_alerts.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/endpoint_alerts.ts @@ -17,9 +17,7 @@ const baseAllowlistFields: AllowlistFields = { command_line: true, hash: true, pid: true, - pe: { - original_file_name: true, - }, + pe: true, uptime: true, Ext: { architecture: true, @@ -27,11 +25,15 @@ const baseAllowlistFields: AllowlistFields = { dll: true, malware_signature: true, memory_region: true, + protection: true, real: { entity_id: true, }, token: { + elevation: true, + elevation_type: true, integrity_level_name: true, + security_attributes: true, }, }, thread: true, @@ -44,10 +46,9 @@ const allowlistBaseEventFields: AllowlistFields = { name: true, path: true, code_signature: true, + hash: true, malware_signature: true, - pe: { - original_file_name: true, - }, + pe: true, }, dns: true, event: true, @@ -61,6 +62,7 @@ const allowlistBaseEventFields: AllowlistFields = { mtime: true, directory: true, hash: true, + pe: true, Ext: { bytes_compressed: true, bytes_compressed_present: true, diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts b/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts index 71e8b8e11c215..240634bccdca4 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/sender.test.ts @@ -58,6 +58,9 @@ describe('TelemetryEventsSender', () => { path: 'X', test: 'me', another: 'nope', + pe: { + original_file_name: 'malware.exe', + }, Ext: { bytes_compressed: 'data up to 4mb', bytes_compressed_present: 'data up to 4mb', @@ -89,6 +92,9 @@ describe('TelemetryEventsSender', () => { executable: null, // null fields are never allowlisted working_directory: '/some/usr/dir', entity_id: 'some_entity_id', + Ext: { + protection: 'PsProtectedSignerAntimalware-Light', + }, }, Responses: '{ "result": 0 }', // >= 7.15 Target: { @@ -132,6 +138,9 @@ describe('TelemetryEventsSender', () => { size: 3, created: 0, path: 'X', + pe: { + original_file_name: 'malware.exe', + }, Ext: { bytes_compressed: 'data up to 4mb', bytes_compressed_present: 'data up to 4mb', @@ -159,6 +168,9 @@ describe('TelemetryEventsSender', () => { name: 'foo.exe', working_directory: '/some/usr/dir', entity_id: 'some_entity_id', + Ext: { + protection: 'PsProtectedSignerAntimalware-Light', + }, }, Responses: '{ "result": 0 }', Target: { From 1a849dc2b6d0741f3554824c8423e469263f1c34 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 4 May 2022 09:52:34 -0700 Subject: [PATCH 39/68] [flaky-tests] require using the new UI to trigger (#131534) --- .buildkite/pipelines/flaky_tests/pipeline.js | 204 ++++++++++++++---- .buildkite/pipelines/flaky_tests/pipeline.sh | 3 + .buildkite/pipelines/flaky_tests/runner.js | 213 ------------------- .buildkite/pipelines/flaky_tests/runner.sh | 8 - 4 files changed, 168 insertions(+), 260 deletions(-) delete mode 100644 .buildkite/pipelines/flaky_tests/runner.js delete mode 100755 .buildkite/pipelines/flaky_tests/runner.sh diff --git a/.buildkite/pipelines/flaky_tests/pipeline.js b/.buildkite/pipelines/flaky_tests/pipeline.js index b7f93412edb37..000f9954b76f1 100644 --- a/.buildkite/pipelines/flaky_tests/pipeline.js +++ b/.buildkite/pipelines/flaky_tests/pipeline.js @@ -6,56 +6,182 @@ * Side Public License, v 1. */ +const configJson = process.env.KIBANA_FLAKY_TEST_RUNNER_CONFIG; +if (!configJson) { + console.error('+++ Triggering directly is not supported anymore'); + console.error( + `Please use the "Trigger Flaky Test Runner" UI to run the Flaky Test Runner. You can find the UI at the URL below:` + ); + console.error('\n https://ci-stats.kibana.dev/trigger_flaky_test_runner\n'); + process.exit(1); +} + const groups = /** @type {Array<{key: string, name: string, ciGroups: number }>} */ ( require('./groups.json').groups ); -const stepInput = (key, nameOfSuite) => { - return { - key: `ftsr-suite/${key}`, - text: nameOfSuite, - required: false, - default: '0', +const concurrency = 25; +const initialJobs = 3; + +function getTestSuitesFromJson(json) { + const fail = (errorMsg) => { + console.error('+++ Invalid test config provided'); + console.error(`${errorMsg}: ${json}`); + process.exit(1); }; -}; -const inputs = [ - { - key: 'ftsr-override-count', - text: 'Override for all suites', - default: '0', - required: true, - }, -]; - -for (const group of groups) { - if (!group.ciGroups) { - inputs.push(stepInput(group.key, group.name)); - } else { - for (let i = 1; i <= group.ciGroups; i++) { - inputs.push(stepInput(`${group.key}/${i}`, `${group.name} ${i}`)); + let parsed; + try { + parsed = JSON.parse(json); + } catch (error) { + fail(`JSON test config did not parse correctly`); + } + + if (!Array.isArray(parsed)) { + fail(`JSON test config must be an array`); + } + + /** @type {Array<{ key: string, count: number }>} */ + const testSuites = []; + for (const item of parsed) { + if (typeof item !== 'object' || item === null) { + fail(`testSuites must be objects`); + } + const key = item.key; + if (typeof key !== 'string') { + fail(`testSuite.key must be a string`); + } + const count = item.count; + if (typeof count !== 'number') { + fail(`testSuite.count must be a number`); } + testSuites.push({ + key, + count, + }); } + + return testSuites; } +const testSuites = getTestSuitesFromJson(configJson); +const totalJobs = testSuites.reduce((acc, t) => acc + t.count, initialJobs); + +if (totalJobs > 500) { + console.error('+++ Too many tests'); + console.error( + `Buildkite builds can only contain 500 steps in total. Found ${totalJobs} in total. Make sure your test runs are less than ${ + 500 - initialJobs + }` + ); + process.exit(1); +} + +const steps = []; const pipeline = { - steps: [ - { - input: 'Number of Runs - Click Me', - fields: inputs, - if: `build.env('KIBANA_FLAKY_TEST_RUNNER_CONFIG') == null`, - }, - { - wait: '~', - }, - { - command: '.buildkite/pipelines/flaky_tests/runner.sh', - label: 'Create pipeline', - agents: { - queue: 'kibana-default', - }, - }, - ], + env: { + IGNORE_SHIP_CI_STATS_ERROR: 'true', + }, + steps: steps, }; +steps.push({ + command: '.buildkite/scripts/steps/build_kibana.sh', + label: 'Build Kibana Distribution and Plugins', + agents: { queue: 'c2-8' }, + key: 'build', + if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''", +}); + +for (const testSuite of testSuites) { + const TEST_SUITE = testSuite.key; + const RUN_COUNT = testSuite.count; + const UUID = process.env.UUID; + + const JOB_PARTS = TEST_SUITE.split('/'); + const IS_XPACK = JOB_PARTS[0] === 'xpack'; + const TASK = JOB_PARTS[1]; + const CI_GROUP = JOB_PARTS.length > 2 ? JOB_PARTS[2] : ''; + + if (RUN_COUNT < 1) { + continue; + } + + switch (TASK) { + case 'cigroup': + if (IS_XPACK) { + steps.push({ + command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/xpack_cigroup.sh`, + label: `Default CI Group ${CI_GROUP}`, + agents: { queue: 'n2-4' }, + depends_on: 'build', + parallelism: RUN_COUNT, + concurrency: concurrency, + concurrency_group: UUID, + concurrency_method: 'eager', + }); + } else { + steps.push({ + command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/oss_cigroup.sh`, + label: `OSS CI Group ${CI_GROUP}`, + agents: { queue: 'ci-group-4d' }, + depends_on: 'build', + parallelism: RUN_COUNT, + concurrency: concurrency, + concurrency_group: UUID, + concurrency_method: 'eager', + }); + } + break; + + case 'firefox': + steps.push({ + command: `.buildkite/scripts/steps/functional/${IS_XPACK ? 'xpack' : 'oss'}_firefox.sh`, + label: `${IS_XPACK ? 'Default' : 'OSS'} Firefox`, + agents: { queue: IS_XPACK ? 'n2-4' : 'ci-group-4d' }, + depends_on: 'build', + parallelism: RUN_COUNT, + concurrency: concurrency, + concurrency_group: UUID, + concurrency_method: 'eager', + }); + break; + + case 'accessibility': + steps.push({ + command: `.buildkite/scripts/steps/functional/${ + IS_XPACK ? 'xpack' : 'oss' + }_accessibility.sh`, + label: `${IS_XPACK ? 'Default' : 'OSS'} Accessibility`, + agents: { queue: IS_XPACK ? 'n2-4' : 'ci-group-4d' }, + depends_on: 'build', + parallelism: RUN_COUNT, + concurrency: concurrency, + concurrency_group: UUID, + concurrency_method: 'eager', + }); + break; + + case 'cypress': + const CYPRESS_SUITE = CI_GROUP; + const group = groups.find((group) => group.key.includes(CYPRESS_SUITE)); + if (!group) { + throw new Error( + `Group configuration was not found in groups.json for the following cypress suite: {${CYPRESS_SUITE}}.` + ); + } + steps.push({ + command: `.buildkite/scripts/steps/functional/${CYPRESS_SUITE}.sh`, + label: group.name, + agents: { queue: 'ci-group-6' }, + depends_on: 'build', + parallelism: RUN_COUNT, + concurrency: concurrency, + concurrency_group: UUID, + concurrency_method: 'eager', + }); + break; + } +} + console.log(JSON.stringify(pipeline, null, 2)); diff --git a/.buildkite/pipelines/flaky_tests/pipeline.sh b/.buildkite/pipelines/flaky_tests/pipeline.sh index 6335cd5490af0..17fa0152e8b34 100755 --- a/.buildkite/pipelines/flaky_tests/pipeline.sh +++ b/.buildkite/pipelines/flaky_tests/pipeline.sh @@ -2,4 +2,7 @@ set -euo pipefail +UUID="$(cat /proc/sys/kernel/random/uuid)" +export UUID + node .buildkite/pipelines/flaky_tests/pipeline.js | buildkite-agent pipeline upload diff --git a/.buildkite/pipelines/flaky_tests/runner.js b/.buildkite/pipelines/flaky_tests/runner.js deleted file mode 100644 index a5cc237a1814a..0000000000000 --- a/.buildkite/pipelines/flaky_tests/runner.js +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -const { execSync } = require('child_process'); -const groups = /** @type {Array<{key: string, name: string, ciGroups: number }>} */ ( - require('./groups.json').groups -); - -const concurrency = 25; -const defaultCount = concurrency * 2; -const initialJobs = 3; - -function getTestSuitesFromMetadata() { - const keys = execSync('buildkite-agent meta-data keys') - .toString() - .split('\n') - .filter((k) => k.startsWith('ftsr-suite/')); - - const overrideCount = execSync(`buildkite-agent meta-data get 'ftsr-override-count'`) - .toString() - .trim(); - - const testSuites = []; - for (const key of keys) { - if (!key) { - continue; - } - - const value = - overrideCount && overrideCount !== '0' - ? overrideCount - : execSync(`buildkite-agent meta-data get '${key}'`).toString().trim(); - - const count = value === '' ? defaultCount : parseInt(value); - testSuites.push({ - key: key.replace('ftsr-suite/', ''), - count: count, - }); - } - - return testSuites; -} - -function getTestSuitesFromJson(json) { - const fail = (errorMsg) => { - console.error('+++ Invalid test config provided'); - console.error(`${errorMsg}: ${json}`); - process.exit(1); - }; - - let parsed; - try { - parsed = JSON.parse(json); - } catch (error) { - fail(`JSON test config did not parse correctly`); - } - - if (!Array.isArray(parsed)) { - fail(`JSON test config must be an array`); - } - - /** @type {Array<{ key: string, count: number }>} */ - const testSuites = []; - for (const item of parsed) { - if (typeof item !== 'object' || item === null) { - fail(`testSuites must be objects`); - } - const key = item.key; - if (typeof key !== 'string') { - fail(`testSuite.key must be a string`); - } - const count = item.count; - if (typeof count !== 'number') { - fail(`testSuite.count must be a number`); - } - testSuites.push({ - key, - count, - }); - } - - return testSuites; -} - -const testSuites = process.env.KIBANA_FLAKY_TEST_RUNNER_CONFIG - ? getTestSuitesFromJson(process.env.KIBANA_FLAKY_TEST_RUNNER_CONFIG) - : getTestSuitesFromMetadata(); - -const totalJobs = testSuites.reduce((acc, t) => acc + t.count, initialJobs); - -if (totalJobs > 500) { - console.error('+++ Too many tests'); - console.error( - `Buildkite builds can only contain 500 steps in total. Found ${totalJobs} in total. Make sure your test runs are less than ${ - 500 - initialJobs - }` - ); - process.exit(1); -} - -const steps = []; -const pipeline = { - env: { - IGNORE_SHIP_CI_STATS_ERROR: 'true', - }, - steps: steps, -}; - -steps.push({ - command: '.buildkite/scripts/steps/build_kibana.sh', - label: 'Build Kibana Distribution and Plugins', - agents: { queue: 'c2-8' }, - key: 'build', - if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''", -}); - -for (const testSuite of testSuites) { - const TEST_SUITE = testSuite.key; - const RUN_COUNT = testSuite.count; - const UUID = process.env.UUID; - - const JOB_PARTS = TEST_SUITE.split('/'); - const IS_XPACK = JOB_PARTS[0] === 'xpack'; - const TASK = JOB_PARTS[1]; - const CI_GROUP = JOB_PARTS.length > 2 ? JOB_PARTS[2] : ''; - - if (RUN_COUNT < 1) { - continue; - } - - switch (TASK) { - case 'cigroup': - if (IS_XPACK) { - steps.push({ - command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/xpack_cigroup.sh`, - label: `Default CI Group ${CI_GROUP}`, - agents: { queue: 'n2-4' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - } else { - steps.push({ - command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/oss_cigroup.sh`, - label: `OSS CI Group ${CI_GROUP}`, - agents: { queue: 'ci-group-4d' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - } - break; - - case 'firefox': - steps.push({ - command: `.buildkite/scripts/steps/functional/${IS_XPACK ? 'xpack' : 'oss'}_firefox.sh`, - label: `${IS_XPACK ? 'Default' : 'OSS'} Firefox`, - agents: { queue: IS_XPACK ? 'n2-4' : 'ci-group-4d' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - break; - - case 'accessibility': - steps.push({ - command: `.buildkite/scripts/steps/functional/${ - IS_XPACK ? 'xpack' : 'oss' - }_accessibility.sh`, - label: `${IS_XPACK ? 'Default' : 'OSS'} Accessibility`, - agents: { queue: IS_XPACK ? 'n2-4' : 'ci-group-4d' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - break; - - case 'cypress': - const CYPRESS_SUITE = CI_GROUP; - const group = groups.find((group) => group.key.includes(CYPRESS_SUITE)); - if (!group) { - throw new Error( - `Group configuration was not found in groups.json for the following cypress suite: {${CYPRESS_SUITE}}.` - ); - } - steps.push({ - command: `.buildkite/scripts/steps/functional/${CYPRESS_SUITE}.sh`, - label: group.name, - agents: { queue: 'ci-group-6' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - break; - } -} - -console.log(JSON.stringify(pipeline, null, 2)); diff --git a/.buildkite/pipelines/flaky_tests/runner.sh b/.buildkite/pipelines/flaky_tests/runner.sh deleted file mode 100755 index b541af88a408a..0000000000000 --- a/.buildkite/pipelines/flaky_tests/runner.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -UUID="$(cat /proc/sys/kernel/random/uuid)" -export UUID - -node .buildkite/pipelines/flaky_tests/runner.js | buildkite-agent pipeline upload From 2288342143dd6215d6910ccd35d3924f5caa4b7b Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Wed, 4 May 2022 12:34:22 -0500 Subject: [PATCH 40/68] Bump versions.json (#131545) --- versions.json | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/versions.json b/versions.json index 6dfe620c9fd7e..3223c4e8c62dd 100644 --- a/versions.json +++ b/versions.json @@ -8,16 +8,11 @@ "currentMinor": true }, { - "version": "8.2.0", + "version": "8.2.1", "branch": "8.2", "currentMajor": true, "previousMinor": true }, - { - "version": "8.1.3", - "branch": "8.1", - "currentMajor": true - }, { "version": "7.17.3", "branch": "7.17", From 1c99a04c0414c32ad274c652be76b48233e0c23b Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 4 May 2022 12:45:05 -0500 Subject: [PATCH 41/68] skip flaky suite (#131535) --- .../apps/triggers_actions_ui/alerts_list.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts index 49a3fada3dbef..5f6c4501476bf 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_list.ts @@ -31,7 +31,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('rulesTab'); } - describe('rules list', function () { + // FLAKY: https://github.com/elastic/kibana/issues/131535 + describe.skip('rules list', function () { before(async () => { await pageObjects.common.navigateToApp('triggersActions'); await testSubjects.click('rulesTab'); From 47f4658b363cafcc48c00a0183083a9f5bbcd7df Mon Sep 17 00:00:00 2001 From: mgiota Date: Wed, 4 May 2022 19:57:32 +0200 Subject: [PATCH 42/68] [Actionable Observability] consume shareable status filter (#131219) * use shareable status filter * clean up and remove remnants from old status implementation * bring back props * fix more CI issues after renaming * fix i118n issues * fix failing unit tests --- .../public/hooks/use_fetch_rules.ts | 14 +++++++- ...observability_public_plugins_start.mock.ts | 1 + .../rules/components/last_response_filter.tsx | 6 ++-- .../public/pages/rules/config.ts | 19 ----------- .../public/pages/rules/index.tsx | 10 +++++- .../public/pages/rules/translations.ts | 21 ------------ .../observability/public/pages/rules/types.ts | 34 ++----------------- .../translations/translations/fr-FR.json | 3 -- .../translations/translations/ja-JP.json | 3 -- .../translations/translations/zh-CN.json | 3 -- .../triggers_actions_ui/public/index.ts | 1 + 11 files changed, 30 insertions(+), 85 deletions(-) diff --git a/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts b/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts index a09626654e6f8..de0127b08213e 100644 --- a/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts +++ b/x-pack/plugins/observability/public/hooks/use_fetch_rules.ts @@ -16,6 +16,7 @@ import { useKibana } from '../utils/kibana_react'; export function useFetchRules({ searchText, ruleLastResponseFilter, + ruleStatusesFilter, typesFilter, setPage, page, @@ -43,6 +44,7 @@ export function useFetchRules({ searchText, typesFilter: typesFilter.length > 0 ? typesFilter : OBSERVABILITY_RULE_TYPES, ruleExecutionStatusesFilter: ruleLastResponseFilter, + ruleStatusesFilter, sort, }); setRulesState((oldState) => ({ @@ -58,6 +60,7 @@ export function useFetchRules({ const isFilterApplied = !( isEmpty(searchText) && isEmpty(ruleLastResponseFilter) && + isEmpty(ruleStatusesFilter) && isEmpty(typesFilter) ); @@ -66,7 +69,16 @@ export function useFetchRules({ setRulesState((oldState) => ({ ...oldState, isLoading: false, error: RULES_LOAD_ERROR })); } setInitialLoad(false); - }, [http, page, setPage, searchText, ruleLastResponseFilter, typesFilter, sort]); + }, [ + http, + page, + setPage, + searchText, + ruleLastResponseFilter, + ruleStatusesFilter, + typesFilter, + sort, + ]); useEffect(() => { fetchRules(); }, [fetchRules]); diff --git a/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts b/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts index 930b75f578eb1..50836859a5415 100644 --- a/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts +++ b/x-pack/plugins/observability/public/observability_public_plugins_start.mock.ts @@ -38,6 +38,7 @@ const triggersActionsUiStartMock = { getAddAlertFlyout: jest.fn(), getRuleStatusDropdown: jest.fn(), getRuleTagBadge: jest.fn(), + getRuleStatusFilter: jest.fn(), ruleTypeRegistry: { has: jest.fn(), register: jest.fn(), diff --git a/x-pack/plugins/observability/public/pages/rules/components/last_response_filter.tsx b/x-pack/plugins/observability/public/pages/rules/components/last_response_filter.tsx index d7154c47fecf7..f74c56f7f2792 100644 --- a/x-pack/plugins/observability/public/pages/rules/components/last_response_filter.tsx +++ b/x-pack/plugins/observability/public/pages/rules/components/last_response_filter.tsx @@ -18,12 +18,12 @@ import { } from '@elastic/eui'; import { RuleExecutionStatuses, RuleExecutionStatusValues } from '@kbn/alerting-plugin/common'; import { getHealthColor, rulesStatusesTranslationsMapping } from '../config'; -import { StatusFilterProps } from '../types'; +import { LastResponseFilterProps } from '../types'; -export const LastResponseFilter: React.FunctionComponent = ({ +export const LastResponseFilter: React.FunctionComponent = ({ selectedStatuses, onChange, -}: StatusFilterProps) => { +}: LastResponseFilterProps) => { const [selectedValues, setSelectedValues] = useState(selectedStatuses); const [isPopoverOpen, setIsPopoverOpen] = useState(false); diff --git a/x-pack/plugins/observability/public/pages/rules/config.ts b/x-pack/plugins/observability/public/pages/rules/config.ts index 9da846c2c1cc4..8c39acb75976d 100644 --- a/x-pack/plugins/observability/public/pages/rules/config.ts +++ b/x-pack/plugins/observability/public/pages/rules/config.ts @@ -7,7 +7,6 @@ import { RuleExecutionStatuses } from '@kbn/alerting-plugin/common'; import { Rule, RuleTypeIndex, RuleType } from '@kbn/triggers-actions-ui-plugin/public'; -import { Status, RuleStatus } from './types'; import { RULE_STATUS_OK, RULE_STATUS_ACTIVE, @@ -15,26 +14,8 @@ import { RULE_STATUS_PENDING, RULE_STATUS_UNKNOWN, RULE_STATUS_WARNING, - RULE_STATUS_ENABLED, - RULE_STATUS_DISABLED, - RULE_STATUS_SNOOZED_INDEFINITELY, } from './translations'; -export const statusMap: Status = { - [RuleStatus.enabled]: { - color: 'primary', - label: RULE_STATUS_ENABLED, - }, - [RuleStatus.disabled]: { - color: 'default', - label: RULE_STATUS_DISABLED, - }, - [RuleStatus.snoozed]: { - color: 'warning', - label: RULE_STATUS_SNOOZED_INDEFINITELY, - }, -}; - export const DEFAULT_SEARCH_PAGE_SIZE: number = 25; export function getHealthColor(status: RuleExecutionStatuses) { diff --git a/x-pack/plugins/observability/public/pages/rules/index.tsx b/x-pack/plugins/observability/public/pages/rules/index.tsx index 3d005c30fc747..801ea24fb46c3 100644 --- a/x-pack/plugins/observability/public/pages/rules/index.tsx +++ b/x-pack/plugins/observability/public/pages/rules/index.tsx @@ -27,6 +27,7 @@ import { disableRule, snoozeRule, useLoadRuleTypes, + RuleStatus, unsnoozeRule, } from '@kbn/triggers-actions-ui-plugin/public'; import { RuleExecutionStatus, ALERTS_FEATURE_ID } from '@kbn/alerting-plugin/common'; @@ -93,7 +94,7 @@ function RulesPage() { }); const [inputText, setInputText] = useState(); const [searchText, setSearchText] = useState(); - // const [ruleLastResponseFilter, setRuleLastResponseFilter] = useState([]); + const [ruleStatusesFilter, setRuleStatusesFilter] = useState([]); const [typesFilter, setTypesFilter] = useState([]); const [currentRuleToEdit, setCurrentRuleToEdit] = useState(null); const [rulesToDelete, setRulesToDelete] = useState([]); @@ -110,6 +111,7 @@ function RulesPage() { const { rulesState, setRulesState, reload, noData, initialLoad } = useFetchRules({ searchText, ruleLastResponseFilter: lastResponse, + ruleStatusesFilter, typesFilter, page, setPage, @@ -353,6 +355,12 @@ function RulesPage() { onChange={setExecutionStatusFilter} /> + + {triggersActionsUi.getRuleStatusFilter({ + selectedStatuses: ruleStatusesFilter, + onChange: setRuleStatusesFilter, + })} + void; -} - -export enum RuleStatus { - enabled = 'enabled', - disabled = 'disabled', - snoozed = 'snoozed', -} - -export type Status = Record< - RuleStatus, - { - color: string; - label: string; - } ->; - -export interface StatusContextProps { - item: RuleTableItem; - disabled: boolean; - onStatusChanged: (status: RuleStatus) => void; - enableRule: (rule: Rule) => Promise; - disableRule: (rule: Rule) => Promise; - muteRule: (rule: Rule) => Promise; - unMuteRule: (rule: Rule) => Promise; -} +import { RuleTableItem, Rule, RuleStatus } from '@kbn/triggers-actions-ui-plugin/public'; -export interface StatusFilterProps { +export interface LastResponseFilterProps { selectedStatuses: string[]; onChange?: (selectedRuleStatusesIds: string[]) => void; } @@ -71,6 +42,7 @@ export interface Pagination { export interface FetchRulesProps { searchText: string | undefined; ruleLastResponseFilter: string[]; + ruleStatusesFilter: RuleStatus[]; typesFilter: string[]; page: Pagination; setPage: Dispatch>; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index c4d73013a4591..7ee56f53e1f89 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -21855,13 +21855,10 @@ "xpack.observability.rules.rulesTable.columns.statusTitle": "Statut", "xpack.observability.rules.rulesTable.pluralTitle": "règles", "xpack.observability.rules.rulesTable.ruleStatusActive": "Actif", - "xpack.observability.rules.rulesTable.ruleStatusDisabled": "Désactivé", - "xpack.observability.rules.rulesTable.ruleStatusEnabled": "Activé", "xpack.observability.rules.rulesTable.ruleStatusError": "Erreur", "xpack.observability.rules.rulesTable.ruleStatusLicenseError": "Erreur de licence", "xpack.observability.rules.rulesTable.ruleStatusOk": "Ok", "xpack.observability.rules.rulesTable.ruleStatusPending": "En attente", - "xpack.observability.rules.rulesTable.ruleStatusSnoozedIndefinitely": "Répété indéfiniment", "xpack.observability.rules.rulesTable.ruleStatusUnknown": "Inconnu", "xpack.observability.rules.rulesTable.ruleStatusWarning": "avertissement", "xpack.observability.rules.rulesTable.singleTitle": "règle", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ac5090885883c..2cd3f174be443 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -21877,13 +21877,10 @@ "xpack.observability.rules.rulesTable.columns.statusTitle": "ステータス", "xpack.observability.rules.rulesTable.pluralTitle": "ルール", "xpack.observability.rules.rulesTable.ruleStatusActive": "アクティブ", - "xpack.observability.rules.rulesTable.ruleStatusDisabled": "無効", - "xpack.observability.rules.rulesTable.ruleStatusEnabled": "有効", "xpack.observability.rules.rulesTable.ruleStatusError": "エラー", "xpack.observability.rules.rulesTable.ruleStatusLicenseError": "ライセンスエラー", "xpack.observability.rules.rulesTable.ruleStatusOk": "OK", "xpack.observability.rules.rulesTable.ruleStatusPending": "保留中", - "xpack.observability.rules.rulesTable.ruleStatusSnoozedIndefinitely": "無期限にスヌーズ", "xpack.observability.rules.rulesTable.ruleStatusUnknown": "不明", "xpack.observability.rules.rulesTable.ruleStatusWarning": "警告", "xpack.observability.rules.rulesTable.singleTitle": "ルール", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 6c597be7e4655..1afb1b21737da 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -21909,13 +21909,10 @@ "xpack.observability.rules.rulesTable.columns.statusTitle": "状态", "xpack.observability.rules.rulesTable.pluralTitle": "规则", "xpack.observability.rules.rulesTable.ruleStatusActive": "活动", - "xpack.observability.rules.rulesTable.ruleStatusDisabled": "已禁用", - "xpack.observability.rules.rulesTable.ruleStatusEnabled": "已启用", "xpack.observability.rules.rulesTable.ruleStatusError": "错误", "xpack.observability.rules.rulesTable.ruleStatusLicenseError": "许可证错误", "xpack.observability.rules.rulesTable.ruleStatusOk": "确定", "xpack.observability.rules.rulesTable.ruleStatusPending": "待处理", - "xpack.observability.rules.rulesTable.ruleStatusSnoozedIndefinitely": "已无限期暂停", "xpack.observability.rules.rulesTable.ruleStatusUnknown": "未知", "xpack.observability.rules.rulesTable.ruleStatusWarning": "警告", "xpack.observability.rules.rulesTable.singleTitle": "规则", diff --git a/x-pack/plugins/triggers_actions_ui/public/index.ts b/x-pack/plugins/triggers_actions_ui/public/index.ts index 1e109b96ae5c9..82923205666f6 100644 --- a/x-pack/plugins/triggers_actions_ui/public/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/index.ts @@ -18,6 +18,7 @@ export type { RuleType, RuleTypeIndex, RuleTypeModel, + RuleStatus, ActionType, ActionTypeRegistryContract, RuleTypeRegistryContract, From 1cdf0a45a655046e6fcb9de1ed54634cc5062875 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 4 May 2022 11:04:40 -0700 Subject: [PATCH 43/68] [ci] hide browserslist outdated warnings (#131549) --- .buildkite/scripts/common/env.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.buildkite/scripts/common/env.sh b/.buildkite/scripts/common/env.sh index 5d2ccda66285b..0efcbb7dbcda3 100755 --- a/.buildkite/scripts/common/env.sh +++ b/.buildkite/scripts/common/env.sh @@ -98,3 +98,6 @@ fi export BUILD_TS_REFS_DISABLE=true export DISABLE_BOOTSTRAP_VALIDATION=true + +# Prevent Browserlist from logging on CI about outdated database versions +export BROWSERSLIST_IGNORE_OLD_DATA=true From fe76adbc3acfb676a4b1021a67b9abd6ef66a770 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Wed, 4 May 2022 14:21:21 -0400 Subject: [PATCH 44/68] [ResponseOps] Fix broken search strategy test (#130393) * Unskip and add debug * try this * lets fail * this? * add another * Add more * Try this Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/test/common/services/bsearch_secure.ts | 3 +-- .../security_and_spaces/tests/basic/search_strategy.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/x-pack/test/common/services/bsearch_secure.ts b/x-pack/test/common/services/bsearch_secure.ts index 458e0878e187f..f60dc6aa4c3cd 100644 --- a/x-pack/test/common/services/bsearch_secure.ts +++ b/x-pack/test/common/services/bsearch_secure.ts @@ -79,12 +79,11 @@ export const BSecureSearchFactory = (retry: RetryService) => ({ .set('kbn-xsrf', 'true') .send(options); } - if (result.status === 500 || result.status === 200) { + if ((result.status === 500 || result.status === 200) && result.body) { return result; } throw new Error('try again'); }); - if (body.isRunning) { const result = await retry.try(async () => { const resp = await supertestWithoutAuth diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts index 27dfd7a9c9a90..1f5ec04cb8ffb 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts @@ -43,7 +43,7 @@ export default ({ getService }: FtrProviderContext) => { const SPACE1 = 'space1'; // Failing: See https://github.com/elastic/kibana/issues/129219 - describe.skip('ruleRegistryAlertsSearchStrategy', () => { + describe('ruleRegistryAlertsSearchStrategy', () => { let kibanaVersion: string; before(async () => { kibanaVersion = await kbnClient.version.get(); From a632484214f0b6ae2fac290d9201b290f71c413c Mon Sep 17 00:00:00 2001 From: Quynh Nguyen <43350163+qn895@users.noreply.github.com> Date: Wed, 4 May 2022 13:21:51 -0500 Subject: [PATCH 45/68] [ML] Add recognized modules links for Index data visualizer (#131342) * [ML] Add dynamic registration of links for both index and file * [ML] Consolidate type imports * [ML] Revert uptime changes * [ML] Fix cards visible when canDisplay is false * [ML] Shorten create job text * [ML] Remove as assertions * [ML] Rename to GetAdditionalLinks Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/components/link_card/link_card.tsx | 12 +- .../common/components/results_links/index.ts | 2 +- .../results_links/results_links.tsx | 68 +++++++---- .../application/common/util/is_defined.ts | 10 ++ .../file_data_visualizer_view.js | 2 +- .../components/import_view/import_view.js | 2 +- .../file_data_visualizer.tsx | 8 +- .../actions_panel/actions_panel.tsx | 86 +++++++------ .../index_data_visualizer_view.tsx | 8 +- .../index_data_visualizer.tsx | 17 +-- .../plugins/data_visualizer/public/index.ts | 6 +- x-pack/plugins/ml/common/constants/locator.ts | 1 + x-pack/plugins/ml/common/types/locator.ts | 1 + .../components/link_card/link_card.tsx | 4 +- .../file_based/file_datavisualizer.tsx | 115 +++++++++--------- .../index_based/index_data_visualizer.tsx | 99 ++++++++++++--- .../plugins/ml/public/locator/ml_locator.ts | 1 + 17 files changed, 277 insertions(+), 165 deletions(-) create mode 100644 x-pack/plugins/data_visualizer/public/application/common/util/is_defined.ts diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx index ae5c4f0ab9ad9..4d5b5a8154e72 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/link_card/link_card.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FC, ReactElement } from 'react'; +import React, { FC } from 'react'; import { EuiIcon, @@ -18,8 +18,8 @@ import { EuiLink, } from '@elastic/eui'; -interface Props { - icon: IconType | ReactElement; +export interface LinkCardProps { + icon: IconType; iconAreaLabel?: string; title: any; description: any; @@ -31,7 +31,7 @@ interface Props { // Component for rendering a card which links to the Create Job page, displaying an // icon, card title, description and link. -export const LinkCard: FC = ({ +export const LinkCard: FC = ({ icon, iconAreaLabel, title, @@ -39,7 +39,7 @@ export const LinkCard: FC = ({ onClick, href, isDisabled, - 'data-test-subj': dateTestSubj, + 'data-test-subj': dataTestSubj, }) => { const linkHrefAndOnClickProps = { ...(href ? { href } : {}), @@ -58,7 +58,7 @@ export const LinkCard: FC = ({ background: 'transparent', outline: 'none', }} - data-test-subj={dateTestSubj} + data-test-subj={dataTestSubj} color="subdued" {...linkHrefAndOnClickProps} > diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts index 24c36f97d7633..4c59725037577 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/index.ts @@ -5,5 +5,5 @@ * 2.0. */ -export type { ResultLink } from './results_links'; +export type { ResultLink, GetAdditionalLinks, GetAdditionalLinksParams } from './results_links'; export { ResultsLinks } from './results_links'; diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx index 57395b506af28..64b0097401ef6 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/results_links/results_links.tsx @@ -12,10 +12,23 @@ import { EuiFlexGroup, EuiFlexItem, EuiCard, EuiIcon } from '@elastic/eui'; import { TimeRange, RefreshInterval } from '@kbn/data-plugin/public'; import { FindFileStructureResponse } from '@kbn/file-upload-plugin/common'; import type { FileUploadPluginStart } from '@kbn/file-upload-plugin/public'; +import { flatten } from 'lodash'; +import { LinkCardProps } from '../link_card/link_card'; import { useDataVisualizerKibana } from '../../../kibana_context'; +import { isDefined } from '../../util/is_defined'; type LinkType = 'file' | 'index'; +export interface GetAdditionalLinksParams { + dataViewId: string; + dataViewTitle?: string; + globalState?: any; +} + +export type GetAdditionalLinks = Array< + (params: GetAdditionalLinksParams) => Promise +>; + export interface ResultLink { id: string; type: LinkType; @@ -24,7 +37,7 @@ export interface ResultLink { description: string; getUrl(params?: any): Promise; canDisplay(params?: any): Promise; - dataTestSubj?: string; + 'data-test-subj'?: string; } interface Props { @@ -34,7 +47,7 @@ interface Props { timeFieldName?: string; createDataView: boolean; showFilebeatFlyout(): void; - additionalLinks: ResultLink[]; + getAdditionalLinks?: GetAdditionalLinks; } interface GlobalState { @@ -51,7 +64,7 @@ export const ResultsLinks: FC = ({ timeFieldName, createDataView, showFilebeatFlyout, - additionalLinks, + getAdditionalLinks, }) => { const { services: { @@ -70,7 +83,7 @@ export const ResultsLinks: FC = ({ const [discoverLink, setDiscoverLink] = useState(''); const [indexManagementLink, setIndexManagementLink] = useState(''); const [dataViewsManagementLink, setDataViewsManagementLink] = useState(''); - const [generatedLinks, setGeneratedLinks] = useState>({}); + const [asyncHrefCards, setAsyncHrefCards] = useState(); useEffect(() => { let unmounted = false; @@ -93,22 +106,30 @@ export const ResultsLinks: FC = ({ getDiscoverUrl(); - Promise.all( - additionalLinks.map(async ({ canDisplay, getUrl }) => { - if ((await canDisplay({ indexPatternId: dataViewId })) === false) { - return null; - } - return getUrl({ globalState, indexPatternId: dataViewId }); - }) - ).then((urls) => { - const linksById = urls.reduce((acc, url, i) => { - if (url !== null) { - acc[additionalLinks[i].id] = url; - } - return acc; - }, {} as Record); - setGeneratedLinks(linksById); - }); + if (Array.isArray(getAdditionalLinks)) { + Promise.all( + getAdditionalLinks.map(async (asyncCardGetter) => { + const results = await asyncCardGetter({ + dataViewId, + }); + if (Array.isArray(results)) { + return await Promise.all( + results.map(async (c) => ({ + ...c, + canDisplay: await c.canDisplay(), + href: await c.getUrl(), + })) + ); + } + }) + ).then((cards) => { + setAsyncHrefCards( + flatten(cards) + .filter(isDefined) + .filter((d) => d.canDisplay === true) + ); + }); + } if (!unmounted) { setIndexManagementLink( @@ -244,16 +265,15 @@ export const ResultsLinks: FC = ({ onClick={showFilebeatFlyout} /> - {additionalLinks - .filter(({ id }) => generatedLinks[id] !== undefined) - .map((link) => ( + {Array.isArray(asyncHrefCards) && + asyncHrefCards.map((link) => ( } data-test-subj="fileDataVisLink" title={link.title} description={link.description} - href={generatedLinks[link.id]} + href={link.href} /> ))} diff --git a/x-pack/plugins/data_visualizer/public/application/common/util/is_defined.ts b/x-pack/plugins/data_visualizer/public/application/common/util/is_defined.ts new file mode 100644 index 0000000000000..ead91eafc2d4e --- /dev/null +++ b/x-pack/plugins/data_visualizer/public/application/common/util/is_defined.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export function isDefined(argument: T | undefined | null): argument is T { + return argument !== undefined && argument !== null; +} diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js index 0d3408a77e7c8..9495c599e73d4 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/file_data_visualizer_view/file_data_visualizer_view.js @@ -369,7 +369,7 @@ export class FileDataVisualizerView extends Component { hideBottomBar={this.hideBottomBar} savedObjectsClient={this.savedObjectsClient} fileUpload={this.props.fileUpload} - resultsLinks={this.props.resultsLinks} + getAdditionalLinks={this.props.getAdditionalLinks} capabilities={this.props.capabilities} /> diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js index c5021f930c942..006bd9e3356f7 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/components/import_view/import_view.js @@ -585,7 +585,7 @@ export class ImportView extends Component { timeFieldName={timeFieldName} createDataView={createDataView} showFilebeatFlyout={this.showFilebeatFlyout} - additionalLinks={this.props.resultsLinks ?? []} + getAdditionalLinks={this.props.getAdditionalLinks ?? []} /> {isFilebeatFlyoutVisible && ( diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx index 60a67ef8e33d5..0238659b1f348 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx @@ -11,14 +11,14 @@ import { getCoreStart, getPluginsStart } from '../../kibana_services'; // @ts-ignore import { FileDataVisualizerView } from './components/file_data_visualizer_view'; -import { ResultLink } from '../common/components/results_links'; +import { GetAdditionalLinks } from '../common/components/results_links'; interface Props { - additionalLinks?: ResultLink[]; + getAdditionalLinks?: GetAdditionalLinks; } export type FileDataVisualizerSpec = typeof FileDataVisualizer; -export const FileDataVisualizer: FC = ({ additionalLinks }) => { +export const FileDataVisualizer: FC = ({ getAdditionalLinks }) => { const coreStart = getCoreStart(); const { data, maps, embeddable, discover, share, security, fileUpload, cloud } = getPluginsStart(); @@ -45,7 +45,7 @@ export const FileDataVisualizer: FC = ({ additionalLinks }) => { savedObjectsClient={coreStart.savedObjects.client} http={coreStart.http} fileUpload={fileUpload} - resultsLinks={additionalLinks} + getAdditionalLinks={getAdditionalLinks} capabilities={coreStart.application.capabilities} /> diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx index c3bb0eef960ba..5d055ed993575 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/actions_panel/actions_panel.tsx @@ -11,28 +11,31 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { EuiSpacer, EuiTitle } from '@elastic/eui'; import { DataView } from '@kbn/data-views-plugin/public'; +import { flatten } from 'lodash'; +import { LinkCardProps } from '../../../common/components/link_card/link_card'; import { useDataVisualizerKibana } from '../../../kibana_context'; import { useUrlState } from '../../../common/util/url_state'; import { LinkCard } from '../../../common/components/link_card'; -import { ResultLink } from '../../../common/components/results_links'; +import { GetAdditionalLinks } from '../../../common/components/results_links'; +import { isDefined } from '../../../common/util/is_defined'; interface Props { dataView: DataView; searchString?: string | { [key: string]: any }; searchQueryLanguage?: string; - additionalLinks: ResultLink[]; + getAdditionalLinks?: GetAdditionalLinks; } export const ActionsPanel: FC = ({ dataView, searchString, searchQueryLanguage, - additionalLinks, + getAdditionalLinks, }) => { const [globalState] = useUrlState('_g'); const [discoverLink, setDiscoverLink] = useState(''); - const [generatedLinks, setGeneratedLinks] = useState>({}); + const [asyncHrefCards, setAsyncHrefCards] = useState(); const { services: { @@ -46,6 +49,7 @@ export const ActionsPanel: FC = ({ let unmounted = false; const indexPatternId = dataView.id; + const indexPatternTitle = dataView.title; const getDiscoverUrl = async (): Promise => { const isDiscoverAvailable = capabilities.discover?.show ?? false; if (!isDiscoverAvailable) return; @@ -68,24 +72,33 @@ export const ActionsPanel: FC = ({ setDiscoverLink(discoverUrl); }; - Promise.all( - additionalLinks.map(async ({ canDisplay, getUrl }) => { - if ((await canDisplay({ indexPatternId })) === false) { - return null; - } - return getUrl({ globalState, indexPatternId }); - }) - ).then((urls) => { - const linksById = urls.reduce((acc, url, i) => { - if (url !== null) { - acc[additionalLinks[i].id] = url; - } - return acc; - }, {} as Record); - setGeneratedLinks(linksById); - }); - + if (Array.isArray(getAdditionalLinks) && indexPatternId !== undefined) { + Promise.all( + getAdditionalLinks.map(async (asyncCardGetter) => { + const results = await asyncCardGetter({ + dataViewId: indexPatternId, + dataViewTitle: indexPatternTitle, + }); + if (Array.isArray(results)) { + return await Promise.all( + results.map(async (c) => ({ + ...c, + canDisplay: await c.canDisplay(), + href: await c.getUrl(), + })) + ); + } + }) + ).then((cards) => { + setAsyncHrefCards( + flatten(cards) + .filter(isDefined) + .filter((d) => d.canDisplay === true) + ); + }); + } getDiscoverUrl(); + return () => { unmounted = true; }; @@ -96,8 +109,8 @@ export const ActionsPanel: FC = ({ globalState, capabilities, discover, - additionalLinks, data.query, + getAdditionalLinks, ]); // Note we use display:none for the DataRecognizer section as it needs to be @@ -105,20 +118,6 @@ export const ActionsPanel: FC = ({ // controls whether the recognizer section is ultimately displayed. return (
- {additionalLinks - .filter(({ id }) => generatedLinks[id] !== undefined) - .map((link) => ( - <> - - - - ))} {discoverLink && ( <> @@ -147,8 +146,23 @@ export const ActionsPanel: FC = ({ } data-test-subj="dataVisualizerViewInDiscoverCard" /> + )} + + {Array.isArray(asyncHrefCards) && + asyncHrefCards.map((link) => ( + <> + + + + ))}
); }; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx index 9ce1fb4f552e5..d892b5f159434 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx @@ -48,7 +48,7 @@ import { DatePickerWrapper } from '../../../common/components/date_picker_wrappe import { HelpMenu } from '../../../common/components/help_menu'; import { createMergedEsQuery } from '../../utils/saved_search_utils'; import { DataVisualizerDataViewManagement } from '../data_view_management'; -import { ResultLink } from '../../../common/components/results_links'; +import { GetAdditionalLinks } from '../../../common/components/results_links'; import { useDataVisualizerGridData } from '../../hooks/use_data_visualizer_grid_data'; import { DataVisualizerGridInput } from '../../embeddables/grid_embeddable/grid_embeddable'; import './_index.scss'; @@ -110,7 +110,7 @@ export interface IndexDataVisualizerViewProps { currentDataView: DataView; currentSavedSearch: SavedSearchSavedObject | null; currentSessionId?: string; - additionalLinks?: ResultLink[]; + getAdditionalLinks?: GetAdditionalLinks; } const restorableDefaults = getDefaultDataVisualizerListState(); @@ -129,7 +129,7 @@ export const IndexDataVisualizerView: FC = (dataVi dataVisualizerProps.currentSavedSearch ); - const { currentDataView, additionalLinks, currentSessionId } = dataVisualizerProps; + const { currentDataView, currentSessionId, getAdditionalLinks } = dataVisualizerProps; useEffect(() => { if (dataVisualizerProps?.currentSavedSearch !== undefined) { @@ -487,7 +487,7 @@ export const IndexDataVisualizerView: FC = (dataVi dataView={currentDataView} searchQueryLanguage={searchQueryLanguage} searchString={searchString} - additionalLinks={additionalLinks ?? []} + getAdditionalLinks={getAdditionalLinks} /> diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx index 0a11f51fa3a26..719986b7ae2ea 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx @@ -29,17 +29,16 @@ import { isRisonSerializationRequired, } from '../common/util/url_state'; import { useDataVisualizerKibana } from '../kibana_context'; -import { ResultLink } from '../common/components/results_links'; +import { GetAdditionalLinks } from '../common/components/results_links'; import { DATA_VISUALIZER_APP_LOCATOR, IndexDataVisualizerLocatorParams } from './locator'; import { DATA_VISUALIZER_INDEX_VIEWER } from './constants/index_data_visualizer_viewer'; import { INDEX_DATA_VISUALIZER_NAME } from '../common/constants'; -export type IndexDataVisualizerSpec = typeof IndexDataVisualizer; - export interface DataVisualizerUrlStateContextProviderProps { IndexDataVisualizerComponent: FC; - additionalLinks: ResultLink[]; + getAdditionalLinks?: GetAdditionalLinks; } +export type IndexDataVisualizerSpec = typeof IndexDataVisualizer; export const getLocatorParams = (params: { dataViewId?: string; @@ -73,7 +72,7 @@ export const getLocatorParams = (params: { export const DataVisualizerUrlStateContextProvider: FC< DataVisualizerUrlStateContextProviderProps -> = ({ IndexDataVisualizerComponent, additionalLinks }) => { +> = ({ IndexDataVisualizerComponent, getAdditionalLinks }) => { const { services } = useDataVisualizerKibana(); const { data: { dataViews, search }, @@ -247,8 +246,8 @@ export const DataVisualizerUrlStateContextProvider: FC< ) : (
@@ -257,7 +256,9 @@ export const DataVisualizerUrlStateContextProvider: FC< ); }; -export const IndexDataVisualizer: FC<{ additionalLinks: ResultLink[] }> = ({ additionalLinks }) => { +export const IndexDataVisualizer: FC<{ + getAdditionalLinks?: GetAdditionalLinks; +}> = ({ getAdditionalLinks }) => { const coreStart = getCoreStart(); const { data, @@ -294,7 +295,7 @@ export const IndexDataVisualizer: FC<{ additionalLinks: ResultLink[] }> = ({ add diff --git a/x-pack/plugins/data_visualizer/public/index.ts b/x-pack/plugins/data_visualizer/public/index.ts index 4a579f4e3abcc..7c4208106cb75 100644 --- a/x-pack/plugins/data_visualizer/public/index.ts +++ b/x-pack/plugins/data_visualizer/public/index.ts @@ -18,4 +18,8 @@ export type { IndexDataVisualizerSpec, IndexDataVisualizerViewProps, } from './application'; -export type { ResultLink } from './application/common/components/results_links'; +export type { + GetAdditionalLinksParams, + ResultLink, + GetAdditionalLinks, +} from './application/common/components/results_links'; diff --git a/x-pack/plugins/ml/common/constants/locator.ts b/x-pack/plugins/ml/common/constants/locator.ts index ae45bec27deb6..0a1c2638e684a 100644 --- a/x-pack/plugins/ml/common/constants/locator.ts +++ b/x-pack/plugins/ml/common/constants/locator.ts @@ -38,6 +38,7 @@ export const ML_PAGES = { */ DATA_VISUALIZER_INDEX_VIEWER: 'jobs/new_job/datavisualizer', ANOMALY_DETECTION_CREATE_JOB: `jobs/new_job`, + ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER: `jobs/new_job/recognize`, ANOMALY_DETECTION_CREATE_JOB_ADVANCED: `jobs/new_job/advanced`, ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE: `jobs/new_job/step/job_type`, ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX: `jobs/new_job/step/index_or_search`, diff --git a/x-pack/plugins/ml/common/types/locator.ts b/x-pack/plugins/ml/common/types/locator.ts index 933862085b3c6..33ec94b825303 100644 --- a/x-pack/plugins/ml/common/types/locator.ts +++ b/x-pack/plugins/ml/common/types/locator.ts @@ -46,6 +46,7 @@ export interface MlGenericUrlPageState extends MlIndexBasedSearchState { export type MlGenericUrlState = MLPageState< | typeof ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB + | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE | typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX diff --git a/x-pack/plugins/ml/public/application/components/link_card/link_card.tsx b/x-pack/plugins/ml/public/application/components/link_card/link_card.tsx index ae5c4f0ab9ad9..3b3d6a2fdeb5c 100644 --- a/x-pack/plugins/ml/public/application/components/link_card/link_card.tsx +++ b/x-pack/plugins/ml/public/application/components/link_card/link_card.tsx @@ -39,7 +39,7 @@ export const LinkCard: FC = ({ onClick, href, isDisabled, - 'data-test-subj': dateTestSubj, + 'data-test-subj': dataTestSubj, }) => { const linkHrefAndOnClickProps = { ...(href ? { href } : {}), @@ -58,7 +58,7 @@ export const LinkCard: FC = ({ background: 'transparent', outline: 'none', }} - data-test-subj={dateTestSubj} + data-test-subj={dataTestSubj} color="subdued" {...linkHrefAndOnClickProps} > diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx index 4c1d8b478f971..9fcf0df33a0af 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/file_datavisualizer.tsx @@ -8,7 +8,11 @@ import React, { FC, Fragment, useState, useEffect, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { ResultLink, FileDataVisualizerSpec } from '@kbn/data-visualizer-plugin/public'; +import type { + FileDataVisualizerSpec, + GetAdditionalLinksParams, + GetAdditionalLinks, +} from '@kbn/data-visualizer-plugin/public'; import { useTimefilter } from '../../contexts/kibana'; import { HelpMenu } from '../../components/help_menu'; import { useMlKibana, useMlLocator } from '../../contexts/kibana'; @@ -19,11 +23,6 @@ import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_ import { checkPermission } from '../../capabilities/check_capabilities'; import { MlPageHeader } from '../../components/page_header'; -interface GetUrlParams { - indexPatternId: string; - globalState: any; -} - export const FileDataVisualizerPage: FC = () => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const { @@ -40,60 +39,62 @@ export const FileDataVisualizerPage: FC = () => { const [FileDataVisualizer, setFileDataVisualizer] = useState(null); - const links: ResultLink[] = useMemo( + const getAdditionalLinks: GetAdditionalLinks = useMemo( () => [ - { - id: 'create_ml_job', - title: i18n.translate('xpack.ml.fileDatavisualizer.actionsPanel.anomalyDetectionTitle', { - defaultMessage: 'Create new ML job', - }), - description: '', - icon: 'machineLearningApp', - type: 'file', - getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { - return await mlLocator.getUrl({ - page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, - pageState: { - index: indexPatternId, - globalState, - }, - }); - }, - canDisplay: async ({ indexPatternId }) => { - try { - const { timeFieldName } = await getDataView(indexPatternId); - return ( - isFullLicense() && - timeFieldName !== undefined && - checkPermission('canCreateJob') && - mlNodesAvailable() - ); - } catch (error) { - return false; - } + async ({ dataViewId, globalState }: GetAdditionalLinksParams) => [ + { + id: 'create_ml_job', + title: i18n.translate('xpack.ml.fileDatavisualizer.actionsPanel.anomalyDetectionTitle', { + defaultMessage: 'Create ML job', + }), + description: '', + icon: 'machineLearningApp', + type: 'file', + getUrl: async () => { + return await mlLocator.getUrl({ + page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE, + pageState: { + index: dataViewId, + globalState, + }, + }); + }, + canDisplay: async () => { + try { + const { timeFieldName } = await getDataView(dataViewId); + return ( + isFullLicense() && + timeFieldName !== undefined && + checkPermission('canCreateJob') && + mlNodesAvailable() + ); + } catch (error) { + return false; + } + }, }, - }, - { - id: 'open_in_data_viz', - title: i18n.translate('xpack.ml.fileDatavisualizer.actionsPanel.dataframeTitle', { - defaultMessage: 'Open in Data Visualizer', - }), - description: '', - icon: 'dataVisualizer', - type: 'file', - getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { - return await mlLocator.getUrl({ - page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, - pageState: { - index: indexPatternId, - globalState, - }, - }); + { + id: 'open_in_data_viz', + title: i18n.translate('xpack.ml.fileDatavisualizer.actionsPanel.dataframeTitle', { + defaultMessage: 'Open in Data Visualizer', + }), + description: '', + icon: 'dataVisualizer', + type: 'file', + getUrl: async () => { + return await mlLocator.getUrl({ + page: ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER, + pageState: { + index: dataViewId, + globalState, + }, + }); + }, + canDisplay: async () => dataViewId !== '', }, - canDisplay: async ({ indexPatternId }) => indexPatternId !== '', - }, + ], ], - [] + [mlLocator] ); useEffect(() => { @@ -114,7 +115,7 @@ export const FileDataVisualizerPage: FC = () => { defaultMessage="Data Visualizer" /> - + ) : null} diff --git a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx index 5a041df220df9..ae5c7c9948f18 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/index_based/index_data_visualizer.tsx @@ -5,28 +5,38 @@ * 2.0. */ -import React, { FC, Fragment, useEffect, useState, useMemo } from 'react'; +import React, { FC, Fragment, useEffect, useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { ResultLink, IndexDataVisualizerSpec } from '@kbn/data-visualizer-plugin/public'; +import type { + IndexDataVisualizerSpec, + ResultLink, + GetAdditionalLinks, + GetAdditionalLinksParams, +} from '@kbn/data-visualizer-plugin/public'; import { useMlKibana, useTimefilter, useMlLocator } from '../../contexts/kibana'; import { HelpMenu } from '../../components/help_menu'; import { ML_PAGES } from '../../../../common/constants/locator'; import { isFullLicense } from '../../license'; import { mlNodesAvailable, getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes'; import { checkPermission } from '../../capabilities/check_capabilities'; - import { MlPageHeader } from '../../components/page_header'; -interface GetUrlParams { - indexPatternId: string; - globalState: any; +interface RecognizerModule { + id: string; + title: string; + query: Record; + description: string; + logo: { + icon: string; + }; } export const IndexDataVisualizerPage: FC = () => { useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false }); const { services: { + http, docLinks, dataVisualizer, data: { @@ -48,8 +58,12 @@ export const IndexDataVisualizerPage: FC = () => { } }, []); - const links: ResultLink[] = useMemo( - () => [ + const getAsyncMLCards = async ({ + dataViewId, + dataViewTitle, + globalState, + }: GetAdditionalLinksParams): Promise => { + return [ { id: 'create_ml_ad_job', title: i18n.translate('xpack.ml.indexDatavisualizer.actionsPanel.anomalyDetectionTitle', { @@ -64,18 +78,18 @@ export const IndexDataVisualizerPage: FC = () => { ), icon: 'createAdvancedJob', type: 'file', - getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { + getUrl: async () => { return await mlLocator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED, pageState: { - index: indexPatternId, + index: dataViewId, globalState, }, }); }, - canDisplay: async ({ indexPatternId }) => { + canDisplay: async () => { try { - const { timeFieldName } = await getDataView(indexPatternId); + const { timeFieldName } = await getDataView(dataViewId); return ( isFullLicense() && timeFieldName !== undefined && @@ -86,7 +100,7 @@ export const IndexDataVisualizerPage: FC = () => { return false; } }, - dataTestSubj: 'dataVisualizerCreateAdvancedJobCard', + 'data-test-subj': 'dataVisualizerCreateAdvancedJobCard', }, { id: 'create_ml_dfa_job', @@ -101,11 +115,11 @@ export const IndexDataVisualizerPage: FC = () => { ), icon: 'classificationJob', type: 'file', - getUrl: async ({ indexPatternId, globalState }: GetUrlParams) => { + getUrl: async () => { return await mlLocator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB, pageState: { - index: indexPatternId, + index: dataViewId, globalState, }, }); @@ -115,12 +129,57 @@ export const IndexDataVisualizerPage: FC = () => { isFullLicense() && checkPermission('canCreateDataFrameAnalytics') && mlNodesAvailable() ); }, - dataTestSubj: 'dataVisualizerCreateDataFrameAnalyticsCard', + 'data-test-subj': 'dataVisualizerCreateDataFrameAnalyticsCard', }, - ], - [] - ); + ]; + }; + const getAsyncRecognizedModuleCards = async (params: GetAdditionalLinksParams) => { + const { dataViewId, dataViewTitle } = params; + const modules = await http.fetch( + `/api/ml/modules/recognize/${dataViewTitle}`, + { + method: 'GET', + } + ); + return modules?.map( + (m): ResultLink => ({ + id: m.id, + title: m.title, + description: m.description, + icon: m.logo.icon, + type: 'index', + getUrl: async () => { + return await mlLocator.getUrl({ + page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER, + pageState: { + id: m.id, + index: dataViewId, + }, + }); + }, + canDisplay: async () => { + try { + const { timeFieldName } = await getDataView(dataViewId); + return ( + isFullLicense() && + timeFieldName !== undefined && + checkPermission('canCreateJob') && + mlNodesAvailable() + ); + } catch (error) { + return false; + } + }, + 'data-test-subj': m.id, + }) + ); + }; + + const getAdditionalLinks: GetAdditionalLinks = useMemo( + () => [getAsyncRecognizedModuleCards, getAsyncMLCards], + [mlLocator] + ); return IndexDataVisualizer ? ( {IndexDataVisualizer !== null ? ( @@ -131,7 +190,7 @@ export const IndexDataVisualizerPage: FC = () => { defaultMessage="Data Visualizer" /> - + ) : null} diff --git a/x-pack/plugins/ml/public/locator/ml_locator.ts b/x-pack/plugins/ml/public/locator/ml_locator.ts index dcc31591208cb..b1ea2549c3347 100644 --- a/x-pack/plugins/ml/public/locator/ml_locator.ts +++ b/x-pack/plugins/ml/public/locator/ml_locator.ts @@ -77,6 +77,7 @@ export class MlLocatorDefinition implements LocatorDefinition { path = formatTrainedModelsNodesManagementUrl('', params.pageState); break; case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB: + case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER: case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED: case ML_PAGES.DATA_VISUALIZER: case ML_PAGES.DATA_VISUALIZER_FILE: From c43a51d7ab9d86192d7808ada877ee5dd51d8810 Mon Sep 17 00:00:00 2001 From: Kristof C Date: Wed, 4 May 2022 13:56:00 -0500 Subject: [PATCH 46/68] [Security Solution][Detection & Response] 131028 implement recently opened cases table (#131029) * First draft at possible implementation. tests need to be added, and imports,comments, logs cleaned up * Further tweaks to alerts counters * Add tests for alerts_counters hook * Working on vulnerable hosts * Add useVulnerableHostsCounters hook along with tests * add Vulnerable users and tests * Move files to components folder and wire up to detections overview page * Add translations * add querytoggle and navigation to both tables * fix bug for toggleQuery * update button navigation * remove alerts by status, as Angela built instead * Working on changing test files * test files for host and user hooks complete * Components complete * bug fixes from PR * failing tests * Undo bad edit to useRuleAlerts test * Fix show inspect on hover, and use HostDetailsLink component * missed in last commit * more fixes from PR review * recent cases table working, need tests * first pass for table and data fetching * Make changes from PR review * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * PR fixes * PR fixes * remove cases api date workaround * enable detectionsResponse for deployed instance * Fix tests * turn off detectionresponseEnabled flag * fixes from design review * stability fix. remove useUserInfo * Add comment for removing togglequery code Co-authored-by: Kristof-Pierre Cummings Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/formatted_date/index.test.tsx | 12 ++ .../components/formatted_date/index.tsx | 6 +- .../alerts_by_status/alerts_by_status.tsx | 12 +- .../cases_by_status/cases_by_status.tsx | 17 +- .../cases_table/cases_table.test.tsx | 104 ++++++++++++ .../cases_table/cases_table.tsx | 145 ++++++++++++++++ .../{ => cases_table}/index.ts | 3 +- .../cases_table/mock_data.ts | 160 ++++++++++++++++++ .../cases_table/status_badge.tsx | 42 +++++ .../cases_table/use_case_items.test.ts | 133 +++++++++++++++ .../cases_table/use_case_items.ts | 110 ++++++++++++ .../host_alerts_table/host_alerts_table.tsx | 12 +- .../use_host_alerts_items.ts | 2 +- .../detection_response/translations.ts | 67 +++++++- .../use_user_alerts_items.ts | 2 +- .../user_alerts_table/user_alerts_table.tsx | 10 +- .../pages/detection_response.test.tsx | 78 ++++++--- .../overview/pages/detection_response.tsx | 22 ++- 18 files changed, 881 insertions(+), 56 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.test.tsx create mode 100644 x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx rename x-pack/plugins/security_solution/public/overview/components/detection_response/{ => cases_table}/index.ts (69%) create mode 100644 x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/mock_data.ts create mode 100644 x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/status_badge.tsx create mode 100644 x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts create mode 100644 x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.ts diff --git a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.test.tsx index d25294879a572..a981fb2d2b3f2 100644 --- a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.test.tsx @@ -43,6 +43,18 @@ describe('formatted_date', () => { expect(wrapper.text()).toEqual('Feb 25, 2019 @ 22:27:05.000'); }); + test.each([ + ['MMMM D, YYYY', 'February 25, 2019'], + ['MM/D/YY', '02/25/19'], + ['d-m-y', '1-27-2019'], + ])('it renders the date in the correct format: %s', (momentDateFormat, expectedResult) => { + const wrapper = mount( + + ); + + expect(wrapper.text()).toEqual(expectedResult); + }); + test('it renders a UTC ISO8601 date string supplied when no date format configuration exists', () => { mockUseDateFormat.mockImplementation(() => ''); const wrapper = mount(); diff --git a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx index a31448d181ea7..a837f0cbfa3ec 100644 --- a/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/formatted_date/index.tsx @@ -97,16 +97,18 @@ interface FormattedDateProps { className?: string; fieldName: string; value?: string | number | null; + dateFormat?: string; } export const FormattedDate = React.memo( - ({ value, fieldName, className = '' }): JSX.Element => { + ({ value, fieldName, className = '', dateFormat }): JSX.Element => { if (value == null) { return getOrEmptyTagFromValue(value); } + const maybeDate = getMaybeDate(value); return maybeDate.isValid() ? ( - + ) : ( getOrEmptyTagFromValue(value) diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx index 2e1b96447f3df..f7f3cc9a81f7f 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx @@ -49,6 +49,11 @@ const StyledLegendFlexItem = styled(EuiFlexItem)` padding-top: 45px; `; +// To Do remove this styled component once togglequery is updated: #131405 +const StyledEuiPanel = styled(EuiPanel)` + height: fit-content; +`; + interface AlertsByStatusProps { signalIndexName: string | null; } @@ -119,7 +124,10 @@ export const AlertsByStatus = ({ signalIndexName }: AlertsByStatusProps) => { return ( <> - + {loading && ( { )} - + ); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx index 13a2459b44d68..67ed0d43c830c 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_by_status/cases_by_status.tsx @@ -6,7 +6,7 @@ */ import React, { useCallback, useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiPanel, EuiText } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui'; import { AxisStyle, Rotation, ScaleType } from '@elastic/charts'; import styled from 'styled-components'; import { FormattedNumber } from '@kbn/i18n-react'; @@ -112,6 +112,10 @@ const Wrapper = styled.div` width: 100%; `; +const StyledEuiPanel = styled(EuiPanel)` + height: 258px; +`; + const CasesByStatusComponent: React.FC = () => { const { toggleStatus, setToggleStatus } = useQueryToggle(CASES_BY_STATUS_ID); const { getAppUrl, navigateTo } = useNavigation(); @@ -151,7 +155,7 @@ const CasesByStatusComponent: React.FC = () => { ); return ( - + { <> - - <> - - {CASES(totalCounts)} - + {' '} + {CASES(totalCounts)} )} @@ -193,7 +194,7 @@ const CasesByStatusComponent: React.FC = () => { )} - + ); }; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.test.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.test.tsx new file mode 100644 index 0000000000000..4250c20059094 --- /dev/null +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.test.tsx @@ -0,0 +1,104 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { render } from '@testing-library/react'; + +import { TestProviders } from '../../../../common/mock'; +import { parsedCasesItems } from './mock_data'; +import { CasesTable } from './cases_table'; +import type { UseCaseItems } from './use_case_items'; + +const mockGetAppUrl = jest.fn(); +jest.mock('../../../../common/lib/kibana/hooks', () => { + const original = jest.requireActual('../../../../common/lib/kibana/hooks'); + return { + ...original, + useNavigation: () => ({ + getAppUrl: mockGetAppUrl, + }), + }; +}); + +type UseCaseItemsReturn = ReturnType; +const defaultCaseItemsReturn: UseCaseItemsReturn = { + items: [], + isLoading: false, + updatedAt: Date.now(), +}; +const mockUseCaseItems = jest.fn(() => defaultCaseItemsReturn); +const mockUseCaseItemsReturn = (overrides: Partial) => { + mockUseCaseItems.mockReturnValueOnce({ + ...defaultCaseItemsReturn, + ...overrides, + }); +}; + +jest.mock('./use_case_items', () => ({ + useCaseItems: () => mockUseCaseItems(), +})); + +const renderComponent = () => + render( + + + + ); + +describe('CasesTable', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render empty table', () => { + const { getByText, getByTestId } = renderComponent(); + + expect(getByTestId('recentlyCreatedCasesPanel')).toBeInTheDocument(); + expect(getByText('No cases to display')).toBeInTheDocument(); + expect(getByTestId('allCasesButton')).toBeInTheDocument(); + }); + + it('should render a loading table', () => { + mockUseCaseItemsReturn({ isLoading: true }); + const { getByText, getByTestId } = renderComponent(); + + expect(getByText('Updating...')).toBeInTheDocument(); + expect(getByTestId('allCasesButton')).toBeInTheDocument(); + expect(getByTestId('recentlyCreatedCasesTable')).toHaveClass('euiBasicTable-loading'); + }); + + it('should render the updated at subtitle', () => { + mockUseCaseItemsReturn({ isLoading: false }); + const { getByText } = renderComponent(); + + expect(getByText('Updated now')).toBeInTheDocument(); + }); + + it('should render the table columns', () => { + mockUseCaseItemsReturn({ items: parsedCasesItems }); + const { getAllByRole } = renderComponent(); + + const columnHeaders = getAllByRole('columnheader'); + expect(columnHeaders.at(0)).toHaveTextContent('Name'); + expect(columnHeaders.at(1)).toHaveTextContent('Note'); + expect(columnHeaders.at(2)).toHaveTextContent('Time'); + expect(columnHeaders.at(3)).toHaveTextContent('Created by'); + expect(columnHeaders.at(4)).toHaveTextContent('Status'); + }); + + it('should render the table items', () => { + mockUseCaseItemsReturn({ items: [parsedCasesItems[0]] }); + const { getByTestId } = renderComponent(); + + expect(getByTestId('recentlyCreatedCaseName')).toHaveTextContent('sdcsd'); + expect(getByTestId('recentlyCreatedCaseNote')).toHaveTextContent('klklk'); + expect(getByTestId('recentlyCreatedCaseTime')).toHaveTextContent('April 25, 2022'); + expect(getByTestId('recentlyCreatedCaseCreatedBy')).toHaveTextContent('elastic'); + expect(getByTestId('recentlyCreatedCaseStatus')).toHaveTextContent('Open'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx new file mode 100644 index 0000000000000..80d2495f57ab5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/cases_table.tsx @@ -0,0 +1,145 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; + +import { + EuiBasicTable, + EuiBasicTableColumn, + EuiButton, + EuiEmptyPrompt, + EuiPanel, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { CaseStatuses } from '@kbn/cases-plugin/common'; + +import { SecurityPageName } from '../../../../app/types'; +import { FormattedDate } from '../../../../common/components/formatted_date'; +import { HeaderSection } from '../../../../common/components/header_section'; +import { HoverVisibilityContainer } from '../../../../common/components/hover_visibility_container'; +import { BUTTON_CLASS as INPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; +import { CaseDetailsLink } from '../../../../common/components/links'; +import { useQueryToggle } from '../../../../common/containers/query_toggle'; +import { useNavigation, NavigateTo, GetAppUrl } from '../../../../common/lib/kibana'; +import * as i18n from '../translations'; +import { LastUpdatedAt } from '../util'; +import { StatusBadge } from './status_badge'; +import { CaseItem, useCaseItems } from './use_case_items'; + +type GetTableColumns = (params: { + getAppUrl: GetAppUrl; + navigateTo: NavigateTo; +}) => Array>; + +const DETECTION_RESPONSE_RECENT_CASES_QUERY_ID = 'recentlyCreatedCasesQuery'; + +export const CasesTable = React.memo(() => { + const { getAppUrl, navigateTo } = useNavigation(); + const { toggleStatus, setToggleStatus } = useQueryToggle( + DETECTION_RESPONSE_RECENT_CASES_QUERY_ID + ); + const { items, isLoading, updatedAt } = useCaseItems({ + skip: !toggleStatus, + }); + + const navigateToCases = useCallback(() => { + navigateTo({ deepLinkId: SecurityPageName.case }); + }, [navigateTo]); + + const columns = useMemo( + () => getTableColumns({ getAppUrl, navigateTo }), + [getAppUrl, navigateTo] + ); + + return ( + + + } + showInspectButton={false} + /> + + {toggleStatus && ( + <> + {i18n.NO_CASES_FOUND}} titleSize="xs" /> + } + /> + + + {i18n.VIEW_RECENT_CASES} + + + )} + + + ); +}); + +CasesTable.displayName = 'CasesTable'; + +const getTableColumns: GetTableColumns = () => [ + { + field: 'id', + name: i18n.CASES_TABLE_COLUMN_NAME, + truncateText: true, + textOnly: true, + 'data-test-subj': 'recentlyCreatedCaseName', + + render: (id: string, { name }) => {name}, + }, + { + field: 'note', + name: i18n.CASES_TABLE_COLUMN_NOTE, + truncateText: true, + textOnly: true, + render: (note: string) => ( + + {note} + + ), + }, + { + field: 'createdAt', + name: i18n.CASES_TABLE_COLUMN_TIME, + render: (createdAt: string) => ( + + ), + 'data-test-subj': 'recentlyCreatedCaseTime', + }, + { + field: 'createdBy', + name: i18n.CASES_TABLE_COLUMN_CREATED_BY, + render: (createdBy: string) => ( + + {createdBy} + + ), + }, + { + field: 'status', + name: i18n.CASES_TABLE_COLUMN_STATUS, + render: (status: CaseStatuses) => , + 'data-test-subj': 'recentlyCreatedCaseStatus', + }, +]; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/index.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/index.ts similarity index 69% rename from x-pack/plugins/security_solution/public/overview/components/detection_response/index.ts rename to x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/index.ts index 8ab93de825305..4151054408345 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/index.ts +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -export { HostAlertsTable } from './host_alerts_table'; -export { UserAlertsTable } from './user_alerts_table'; +export { CasesTable } from './cases_table'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/mock_data.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/mock_data.ts new file mode 100644 index 0000000000000..2547cfa264757 --- /dev/null +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/mock_data.ts @@ -0,0 +1,160 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CaseStatuses } from '@kbn/cases-plugin/common'; + +export const mockCasesResult = { + cases: [ + { + id: '0ce2a510-c43a-11ec-98b5-3109bd2a1901', + version: 'Wzg2MDIsMV0=', + comments: [], + totalComment: 0, + totalAlerts: 0, + title: 'sdcsd', + tags: [], + description: 'klklk', + settings: { + syncAlerts: true, + }, + owner: 'securitySolution', + closed_at: '2022-04-25T01:50:40.435Z', + closed_by: { + full_name: null, + email: null, + username: 'elastic', + }, + createdAt: '2022-04-25T01:50:14.499Z', + createdBy: { + username: 'elastic', + email: null, + full_name: null, + }, + status: 'open', + updated_at: '2022-04-25T01:50:40.435Z', + updated_by: { + full_name: null, + email: null, + username: 'elastic', + }, + connector: { + id: 'none', + name: 'none', + type: '.none', + fields: null, + }, + external_service: null, + }, + { + id: 'dc12f930-c178-11ec-98b5-3109bd2a1901', + version: 'Wzg5NjksMV0=', + comments: [], + totalComment: 0, + totalAlerts: 0, + title: 'zzzz', + tags: [], + description: 'sssss', + settings: { + syncAlerts: true, + }, + owner: 'securitySolution', + closed_at: '2022-04-25T13:45:18.317Z', + closed_by: { + full_name: null, + email: null, + username: 'elastic', + }, + createdAt: '2022-04-21T13:42:17.414Z', + createdBy: { + username: 'elastic', + email: null, + full_name: null, + }, + status: 'in-progress', + updated_at: '2022-04-25T13:45:18.317Z', + updated_by: { + full_name: null, + email: null, + username: 'elastic', + }, + connector: { + id: 'none', + name: 'none', + type: '.none', + fields: null, + }, + external_service: null, + }, + { + id: 'd11cbac0-c178-11ec-98b5-3109bd2a1901', + version: 'Wzg5ODQsMV0=', + comments: [], + totalComment: 0, + totalAlerts: 0, + title: 'asxa', + tags: [], + description: 'dsdd', + settings: { + syncAlerts: true, + }, + owner: 'securitySolution', + closed_at: '2022-04-25T13:45:22.539Z', + closed_by: { + full_name: null, + email: null, + username: 'elastic', + }, + createdAt: '2022-04-21T13:41:59.025Z', + createdBy: { + username: 'elastic', + email: null, + full_name: null, + }, + status: 'closed', + updated_at: '2022-04-25T13:45:22.539Z', + updated_by: { + full_name: null, + email: null, + username: 'elastic', + }, + connector: { + id: 'none', + name: 'none', + type: '.none', + fields: null, + }, + external_service: null, + }, + ], +}; + +export const parsedCasesItems = [ + { + name: 'sdcsd', + note: 'klklk', + createdBy: 'elastic', + status: CaseStatuses.open, + createdAt: '2022-04-25T01:50:14.499Z', + id: '0ce2a510-c43a-11ec-98b5-3109bd2a1901', + }, + { + name: 'zzzz', + note: 'sssss', + status: CaseStatuses['in-progress'], + createdAt: '2022-04-21T13:42:17.414Z', + createdBy: 'elastic', + id: 'dc12f930-c178-11ec-98b5-3109bd2a1901', + }, + { + name: 'asxa', + note: 'dsdd', + createdBy: 'elastic', + status: CaseStatuses.closed, + createdAt: '2022-04-21T13:41:59.025Z', + id: 'd11cbac0-c178-11ec-98b5-3109bd2a1901', + }, +]; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/status_badge.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/status_badge.tsx new file mode 100644 index 0000000000000..9ae1281d9e6e7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/status_badge.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { CaseStatuses } from '@kbn/cases-plugin/common'; +import { EuiBadge } from '@elastic/eui'; + +import * as i18n from '../translations'; + +interface Props { + status: CaseStatuses; +} + +const statuses = { + [CaseStatuses.open]: { + color: 'primary', + label: i18n.STATUS_OPEN, + }, + [CaseStatuses['in-progress']]: { + color: 'warning', + label: i18n.STATUS_IN_PROGRESS, + }, + [CaseStatuses.closed]: { + color: 'default', + label: i18n.STATUS_CLOSED, + }, +} as const; + +export const StatusBadge: React.FC = ({ status }) => { + return ( + + {statuses[status].label} + + ); +}; + +StatusBadge.displayName = 'StatusBadge'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts new file mode 100644 index 0000000000000..d112aaac7d5ad --- /dev/null +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.test.ts @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { act, renderHook } from '@testing-library/react-hooks'; + +import { mockCasesResult, parsedCasesItems } from './mock_data'; +import { useCaseItems, UseCaseItemsProps } from './use_case_items'; + +import type { UseCaseItems } from './use_case_items'; + +const dateNow = new Date('2022-04-08T12:00:00.000Z').valueOf(); +const mockDateNow = jest.fn().mockReturnValue(dateNow); +Date.now = jest.fn(() => mockDateNow()) as unknown as DateConstructor['now']; + +const defaultCasesReturn = { + cases: [], +}; + +const mockCasesApi = jest.fn().mockResolvedValue(defaultCasesReturn); +const mockKibana = { + services: { + cases: { + api: { + cases: { + find: (...props: unknown[]) => mockCasesApi(...props), + }, + }, + }, + }, +}; +jest.mock('../../../../common/lib/kibana', () => ({ + useKibana: () => mockKibana, +})); + +const from = '2020-07-07T08:20:18.966Z'; +const to = '2020-07-08T08:20:18.966Z'; + +const mockUseGlobalTime = jest.fn().mockReturnValue({ from, to }); +jest.mock('../../../../common/containers/use_global_time', () => { + return { + useGlobalTime: (...props: unknown[]) => mockUseGlobalTime(...props), + }; +}); + +const renderUseCaseItems = (overrides: Partial = {}) => + renderHook>(() => + useCaseItems({ skip: false, ...overrides }) + ); + +describe('useCaseItems', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockDateNow.mockReturnValue(dateNow); + mockCasesApi.mockResolvedValue(defaultCasesReturn); + }); + + it('should return default values', async () => { + await act(async () => { + const { result, waitForNextUpdate } = renderUseCaseItems(); + + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + items: [], + isLoading: false, + updatedAt: dateNow, + }); + }); + + expect(mockCasesApi).toBeCalledWith({ + from: '2020-07-07T08:20:18.966Z', + to: '2020-07-08T08:20:18.966Z', + owner: 'securitySolution', + sortField: 'create_at', + sortOrder: 'desc', + page: 1, + perPage: 4, + }); + }); + + it('should return parsed items', async () => { + mockCasesApi.mockReturnValue(mockCasesResult); + + await act(async () => { + const { result, waitForNextUpdate } = renderUseCaseItems(); + + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(result.current).toEqual({ + items: parsedCasesItems, + isLoading: false, + updatedAt: dateNow, + }); + }); + }); + + it('should return new updatedAt', async () => { + const newDateNow = new Date('2022-04-08T14:00:00.000Z').valueOf(); + mockDateNow.mockReturnValue(newDateNow); + mockDateNow.mockReturnValueOnce(dateNow); + mockCasesApi.mockReturnValue(mockCasesResult); + + await act(async () => { + const { result, waitForNextUpdate } = renderUseCaseItems(); + + await waitForNextUpdate(); + await waitForNextUpdate(); + + expect(mockDateNow).toHaveBeenCalled(); + expect(result.current).toEqual({ + items: parsedCasesItems, + isLoading: false, + updatedAt: newDateNow, + }); + }); + }); + + it('should skip the query', () => { + const { result } = renderUseCaseItems({ skip: true }); + + expect(result.current).toEqual({ + items: [], + isLoading: false, + updatedAt: dateNow, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.ts new file mode 100644 index 0000000000000..1b19327989729 --- /dev/null +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/cases_table/use_case_items.ts @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useState, useEffect } from 'react'; + +import { CaseStatuses } from '@kbn/cases-plugin/common'; +import { Cases } from '@kbn/cases-plugin/common/ui'; + +import { APP_ID } from '../../../../../common/constants'; +import { useGlobalTime } from '../../../../common/containers/use_global_time'; +import { useKibana } from '../../../../common/lib/kibana'; +import { addError } from '../../../../common/store/app/actions'; + +import * as i18n from '../translations'; + +export interface CaseItem { + name: string; + note: string; + createdAt: string; + createdBy: string; + status: CaseStatuses; + id: string; +} + +export interface UseCaseItemsProps { + skip: boolean; +} + +export type UseCaseItems = (props: UseCaseItemsProps) => { + items: CaseItem[]; + isLoading: boolean; + updatedAt: number; +}; + +export const useCaseItems: UseCaseItems = ({ skip }) => { + const { + services: { cases }, + } = useKibana(); + const { to, from } = useGlobalTime(); + const [isLoading, setIsLoading] = useState(true); + const [updatedAt, setUpdatedAt] = useState(Date.now()); + const [items, setItems] = useState([]); + + useEffect(() => { + let isSubscribed = true; + const abortCtrl = new AbortController(); + + const fetchCases = async () => { + try { + const casesResponse = await cases.api.cases.find({ + from, + to, + owner: APP_ID, + sortField: 'create_at', + sortOrder: 'desc', + page: 1, + perPage: 4, + }); + + if (isSubscribed) { + setItems(parseCases(casesResponse)); + setUpdatedAt(Date.now()); + } + } catch (error) { + if (isSubscribed) { + addError(error, { title: i18n.ERROR_MESSAGE_CASES }); + } + } + setIsLoading(false); + }; + + if (!skip) { + fetchCases(); + } + + if (skip) { + setIsLoading(false); + isSubscribed = false; + abortCtrl.abort(); + } + + return () => { + isSubscribed = false; + abortCtrl.abort(); + }; + }, [cases.api.cases, from, skip, to]); + + return { items, isLoading, updatedAt }; +}; + +function parseCases(casesResponse: Cases): CaseItem[] { + const allCases = casesResponse.cases || []; + + return allCases.reduce((accumulated, currentCase) => { + accumulated.push({ + id: currentCase.id, + name: currentCase.title, + note: currentCase.description, + createdAt: currentCase.createdAt, + createdBy: currentCase.createdBy.username || '—', + status: currentCase.status, + }); + + return accumulated; + }, []); +} diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx index 4fe5bf7785bc7..49ad4352cb586 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback, useMemo } from 'react'; +import styled from 'styled-components'; import { EuiBasicTable, @@ -40,6 +41,11 @@ interface HostAlertsTableProps { const DETECTION_RESPONSE_HOST_SEVERITY_QUERY_ID = 'vulnerableHostsBySeverityQuery'; +// To Do remove this styled component once togglequery is updated: #131405 +const StyledEuiPanel = styled(EuiPanel)` + height: fit-content; +`; + export const HostAlertsTable = React.memo(({ signalIndexName }: HostAlertsTableProps) => { const { getAppUrl, navigateTo } = useNavigation(); const { toggleStatus, setToggleStatus } = useQueryToggle( @@ -62,8 +68,9 @@ export const HostAlertsTable = React.memo(({ signalIndexName }: HostAlertsTableP ); return ( + //
- + )} - + + //
); }); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/use_host_alerts_items.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/use_host_alerts_items.ts index ebd7af1b49cc2..a01cd709b44f6 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/use_host_alerts_items.ts +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/use_host_alerts_items.ts @@ -191,7 +191,7 @@ function parseHostsData( return [ ...accumalatedAlertsByHost, { - hostName: currentHost.key, + hostName: currentHost.key || '—', totalAlerts: currentHost.doc_count, low: currentHost.low.doc_count, medium: currentHost.medium.doc_count, diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/translations.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/translations.ts index 8f37c2e641c7a..d013ab258631a 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/translations.ts +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/translations.ts @@ -103,12 +103,26 @@ export const USER_ALERTS_SECTION_TITLE = i18n.translate( } ); +export const CASES_TABLE_SECTION_TITLE = i18n.translate( + 'xpack.securitySolution.detectionResponse.caseSectionTitle', + { + defaultMessage: 'Recently created cases', + } +); + export const NO_ALERTS_FOUND = i18n.translate( 'xpack.securitySolution.detectionResponse.noRuleAlerts', { defaultMessage: 'No alerts to display', } ); + +export const NO_CASES_FOUND = i18n.translate( + 'xpack.securitySolution.detectionResponse.noRecentCases', + { + defaultMessage: 'No cases to display', + } +); export const RULE_ALERTS_COLUMN_RULE_NAME = i18n.translate( 'xpack.securitySolution.detectionResponse.ruleAlertsColumnRuleName', { @@ -156,14 +170,21 @@ export const OPEN_ALL_ALERTS_BUTTON = i18n.translate( export const VIEW_ALL_USER_ALERTS = i18n.translate( 'xpack.securitySolution.detectionResponse.viewAllUserAlerts', { - defaultMessage: 'View all other user alerts', + defaultMessage: 'View all users', + } +); + +export const VIEW_RECENT_CASES = i18n.translate( + 'xpack.securitySolution.detectionResponse.viewRecentCases', + { + defaultMessage: 'View recent cases', } ); export const VIEW_ALL_HOST_ALERTS = i18n.translate( 'xpack.securitySolution.detectionResponse.viewAllHostAlerts', { - defaultMessage: 'View all other host alerts', + defaultMessage: 'View all hosts', } ); @@ -180,3 +201,45 @@ export const USER_ALERTS_USERNAME_COLUMN = i18n.translate( defaultMessage: 'User name', } ); + +export const CASES_TABLE_COLUMN_NAME = i18n.translate( + 'xpack.securitySolution.detectionResponse.caseColumnName', + { + defaultMessage: 'Name', + } +); + +export const CASES_TABLE_COLUMN_NOTE = i18n.translate( + 'xpack.securitySolution.detectionResponse.caseColumnNote', + { + defaultMessage: 'Note', + } +); + +export const CASES_TABLE_COLUMN_TIME = i18n.translate( + 'xpack.securitySolution.detectionResponse.caseColumnTime', + { + defaultMessage: 'Time', + } +); + +export const CASES_TABLE_COLUMN_CREATED_BY = i18n.translate( + 'xpack.securitySolution.detectionResponse.caseColumnCreatedBy', + { + defaultMessage: 'Created by', + } +); + +export const CASES_TABLE_COLUMN_STATUS = i18n.translate( + 'xpack.securitySolution.detectionResponse.caseColumnStatus', + { + defaultMessage: 'Status', + } +); + +export const ERROR_MESSAGE_CASES = i18n.translate( + 'xpack.securitySolution.detectionResponse.errorMessage', + { + defaultMessage: 'Error fetching case data', + } +); diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/use_user_alerts_items.ts b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/use_user_alerts_items.ts index e86ee2f2aef95..3e2778f82cde4 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/use_user_alerts_items.ts +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/use_user_alerts_items.ts @@ -190,7 +190,7 @@ function parseUsersData(rawAggregation: AlertCountersBySeverityAggregation): Use return [ ...accumalatedAlertsByUser, { - userName: currentUser.key, + userName: currentUser.key || '—', totalAlerts: currentUser.doc_count, low: currentUser.low.doc_count, medium: currentUser.medium.doc_count, diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx index e54ef27c0db34..0416bb48e13e1 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx @@ -6,6 +6,7 @@ */ import React, { useCallback, useMemo } from 'react'; +import styled from 'styled-components'; import { EuiBasicTable, @@ -40,6 +41,11 @@ type GetTableColumns = (params: { const DETECTION_RESPONSE_USER_SEVERITY_QUERY_ID = 'vulnerableUsersBySeverityQuery'; +// To Do remove this styled component once togglequery is updated: #131405 +const StyledEuiPanel = styled(EuiPanel)` + height: fit-content; +`; + export const UserAlertsTable = React.memo(({ signalIndexName }: UserAlertsTableProps) => { const { getAppUrl, navigateTo } = useNavigation(); const { toggleStatus, setToggleStatus } = useQueryToggle( @@ -62,7 +68,7 @@ export const UserAlertsTable = React.memo(({ signalIndexName }: UserAlertsTableP return ( - + )} - + ); }); diff --git a/x-pack/plugins/security_solution/public/overview/pages/detection_response.test.tsx b/x-pack/plugins/security_solution/public/overview/pages/detection_response.test.tsx index 4ad2eeac35240..3b88d22eb4da9 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/detection_response.test.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/detection_response.test.tsx @@ -11,12 +11,24 @@ import { render } from '@testing-library/react'; import { DetectionResponse } from './detection_response'; import { TestProviders } from '../../common/mock'; +jest.mock('../components/detection_response/alerts_by_status', () => ({ + AlertsByStatus: () =>
, +})); + +jest.mock('../components/detection_response/cases_table', () => ({ + CasesTable: () =>
, +})); + +jest.mock('../components/detection_response/host_alerts_table', () => ({ + HostAlertsTable: () =>
, +})); + jest.mock('../components/detection_response/rule_alerts_table', () => ({ RuleAlertsTable: () =>
, })); -jest.mock('../components/detection_response/alerts_by_status', () => ({ - AlertsByStatus: () =>
, +jest.mock('../components/detection_response/user_alerts_table', () => ({ + UserAlertsTable: () =>
, })); jest.mock('../components/detection_response/cases_by_status', () => ({ @@ -37,14 +49,22 @@ jest.mock('../../common/containers/sourcerer', () => ({ useSourcererDataView: () => mockUseSourcererDataView(), })); -const defaultUseUserInfoReturn = { - signalIndexName: '', - canUserREAD: true, +const defaultUseAlertsPrivilegesReturn = { + hasKibanaREAD: true, hasIndexRead: true, }; -const mockUseUserInfo = jest.fn(() => defaultUseUserInfoReturn); -jest.mock('../../detections/components/user_info', () => ({ - useUserInfo: () => mockUseUserInfo(), + +const defaultUseSignalIndexReturn = { + signalIndexName: '', +}; + +const mockUseSignalIndex = jest.fn(() => defaultUseSignalIndexReturn); +jest.mock('../../detections/containers/detection_engine/alerts/use_signal_index', () => ({ + useSignalIndex: () => mockUseSignalIndex(), +})); +const mockUseAlertsPrivileges = jest.fn(() => defaultUseAlertsPrivilegesReturn); +jest.mock('../../detections/containers/detection_engine/alerts/use_alerts_privileges', () => ({ + useAlertsPrivileges: () => mockUseAlertsPrivileges(), })); const defaultUseCasesPermissionsReturn = { read: true }; @@ -61,7 +81,8 @@ describe('DetectionResponse', () => { beforeEach(() => { jest.clearAllMocks(); mockUseSourcererDataView.mockReturnValue(defaultUseSourcererReturn); - mockUseUserInfo.mockReturnValue(defaultUseUserInfoReturn); + mockUseAlertsPrivileges.mockReturnValue(defaultUseAlertsPrivilegesReturn); + mockUseSignalIndex.mockReturnValue(defaultUseSignalIndexReturn); mockUseCasesPermissions.mockReturnValue(defaultUseCasesPermissionsReturn); }); @@ -121,9 +142,9 @@ describe('DetectionResponse', () => { }); it('should not render alerts data sections if user has not index read permission', () => { - mockUseUserInfo.mockReturnValue({ - ...defaultUseUserInfoReturn, + mockUseAlertsPrivileges.mockReturnValue({ hasIndexRead: false, + hasKibanaREAD: true, }); const result = render( @@ -135,18 +156,19 @@ describe('DetectionResponse', () => { ); expect(result.queryByTestId('detectionResponsePage')).toBeInTheDocument(); - // TODO: assert other alert sections are not in the document + expect(result.queryByTestId('mock_CasesTable')).toBeInTheDocument(); + expect(result.queryByTestId('mock_CasesByStatus')).toBeInTheDocument(); + expect(result.queryByTestId('mock_RuleAlertsTable')).not.toBeInTheDocument(); + expect(result.queryByTestId('mock_HostAlertsTable')).not.toBeInTheDocument(); + expect(result.queryByTestId('mock_UserAlertsTable')).not.toBeInTheDocument(); expect(result.queryByTestId('mock_AlertsByStatus')).not.toBeInTheDocument(); - - // TODO: assert cases sections are in the document - expect(result.queryByTestId('mock_CasesByStatus')).toBeInTheDocument(); }); it('should not render alerts data sections if user has not kibana read permission', () => { - mockUseUserInfo.mockReturnValue({ - ...defaultUseUserInfoReturn, - canUserREAD: false, + mockUseAlertsPrivileges.mockReturnValue({ + hasIndexRead: true, + hasKibanaREAD: false, }); const result = render( @@ -158,13 +180,13 @@ describe('DetectionResponse', () => { ); expect(result.queryByTestId('detectionResponsePage')).toBeInTheDocument(); + expect(result.queryByTestId('mock_CasesTable')).toBeInTheDocument(); + expect(result.queryByTestId('mock_CasesByStatus')).toBeInTheDocument(); - // TODO: assert all alert sections are not in the document expect(result.queryByTestId('mock_RuleAlertsTable')).not.toBeInTheDocument(); + expect(result.queryByTestId('mock_HostAlertsTable')).not.toBeInTheDocument(); + expect(result.queryByTestId('mock_UserAlertsTable')).not.toBeInTheDocument(); expect(result.queryByTestId('mock_AlertsByStatus')).not.toBeInTheDocument(); - - // TODO: assert all cases sections are in the document - expect(result.queryByTestId('mock_CasesByStatus')).toBeInTheDocument(); }); it('should not render cases data sections if user has not cases read permission', () => { @@ -178,18 +200,20 @@ describe('DetectionResponse', () => { ); + expect(result.queryByTestId('mock_CasesTable')).not.toBeInTheDocument(); + expect(result.queryByTestId('mock_CasesByStatus')).not.toBeInTheDocument(); + expect(result.queryByTestId('detectionResponsePage')).toBeInTheDocument(); - // TODO: assert all alert sections are in the document expect(result.queryByTestId('mock_RuleAlertsTable')).toBeInTheDocument(); + expect(result.queryByTestId('mock_HostAlertsTable')).toBeInTheDocument(); + expect(result.queryByTestId('mock_UserAlertsTable')).toBeInTheDocument(); expect(result.queryByTestId('mock_AlertsByStatus')).toBeInTheDocument(); - // TODO: assert all cases sections are not in the document - expect(result.queryByTestId('mock_CasesByStatus')).not.toBeInTheDocument(); }); it('should render page permissions message if user has any read permission', () => { mockUseCasesPermissions.mockReturnValue({ read: false }); - mockUseUserInfo.mockReturnValue({ - ...defaultUseUserInfoReturn, + mockUseAlertsPrivileges.mockReturnValue({ + hasKibanaREAD: true, hasIndexRead: false, }); diff --git a/x-pack/plugins/security_solution/public/overview/pages/detection_response.tsx b/x-pack/plugins/security_solution/public/overview/pages/detection_response.tsx index 5b9d298bf915c..fedcca0aac7b4 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/detection_response.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/detection_response.tsx @@ -11,17 +11,20 @@ import { SecuritySolutionPageWrapper } from '../../common/components/page_wrappe import { SpyRoute } from '../../common/utils/route/spy_routes'; import { SecurityPageName } from '../../app/types'; import { useSourcererDataView } from '../../common/containers/sourcerer'; -import { useUserInfo } from '../../detections/components/user_info'; import { HeaderPage } from '../../common/components/header_page'; import { useKibana, useGetUserCasesPermissions } from '../../common/lib/kibana'; -import { HostAlertsTable, UserAlertsTable } from '../components/detection_response'; +import { EmptyPage } from '../../common/components/empty_page'; import { LandingPageComponent } from '../../common/components/landing_page'; +import { useSignalIndex } from '../../detections/containers/detection_engine/alerts/use_signal_index'; +import { useAlertsPrivileges } from '../../detections/containers/detection_engine/alerts/use_alerts_privileges'; +import { AlertsByStatus } from '../components/detection_response/alerts_by_status'; +import { HostAlertsTable } from '../components/detection_response/host_alerts_table'; import { RuleAlertsTable } from '../components/detection_response/rule_alerts_table'; +import { UserAlertsTable } from '../components/detection_response/user_alerts_table'; import * as i18n from './translations'; -import { EmptyPage } from '../../common/components/empty_page'; +import { CasesTable } from '../components/detection_response/cases_table'; import { CasesByStatus } from '../components/detection_response/cases_by_status'; -import { AlertsByStatus } from '../components/detection_response/alerts_by_status'; const NoPrivilegePage: React.FC = () => { const { docLinks } = useKibana().services; @@ -48,9 +51,10 @@ const NoPrivilegePage: React.FC = () => { const DetectionResponseComponent = () => { const { indicesExist, indexPattern, loading: isSourcererLoading } = useSourcererDataView(); - const { signalIndexName, canUserREAD, hasIndexRead } = useUserInfo(); + const { signalIndexName } = useSignalIndex(); + const { hasKibanaREAD, hasIndexRead } = useAlertsPrivileges(); const canReadCases = useGetUserCasesPermissions()?.read; - const canReadAlerts = canUserREAD && hasIndexRead; + const canReadAlerts = hasKibanaREAD && hasIndexRead; if (!canReadAlerts && !canReadCases) { return ; @@ -90,7 +94,11 @@ const DetectionResponseComponent = () => { )} - {canReadCases && {'[cases table]'}} + {canReadCases && ( + + + + )} {canReadAlerts && ( From 2dcbcb45d106a0a5fe16ae09dccba93bb924bf89 Mon Sep 17 00:00:00 2001 From: Ying Mao Date: Wed, 4 May 2022 15:04:25 -0400 Subject: [PATCH 47/68] [Response Ops][Docs] Alerting circuit breaker docs (#131459) * Circuit breaker docs * Apply suggestions from code review Co-authored-by: Lisa Cawley Co-authored-by: Lisa Cawley --- docs/settings/alert-action-settings.asciidoc | 4 +- ...lerting-production-considerations.asciidoc | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index 33c97373a76c4..f3fa027cb186e 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -198,13 +198,13 @@ Specifies the minimum schedule interval for rules. This minimum is applied to al + `[s,m,h,d]` + -For example, `20m`, `24h`, `7d`. Default: `1m`. +For example, `20m`, `24h`, `7d`. This duration cannot exceed `1d`. Default: `1m`. `xpack.alerting.rules.minimumScheduleInterval.enforce`:: Specifies the behavior when a new or changed rule has a schedule interval less than the value defined in `xpack.alerting.rules.minimumScheduleInterval.value`. If `false`, rules with schedules less than the interval will be created but warnings will be logged. If `true`, rules with schedules less than the interval cannot be created. Default: `false`. `xpack.alerting.rules.run.actions.max`:: -Specifies the maximum number of actions that a rule can trigger each time detection checks run. +Specifies the maximum number of actions that a rule can generate each time detection checks run. `xpack.alerting.rules.run.timeout`:: Specifies the default timeout for tasks associated with all types of rules. The time is formatted as: diff --git a/docs/user/production-considerations/alerting-production-considerations.asciidoc b/docs/user/production-considerations/alerting-production-considerations.asciidoc index 42f9a17cc6f88..f94ec1c3d04bb 100644 --- a/docs/user/production-considerations/alerting-production-considerations.asciidoc +++ b/docs/user/production-considerations/alerting-production-considerations.asciidoc @@ -64,3 +64,50 @@ Because {kib} uses the documents to display historic data, you should set the de For more information on index lifecycle management, see: {ref}/index-lifecycle-management.html[Index Lifecycle Policies]. + +[float] +[[alerting-circuit-breakers]] +=== Circuit breakers + +There are several scenarios where running alerting rules and actions can start to negatively impact the overall health of a {kib} instance either by clogging up Task Manager throughput or by consuming so much CPU/memory that other operations cannot complete in a reasonable amount of time. There are several <> circuit breakers to help minimize these effects. + +[float] +==== Rules with very short intervals + +Running large numbers of rules at very short intervals can quickly clog up Task Manager throughput, leading to higher schedule drift. Use `xpack.alerting.rules.minimumScheduleInterval.value` to set a minimum schedule interval for rules. The default (and recommended) value for this configuration is `1m`. Use `xpack.alerting.rules.minimumScheduleInterval.enforce` to specify whether to strictly enforce this minimum. While the default value for this setting is `false` to maintain backwards compatibility with existing rules, set this to `true` to prevent new and updated rules from running at an interval below the minimum. + +[float] +==== Rules that run for a long time + +Rules that run for a long time typically do so because they are issuing resource-intensive {es} queries or performing CPU-intensive processing. This can block the event loop, making {kib} inaccessible while the rule runs. By default, rule processing is cancelled after `5m` but this can be overriden using the `xpack.alerting.rules.run.timeout` configuration. This value can also be configured per rule type using `xpack.alerting.rules.run.ruleTypeOverrides`. For example, the following configuration sets the global timeout value to `1m` while allowing *Index Threshold* rules to run for `10m` before being cancelled. + +[source,yaml] +-- +xpack.alerting.rules.run: + timeout: '1m' + ruleTypeOverrides: + - id: '.index-threshold' + timeout: '10m' +-- + +When a rule run is cancelled, any alerts and actions that were generated during the run are discarded. This behavior is controlled by the `xpack.alerting.cancelAlertsOnRuleTimeout` configuration, which defaults to `true`. Set this to `false` to receive alerts and actions after the timeout, although be aware that these may be incomplete and possibly inaccurate. + +[float] +==== Rules that spawn too many actions + +Rules that spawn too many actions can quickly clog up Task Manager throughput. This can occur if: + +* A rule configured with a single action generates many alerts. For example, if a rule configured to run a single email action generates 100,000 alerts, then 100,000 actions will be scheduled during a run. +* A rule configured with multiple actions generates alerts. For example, if a rule configured to run an email action, a server log action and a webhook action generates 30,000 alerts, then 90,000 actions will be scheduled during a run. + +Use `xpack.alerting.rules.run.actions.max` to limit the maximum number of actions a rule can generate per run. This value can also be configured by connector type using `xpack.alerting.rules.run.actions.connectorTypeOverrides`. For example, the following config sets the global maximum number of actions to 100 while allowing rules with *Email* actions to generate up to 200 actions. + +[source,yaml] +-- +xpack.alerting.rules.run: + actions: + max: 100 + connectorTypeOverrides: + - id: '.email' + max: 200 +-- \ No newline at end of file From 683463ea43db9fc7ba2be43c56d2d059018e90c5 Mon Sep 17 00:00:00 2001 From: Garrett Spong Date: Wed, 4 May 2022 13:22:18 -0600 Subject: [PATCH 48/68] [Security Solution][Detections] Rule Execution Log Feedback and Fixes Part Deux (#130072) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Addresses feedback and fixes identified in https://github.com/elastic/kibana/pull/126215 & https://github.com/elastic/kibana/pull/129003 ##### Feedback addressed includes: * Adds toast for restoring global query state after performing `view alerts for execution` action

* Updates global SuperDatePicker to daterange of execution (+/- day) for `view alerts for execution` action (and clear all other filters) * See above gif * Remove redundant `RuleExecutionStatusType` (https://github.com/elastic/kibana/pull/129003#discussion_r842924704) * Persist table state (DatePicker/StatusFilter/SortField/SortOrder/Pagination) when navigating to other tabs on the same page

* Fix duration hours bug (`7 hours (25033167ms)` as `06:417:13:000`)

* Support `disabled rule` platform error (https://github.com/elastic/kibana/pull/126215#discussion_r834364979) * Updated `getAggregateExecutionEvents` to fallback to platform status from `event.outcome` if `security_status` is empty, and also falls back to `error.message` is `security_message` is empty. This also now queries for corresponding `event.outcome` if filter is provided so that platform-only events can still be displayed when filtering.

* Verify StatusFilter issue https://github.com/elastic/kibana/pull/126215#issuecomment-1080976155 * Unable to reproduce, I believe the query updates around first querying for status may've fixed this? * Provide helpful defaults for `to`/`from` and support datemath strings again (https://github.com/elastic/kibana/pull/129003#discussion_r843091926) * Created enhancement for this here: https://github.com/elastic/kibana/issues/131095 * Adds UI Unit tests for RuleExecutionLog Table * Finalize API Integration tests for gap remediation events * Test methods developed for injecting arbitrary execution events while still working with event-log RBAC. See last [API integration test](https://github.com/elastic/kibana/blob/22cc0c8dbd2a1300675caf4c6d471d211ed44858/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_rule_execution_events.ts#L121-L166) for technique. This can further be used to inject many execution events and expand tests around pagination, sorting, filters, etc. * Fixes `gap_duration`'s of `1-499`ms showing up as `-` instead of `0` * Fixes restore filters action to restore either absolute or relative datepicker as it originally was * Resolves https://github.com/elastic/kibana/issues/130946 * Adds `min-height` to tab container * Removes scroll-pane from ExceptionsViewer to match Alerts/Execution Log --- ##### Remaining follow-ups: None! 🎉 ### Checklist Delete any items that are not applicable to this PR. - [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [X] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [X] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) --- .../schemas/common/rule_monitoring.ts | 6 +- .../get_rule_execution_events_schema.ts | 16 +- .../security_solution/cypress/tasks/alerts.ts | 1 + .../viewer/exceptions_viewer_items.tsx | 9 +- .../visualization_actions/index.test.tsx | 1 + .../events/last_event_time/index.test.ts | 1 + .../containers/sourcerer/index.test.tsx | 1 + .../common/hooks/use_app_toasts.mock.ts | 1 + .../common/hooks/use_app_toasts.test.ts | 3 + .../public/common/hooks/use_app_toasts.ts | 7 +- .../common/lib/kibana/kibana_react.mock.ts | 4 + .../alerts_histogram_panel/index.test.tsx | 1 + .../detection_engine/rules/__mocks__/api.ts | 2 +- .../detection_engine/rules/api.test.ts | 4 +- .../containers/detection_engine/rules/api.ts | 21 +- .../containers/detection_engine/rules/mock.ts | 168 +++++++++ .../rules/use_pre_packaged_rules.test.tsx | 1 + .../rules/use_rule_execution_events.test.tsx | 4 +- .../rules/use_rule_execution_events.tsx | 14 +- .../detection_engine.test.tsx | 1 + .../__mocks__/rule_details_context.tsx | 62 ++++ .../execution_log_table.test.tsx.snap | 140 -------- .../rule_duration_format.test.tsx.snap | 9 - .../execution_log_columns.tsx | 12 +- .../execution_log_search_bar.tsx | 11 +- .../execution_log_table.test.tsx | 95 ++--- .../execution_log_table.tsx | 243 ++++++++++--- .../rule_duration_format.test.tsx | 81 ++++- .../rule_duration_format.tsx | 45 ++- .../execution_log_table/translations.ts | 21 ++ .../detection_engine/rules/details/index.tsx | 339 +++++++++--------- .../rules/details/rule_details_context.tsx | 216 +++++++++++ .../public/network/pages/network.test.tsx | 1 + .../timelines/containers/index.test.tsx | 1 + .../routes/__mocks__/request_responses.ts | 4 +- .../get_rule_execution_events_route.test.ts | 2 - .../client_for_routes/client_interface.ts | 4 +- .../event_log/event_log_reader.ts | 12 +- .../index.test.ts | 71 +++- .../get_execution_event_aggregation/index.ts | 60 +++- .../tests/get_rule_execution_events.ts | 79 +--- .../tests/template_data/execution_events.ts | 197 ++++++++-- .../utils/index_event_log_execution_events.ts | 3 +- 43 files changed, 1330 insertions(+), 644 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/__mocks__/rule_details_context.tsx delete mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/execution_log_table.test.tsx.snap delete mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/rule_duration_format.test.tsx.snap create mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/rule_details_context.tsx diff --git a/x-pack/plugins/security_solution/common/detection_engine/schemas/common/rule_monitoring.ts b/x-pack/plugins/security_solution/common/detection_engine/schemas/common/rule_monitoring.ts index f73e60487a4a8..af005d1b60a8f 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/schemas/common/rule_monitoring.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/schemas/common/rule_monitoring.ts @@ -53,8 +53,6 @@ export enum RuleExecutionStatus { export const ruleExecutionStatus = enumeration('RuleExecutionStatus', RuleExecutionStatus); -export type RuleExecutionStatusType = t.TypeOf; - export const ruleExecutionStatusOrder = PositiveInteger; export type RuleExecutionStatusOrder = t.TypeOf; @@ -130,7 +128,7 @@ export const aggregateRuleExecutionEvent = t.type({ timed_out: t.boolean, indexing_duration_ms: t.number, search_duration_ms: t.number, - gap_duration_ms: t.number, + gap_duration_s: t.number, security_status: t.string, security_message: t.string, }); @@ -140,7 +138,7 @@ export type AggregateRuleExecutionEvent = t.TypeOf( 'DefaultStatusFiltersStringArray', t.array(ruleExecutionStatus).is, - (input, context): Either => { + (input, context): Either => { if (input == null) { return t.success([]); } else if (typeof input === 'string') { - return t.array(ruleExecutionStatus).validate(input.split(','), context); + if (input === '') { + return t.success([]); + } else { + return t.array(ruleExecutionStatus).validate(input.split(','), context); + } } else { return t.array(ruleExecutionStatus).validate(input, context); } diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index 9c5780a9a31fc..3c4d434b1ec3f 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -65,6 +65,7 @@ export const closeAlerts = () => { export const expandFirstAlertActions = () => { cy.get(TIMELINE_CONTEXT_MENU_BTN).should('be.visible'); + cy.get(TIMELINE_CONTEXT_MENU_BTN).find('svg').should('have.class', 'euiIcon-isLoaded'); cy.get(TIMELINE_CONTEXT_MENU_BTN).first().click({ force: true }); }; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx index 5331b2376fd9f..30b5b3e4d1339 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/viewer/exceptions_viewer_items.tsx @@ -23,11 +23,6 @@ const MyFlexItem = styled(EuiFlexItem)` } `; -const MyExceptionsContainer = styled(EuiFlexGroup)` - height: 600px; - overflow: hidden; -`; - const MyExceptionItemContainer = styled(EuiFlexGroup)` margin: ${({ theme }) => `0 ${theme.eui.euiSize} ${theme.eui.euiSize} 0`}; `; @@ -55,7 +50,7 @@ const ExceptionsViewerItemsComponent: React.FC = ({ onEditExceptionItem, disableActions, }): JSX.Element => ( - + {showEmpty || showNoResults || isInitLoading ? ( = ({ )} - + ); ExceptionsViewerItemsComponent.displayName = 'ExceptionsViewerItemsComponent'; diff --git a/x-pack/plugins/security_solution/public/common/components/visualization_actions/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/visualization_actions/index.test.tsx index b06fde164af76..162f321b33f6c 100644 --- a/x-pack/plugins/security_solution/public/common/components/visualization_actions/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/visualization_actions/index.test.tsx @@ -95,6 +95,7 @@ describe('VisualizationActions', () => { addError: jest.fn(), addSuccess: jest.fn(), addWarning: jest.fn(), + remove: jest.fn(), }, }, http: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts index 1bd188d01cb51..ce03d159df5a9 100644 --- a/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/containers/events/last_event_time/index.test.ts @@ -47,6 +47,7 @@ jest.mock('../../../lib/kibana', () => ({ addError: jest.fn(), addSuccess: jest.fn(), addWarning: jest.fn(), + remove: jest.fn(), }), })); diff --git a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx index 1d02d608c0e92..a949478593466 100644 --- a/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/containers/sourcerer/index.test.tsx @@ -60,6 +60,7 @@ jest.mock('../../lib/kibana', () => ({ addError: jest.fn(), addSuccess: jest.fn(), addWarning: mockAddWarning, + remove: jest.fn(), }), useKibana: () => ({ services: { diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.mock.ts b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.mock.ts index c0bb52b20c534..ae3783e82cdbf 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.mock.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.mock.ts @@ -11,6 +11,7 @@ const createAppToastsMock = (): jest.Mocked => ({ addError: jest.fn(), addSuccess: jest.fn(), addWarning: jest.fn(), + remove: jest.fn(), api: { get$: jest.fn(), add: jest.fn(), diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts index 9bea6282e3ad6..359d29be7cd08 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.test.ts @@ -30,15 +30,18 @@ describe('useAppToasts', () => { let addErrorMock: jest.Mock; let addSuccessMock: jest.Mock; let addWarningMock: jest.Mock; + let removeMock: jest.Mock; beforeEach(() => { addErrorMock = jest.fn(); addSuccessMock = jest.fn(); addWarningMock = jest.fn(); + removeMock = jest.fn(); (useToasts as jest.Mock).mockImplementation(() => ({ addError: addErrorMock, addSuccess: addSuccessMock, addWarning: addWarningMock, + remove: removeMock, })); }); diff --git a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts index 4b3b28a54c642..d9c3713f3a4ba 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_app_toasts.ts @@ -19,7 +19,7 @@ import { IEsError, isEsError } from '@kbn/data-plugin/public'; import { ErrorToastOptions, ToastsStart, Toast } from '@kbn/core/public'; import { useToasts } from '../lib/kibana'; -export type UseAppToasts = Pick & { +export type UseAppToasts = Pick & { api: ToastsStart; addError: (error: unknown, options: ErrorToastOptions) => Toast; }; @@ -36,6 +36,7 @@ export const useAppToasts = (): UseAppToasts => { const addError = useRef(toasts.addError.bind(toasts)).current; const addSuccess = useRef(toasts.addSuccess.bind(toasts)).current; const addWarning = useRef(toasts.addWarning.bind(toasts)).current; + const remove = useRef(toasts.remove.bind(toasts)).current; const _addError = useCallback( (error: unknown, options: ErrorToastOptions) => { @@ -46,8 +47,8 @@ export const useAppToasts = (): UseAppToasts => { ); return useMemo( - () => ({ api: toasts, addError: _addError, addSuccess, addWarning }), - [_addError, addSuccess, addWarning, toasts] + () => ({ api: toasts, addError: _addError, addSuccess, addWarning, remove }), + [_addError, addSuccess, addWarning, remove, toasts] ); }; diff --git a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts index 0097e31cfee8a..09e7c1fa6e8c8 100644 --- a/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/kibana/kibana_react.mock.ts @@ -157,6 +157,10 @@ export const createStartServicesMock = ( theme: { theme$: themeServiceMock.createTheme$(), }, + timelines: { + getLastUpdated: jest.fn(), + getFieldBrowser: jest.fn(), + }, } as unknown as StartServices; }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx index 3c82161851dd3..539728291156f 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.test.tsx @@ -55,6 +55,7 @@ jest.mock('../../../../common/lib/kibana/kibana_react', () => { addWarning: jest.fn(), addError: jest.fn(), addSuccess: jest.fn(), + remove: jest.fn(), }, }, }, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts index d93d667f5fbca..59f79b294d7fa 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/__mocks__/api.ts @@ -78,7 +78,7 @@ export const fetchRuleExecutionEvents = async ({ duration_ms: 3866, es_search_duration_ms: 1236, execution_uuid: '88d15095-7937-462c-8f21-9763e1387cad', - gap_duration_ms: 0, + gap_duration_s: 0, indexing_duration_ms: 95, message: "rule executed: siem.queryRule:fb1fc150-a292-11ec-a2cf-c1b28b0392b0: 'Lots of Execution Events'", diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts index b999040674a91..c932d0f982bb6 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts @@ -630,7 +630,7 @@ describe('Detections Rules API', () => { start: '2001-01-01T17:00:00.000Z', end: '2001-01-02T17:00:00.000Z', queryText: '', - statusFilters: '', + statusFilters: [], signal: abortCtrl.signal, }); @@ -659,7 +659,7 @@ describe('Detections Rules API', () => { start: 'now-30', end: 'now', queryText: '', - statusFilters: '', + statusFilters: [], signal: abortCtrl.signal, }); expect(response).toEqual(responseMock); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts index cb78a7a116ae4..220926ebc1722 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { camelCase } from 'lodash'; import dateMath from '@kbn/datemath'; import { HttpStart } from '@kbn/core/public'; @@ -18,7 +19,11 @@ import { DETECTION_ENGINE_RULES_PREVIEW, detectionEngineRuleExecutionEventsUrl, } from '../../../../../common/constants'; -import { BulkAction } from '../../../../../common/detection_engine/schemas/common'; +import { + AggregateRuleExecutionEvent, + BulkAction, + RuleExecutionStatus, +} from '../../../../../common/detection_engine/schemas/common'; import { FullResponseSchema, PreviewResponse, @@ -320,11 +325,11 @@ export const exportRules = async ({ * @param start Start daterange either in UTC ISO8601 or as datemath string (e.g. `2021-12-29T02:44:41.653Z` or `now-30`) * @param end End daterange either in UTC ISO8601 or as datemath string (e.g. `2021-12-29T02:44:41.653Z` or `now/w`) * @param queryText search string in querystring format (e.g. `event.duration > 1000 OR kibana.alert.rule.execution.metrics.execution_gap_duration_s > 100`) - * @param statusFilters comma separated string of `statusFilters` (e.g. `succeeded,failed,partial failure`) + * @param statusFilters RuleExecutionStatus[] array of `statusFilters` (e.g. `succeeded,failed,partial failure`) * @param page current page to fetch * @param perPage number of results to fetch per page - * @param sortField field to sort by - * @param sortOrder what order to sort by (e.g. `asc` or `desc`) + * @param sortField keyof AggregateRuleExecutionEvent field to sort by + * @param sortOrder SortOrder what order to sort by (e.g. `asc` or `desc`) * @param signal AbortSignal Optional signal for cancelling the request * * @throws An error if response is not OK @@ -345,11 +350,11 @@ export const fetchRuleExecutionEvents = async ({ start: string; end: string; queryText?: string; - statusFilters?: string; + statusFilters?: RuleExecutionStatus[]; page?: number; perPage?: number; - sortField?: string; - sortOrder?: string; + sortField?: keyof AggregateRuleExecutionEvent; + sortOrder?: SortOrder; signal?: AbortSignal; }): Promise => { const url = detectionEngineRuleExecutionEventsUrl(ruleId); @@ -361,7 +366,7 @@ export const fetchRuleExecutionEvents = async ({ start: startDate?.utc().toISOString(), end: endDate?.utc().toISOString(), query_text: queryText, - status_filters: statusFilters, + status_filters: statusFilters?.sort()?.join(','), page, per_page: perPage, sort_field: sortField, diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/mock.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/mock.ts index 533ab6138cb09..8c1737a4519a7 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/mock.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/mock.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { GetAggregateRuleExecutionEventsResponse } from '../../../../../common/detection_engine/schemas/response'; import { FetchRulesResponse, Rule } from './types'; export const savedRuleMock: Rule = { @@ -126,3 +127,170 @@ export const rulesMock: FetchRulesResponse = { }, ], }; + +export const ruleExecutionEventsMock: GetAggregateRuleExecutionEventsResponse = { + events: [ + { + execution_uuid: 'dc45a63c-4872-4964-a2d0-bddd8b2e634d', + timestamp: '2022-04-28T21:19:08.047Z', + duration_ms: 3, + status: 'failure', + message: 'siem.queryRule:a6e61cf0-c737-11ec-9e32-e14913ffdd2d: execution failed', + num_active_alerts: 0, + num_new_alerts: 0, + num_recovered_alerts: 0, + num_triggered_actions: 0, + num_succeeded_actions: 0, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 0, + schedule_delay_ms: 2169, + timed_out: false, + indexing_duration_ms: 0, + search_duration_ms: 0, + gap_duration_s: 0, + security_status: 'failed', + security_message: 'Rule failed to execute because rule ran after it was disabled.', + }, + { + execution_uuid: '0fde9271-05d0-4bfb-8ff8-815756d28350', + timestamp: '2022-04-28T21:19:04.973Z', + duration_ms: 1446, + status: 'success', + message: + "rule executed: siem.queryRule:a6e61cf0-c737-11ec-9e32-e14913ffdd2d: 'Click here for hot fresh alerts!'", + num_active_alerts: 0, + num_new_alerts: 0, + num_recovered_alerts: 0, + num_triggered_actions: 0, + num_succeeded_actions: 0, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 0, + schedule_delay_ms: 2089, + timed_out: false, + indexing_duration_ms: 0, + search_duration_ms: 2, + gap_duration_s: 0, + security_status: 'succeeded', + security_message: 'succeeded', + }, + { + execution_uuid: '5daaa259-ded8-4a52-853e-1e7652d325d5', + timestamp: '2022-04-28T21:19:01.976Z', + duration_ms: 1395, + status: 'success', + message: + "rule executed: siem.queryRule:a6e61cf0-c737-11ec-9e32-e14913ffdd2d: 'Click here for hot fresh alerts!'", + num_active_alerts: 0, + num_new_alerts: 0, + num_recovered_alerts: 0, + num_triggered_actions: 0, + num_succeeded_actions: 0, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 1, + schedule_delay_ms: 2637, + timed_out: false, + indexing_duration_ms: 0, + search_duration_ms: 3, + gap_duration_s: 0, + security_status: 'succeeded', + security_message: 'succeeded', + }, + { + execution_uuid: 'c7223e1c-4264-4a27-8697-0d720243fafc', + timestamp: '2022-04-28T21:18:58.431Z', + duration_ms: 1815, + status: 'success', + message: + "rule executed: siem.queryRule:a6e61cf0-c737-11ec-9e32-e14913ffdd2d: 'Click here for hot fresh alerts!'", + num_active_alerts: 0, + num_new_alerts: 0, + num_recovered_alerts: 0, + num_triggered_actions: 0, + num_succeeded_actions: 0, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 1, + schedule_delay_ms: -255429, + timed_out: false, + indexing_duration_ms: 0, + search_duration_ms: 3, + gap_duration_s: 0, + security_status: 'succeeded', + security_message: 'succeeded', + }, + { + execution_uuid: '1f6ba0c1-cc36-4f45-b919-7790b8a8d670', + timestamp: '2022-04-28T21:18:13.954Z', + duration_ms: 2055, + status: 'success', + message: + "rule executed: siem.queryRule:a6e61cf0-c737-11ec-9e32-e14913ffdd2d: 'Click here for hot fresh alerts!'", + num_active_alerts: 0, + num_new_alerts: 0, + num_recovered_alerts: 0, + num_triggered_actions: 0, + num_succeeded_actions: 0, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 0, + schedule_delay_ms: 2027, + timed_out: false, + indexing_duration_ms: 0, + search_duration_ms: 0, + gap_duration_s: 0, + security_status: 'partial failure', + security_message: + 'Check privileges failed to execute ResponseError: index_not_found_exception: [index_not_found_exception] Reason: no such index [yup] name: "Click here for hot fresh alerts!" id: "a6e61cf0-c737-11ec-9e32-e14913ffdd2d" rule id: "34946b12-88d1-49ef-82b7-9cad45972030" execution id: "1f6ba0c1-cc36-4f45-b919-7790b8a8d670" space ID: "default"', + }, + { + execution_uuid: 'b0f65d64-b229-432b-9d39-f4385a7f9368', + timestamp: '2022-04-28T21:15:43.086Z', + duration_ms: 1205, + status: 'success', + message: + "rule executed: siem.queryRule:a6e61cf0-c737-11ec-9e32-e14913ffdd2d: 'Click here for hot fresh alerts!'", + num_active_alerts: 0, + num_new_alerts: 0, + num_recovered_alerts: 0, + num_triggered_actions: 0, + num_succeeded_actions: 0, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 672, + schedule_delay_ms: 3086, + timed_out: false, + indexing_duration_ms: 140, + search_duration_ms: 684, + gap_duration_s: 0, + security_status: 'succeeded', + security_message: 'succeeded', + }, + { + execution_uuid: '7bfd25b9-c0d8-44b1-982c-485169466a8e', + timestamp: '2022-04-28T21:10:40.135Z', + duration_ms: 6321, + status: 'success', + message: + "rule executed: siem.queryRule:a6e61cf0-c737-11ec-9e32-e14913ffdd2d: 'Click here for hot fresh alerts!'", + num_active_alerts: 0, + num_new_alerts: 0, + num_recovered_alerts: 0, + num_triggered_actions: 0, + num_succeeded_actions: 0, + num_errored_actions: 0, + total_search_duration_ms: 0, + es_search_duration_ms: 930, + schedule_delay_ms: 1222, + timed_out: false, + indexing_duration_ms: 2103, + search_duration_ms: 946, + gap_duration_s: 0, + security_status: 'succeeded', + security_message: 'succeeded', + }, + ], + total: 7, +}; diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx index 6596cefef4f08..dfeaca617ed24 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_pre_packaged_rules.test.tsx @@ -18,6 +18,7 @@ jest.mock('../../../../common/lib/kibana', () => ({ addError: jest.fn(), addSuccess: jest.fn(), addWarning: jest.fn(), + remove: jest.fn(), }), })); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.test.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.test.tsx index 2a4efb7f69491..5fba7dd7a2ed2 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.test.tsx @@ -51,7 +51,7 @@ describe('useRuleExecutionEvents', () => { start: 'now-30', end: 'now', queryText: '', - statusFilters: '', + statusFilters: [], }), { wrapper: createReactQueryWrapper(), @@ -92,7 +92,7 @@ describe('useRuleExecutionEvents', () => { duration_ms: 3866, es_search_duration_ms: 1236, execution_uuid: '88d15095-7937-462c-8f21-9763e1387cad', - gap_duration_ms: 0, + gap_duration_s: 0, indexing_duration_ms: 95, message: "rule executed: siem.queryRule:fb1fc150-a292-11ec-a2cf-c1b28b0392b0: 'Lots of Execution Events'", diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.tsx b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.tsx index f2e72858cf392..e18d1f6c2ce5c 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.tsx +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_execution_events.tsx @@ -5,22 +5,27 @@ * 2.0. */ +import { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { useQuery } from 'react-query'; +import { + AggregateRuleExecutionEvent, + RuleExecutionStatus, +} from '../../../../../common/detection_engine/schemas/common'; import { GetAggregateRuleExecutionEventsResponse } from '../../../../../common/detection_engine/schemas/response'; import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import { fetchRuleExecutionEvents } from './api'; import * as i18n from './translations'; -interface UseRuleExecutionEventsArgs { +export interface UseRuleExecutionEventsArgs { ruleId: string; start: string; end: string; queryText?: string; - statusFilters?: string; + statusFilters?: RuleExecutionStatus[]; page?: number; perPage?: number; - sortField?: string; - sortOrder?: string; + sortField?: keyof AggregateRuleExecutionEvent; + sortOrder?: SortOrder; } export const useRuleExecutionEvents = ({ @@ -66,6 +71,7 @@ export const useRuleExecutionEvents = ({ }); }, { + keepPreviousData: true, onError: (e) => { addError(e, { title: i18n.RULE_EXECUTION_EVENTS_FETCH_FAILURE }); }, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx index a783ac7e1e260..1f066751c2b92 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.test.tsx @@ -98,6 +98,7 @@ jest.mock('../../../common/lib/kibana', () => { addError: jest.fn(), addSuccess: jest.fn(), addWarning: jest.fn(), + remove: jest.fn(), }), }; }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/__mocks__/rule_details_context.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/__mocks__/rule_details_context.tsx new file mode 100644 index 0000000000000..257dc8ec512a8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/__mocks__/rule_details_context.tsx @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { RuleDetailsContextType } from '../rule_details_context'; +import React from 'react'; + +export const useRuleDetailsContextMock = { + create: (): jest.Mocked => ({ + executionLogs: { + state: { + superDatePicker: { + recentlyUsedRanges: [], + refreshInterval: 1000, + isPaused: true, + start: 'now-24h', + end: 'now', + }, + queryText: '', + statusFilters: [], + showMetricColumns: true, + pagination: { + pageIndex: 1, + pageSize: 5, + }, + sort: { + sortField: 'timestamp', + sortDirection: 'desc', + }, + }, + actions: { + setEnd: jest.fn(), + setIsPaused: jest.fn(), + setPageIndex: jest.fn(), + setPageSize: jest.fn(), + setQueryText: jest.fn(), + setRecentlyUsedRanges: jest.fn(), + setRefreshInterval: jest.fn(), + setShowMetricColumns: jest.fn(), + setSortDirection: jest.fn(), + setSortField: jest.fn(), + setStart: jest.fn(), + setStatusFilters: jest.fn(), + }, + }, + }), +}; + +export const useRuleDetailsContext = jest + .fn, []>() + .mockImplementation(useRuleDetailsContextMock.create); + +export const useRuleDetailsContextOptional = jest + .fn, []>() + .mockImplementation(useRuleDetailsContextMock.create); + +export const RulesTableContextProvider = jest + .fn() + .mockImplementation(({ children }: { children: React.ReactNode }) => <>{children}); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/execution_log_table.test.tsx.snap b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/execution_log_table.test.tsx.snap deleted file mode 100644 index f93cce70172dc..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/execution_log_table.test.tsx.snap +++ /dev/null @@ -1,140 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ExecutionLogTable snapshots renders correctly against snapshot 1`] = ` - - - - - - - - - - - - - - - Showing 0 rule executions - - - - - - - - - - - , - "render": [Function], - "sortable": false, - "truncateText": false, - "width": "10%", - }, - Object { - "field": "timestamp", - "name": , - "render": [Function], - "sortable": true, - "truncateText": false, - "width": "15%", - }, - Object { - "field": "duration_ms", - "name": , - "render": [Function], - "sortable": true, - "truncateText": false, - "width": "10%", - }, - Object { - "field": "security_message", - "name": , - "render": [Function], - "sortable": false, - "truncateText": false, - "width": "35%", - }, - ] - } - items={Array []} - noItemsMessage={ - - } - onChange={[Function]} - pagination={ - Object { - "pageIndex": 0, - "pageSize": 5, - "pageSizeOptions": Array [ - 5, - 10, - 25, - 50, - ], - "totalItemCount": 0, - } - } - responsive={true} - sorting={ - Object { - "sort": Object { - "direction": "desc", - "field": "timestamp", - }, - } - } - tableLayout="fixed" - /> - -`; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/rule_duration_format.test.tsx.snap b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/rule_duration_format.test.tsx.snap deleted file mode 100644 index ddb59cf52a890..0000000000000 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/__snapshots__/rule_duration_format.test.tsx.snap +++ /dev/null @@ -1,9 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`RuleDurationFormat snapshots renders correctly against snapshot 1`] = ` - - 00:00:00:000 - -`; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_columns.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_columns.tsx index c48f5d6971d23..98569b701d93c 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_columns.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_columns.tsx @@ -6,9 +6,9 @@ */ import { EuiBasicTableColumn, EuiHealth, EuiLink, EuiText } from '@elastic/eui'; -import { capitalize } from 'lodash'; -import { FormattedMessage } from '@kbn/i18n-react'; import { DocLinksStart } from '@kbn/core/public'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { capitalize } from 'lodash'; import React from 'react'; import { AggregateRuleExecutionEvent, @@ -19,9 +19,9 @@ import { FormattedDate } from '../../../../../../common/components/formatted_dat import { getStatusColor } from '../../../../../components/rules/rule_execution_status/utils'; import { PopoverTooltip } from '../../all/popover_tooltip'; import { TableHeaderTooltipCell } from '../../all/table_header_tooltip_cell'; +import { RuleDurationFormat } from './rule_duration_format'; import * as i18n from './translations'; -import { RuleDurationFormat } from './rule_duration_format'; export const EXECUTION_LOG_COLUMNS: Array> = [ { @@ -32,7 +32,7 @@ export const EXECUTION_LOG_COLUMNS: Array ), field: 'security_status', - render: (value: RuleExecutionStatus, data) => + render: (value: RuleExecutionStatus) => value ? ( {capitalize(value)} ) : ( @@ -89,7 +89,7 @@ export const GET_EXECUTION_LOG_METRICS_COLUMNS = ( docLinks: DocLinksStart ): Array> => [ { - field: 'gap_duration_ms', + field: 'gap_duration_s', name: ( ), render: (value: number) => ( - <>{value ? : getEmptyValue()} + <>{value ? : getEmptyValue()} ), sortable: true, truncateText: false, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_search_bar.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_search_bar.tsx index b8c2d82ab324e..74804b7c6b557 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_search_bar.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_search_bar.tsx @@ -56,20 +56,23 @@ const statusFilters = statuses.map((status) => ({ interface ExecutionLogTableSearchProps { onlyShowFilters: true; onSearch: (queryText: string) => void; - onStatusFilterChange: (statusFilters: string[]) => void; + onStatusFilterChange: (statusFilters: RuleExecutionStatus[]) => void; + defaultSelectedStatusFilters?: RuleExecutionStatus[]; } /** * SearchBar + StatusFilters component to be used with the Rule Execution Log table - * NOTE: This component is currently not shown in the UI as custom search queries + * NOTE: The SearchBar component is currently not shown in the UI as custom search queries * are not yet fully supported by the Rule Execution Log aggregation API since * certain queries could result in missing data or inclusion of wrong events. * Please see this comment for history/details: https://github.com/elastic/kibana/pull/127339/files#r825240516 */ export const ExecutionLogSearchBar = React.memo( - ({ onlyShowFilters, onSearch, onStatusFilterChange }) => { + ({ onlyShowFilters, onSearch, onStatusFilterChange, defaultSelectedStatusFilters = [] }) => { const [isPopoverOpen, setIsPopoverOpen] = useState(false); - const [selectedFilters, setSelectedFilters] = useState([]); + const [selectedFilters, setSelectedFilters] = useState( + defaultSelectedStatusFilters + ); const onSearchCallback = useCallback( (queryText: string) => { diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.test.tsx index 81619d01934ba..608853f004eb9 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.test.tsx @@ -5,83 +5,21 @@ * 2.0. */ +import { ruleExecutionEventsMock } from '../../../../../containers/detection_engine/rules/mock'; +import { render, screen } from '@testing-library/react'; +import { TestProviders } from '../../../../../../common/mock'; +import { useRuleDetailsContextMock } from '../__mocks__/rule_details_context'; import React from 'react'; -import { shallow } from 'enzyme'; import { noop } from 'lodash/fp'; +import { useRuleExecutionEvents } from '../../../../../containers/detection_engine/rules'; import { useSourcererDataView } from '../../../../../../common/containers/sourcerer'; +import { useRuleDetailsContext } from '../rule_details_context'; import { ExecutionLogTable } from './execution_log_table'; -jest.mock('../../../../../containers/detection_engine/rules', () => { - const original = jest.requireActual('../../../../../containers/detection_engine/rules'); - return { - ...original, - useRuleExecutionEvents: jest.fn().mockReturnValue({ - loading: true, - setQuery: () => undefined, - data: null, - response: '', - request: '', - refetch: null, - }), - }; -}); - jest.mock('../../../../../../common/containers/sourcerer'); - -jest.mock('../../../../../../common/hooks/use_app_toasts', () => { - const original = jest.requireActual('../../../../../../common/hooks/use_app_toasts'); - - return { - ...original, - useAppToasts: () => ({ - addSuccess: jest.fn(), - addError: jest.fn(), - }), - }; -}); - -jest.mock('react-redux', () => { - const original = jest.requireActual('react-redux'); - return { - ...original, - useDispatch: () => jest.fn(), - useSelector: () => jest.fn(), - }; -}); - -jest.mock('../../../../../../common/lib/kibana', () => { - const original = jest.requireActual('../../../../../../common/lib/kibana'); - - return { - ...original, - useUiSetting$: jest.fn().mockReturnValue([]), - useKibana: () => ({ - services: { - data: { - query: { - filterManager: jest.fn().mockReturnValue({}), - }, - }, - docLinks: { - links: { - siem: { - troubleshootGaps: 'link', - }, - }, - }, - storage: { - get: jest.fn(), - set: jest.fn(), - }, - timelines: { - getLastUpdated: jest.fn(), - getFieldBrowser: jest.fn(), - }, - }, - }), - }; -}); +jest.mock('../../../../../containers/detection_engine/rules'); +jest.mock('../rule_details_context'); const mockUseSourcererDataView = useSourcererDataView as jest.Mock; mockUseSourcererDataView.mockReturnValue({ @@ -92,13 +30,20 @@ mockUseSourcererDataView.mockReturnValue({ loading: false, }); -// TODO: Replace snapshot test with base test cases +const mockUseRuleExecutionEvents = useRuleExecutionEvents as jest.Mock; +mockUseRuleExecutionEvents.mockReturnValue({ + data: ruleExecutionEventsMock, + isLoading: false, + isFetching: false, +}); describe('ExecutionLogTable', () => { - describe('snapshots', () => { - test('renders correctly against snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + test('Shows total events returned', () => { + const ruleDetailsContext = useRuleDetailsContextMock.create(); + (useRuleDetailsContext as jest.Mock).mockReturnValue(ruleDetailsContext); + render(, { + wrapper: TestProviders, }); + expect(screen.getByTestId('executionsShowing')).toHaveTextContent('Showing 7 rule executions'); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.tsx index 31fc446fa2bb7..b471493a9ecd2 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/execution_log_table.tsx @@ -5,10 +5,10 @@ * 2.0. */ -import { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { DurationRange } from '@elastic/eui/src/components/date_picker/types'; +import { useDispatch } from 'react-redux'; import styled from 'styled-components'; -import React, { useCallback, useMemo, useState } from 'react'; +import moment from 'moment'; +import React, { useCallback, useMemo, useRef } from 'react'; import { EuiTextColor, EuiFlexGroup, @@ -20,11 +20,17 @@ import { EuiSpacer, EuiSwitch, EuiBasicTable, + EuiButton, } from '@elastic/eui'; -import { buildFilter, FILTERS } from '@kbn/es-query'; +import { buildFilter, Filter, FILTERS, Query } from '@kbn/es-query'; import { MAX_EXECUTION_EVENTS_DISPLAYED } from '@kbn/securitysolution-rules'; +import { mountReactNode } from '@kbn/core/public/utils'; +import { RuleDetailTabs } from '..'; import { RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY } from '../../../../../../../common/constants'; -import { AggregateRuleExecutionEvent } from '../../../../../../../common/detection_engine/schemas/common'; +import { + AggregateRuleExecutionEvent, + RuleExecutionStatus, +} from '../../../../../../../common/detection_engine/schemas/common'; import { UtilityBar, @@ -34,9 +40,23 @@ import { } from '../../../../../../common/components/utility_bar'; import { useSourcererDataView } from '../../../../../../common/containers/sourcerer'; import { useAppToasts } from '../../../../../../common/hooks/use_app_toasts'; +import { useDeepEqualSelector } from '../../../../../../common/hooks/use_selector'; import { useKibana } from '../../../../../../common/lib/kibana'; +import { inputsSelectors } from '../../../../../../common/store'; +import { + setAbsoluteRangeDatePicker, + setFilterQuery, + setRelativeRangeDatePicker, +} from '../../../../../../common/store/inputs/actions'; +import { + AbsoluteTimeRange, + isAbsoluteTimeRange, + isRelativeTimeRange, + RelativeTimeRange, +} from '../../../../../../common/store/inputs/model'; import { SourcererScopeName } from '../../../../../../common/store/sourcerer/model'; import { useRuleExecutionEvents } from '../../../../../containers/detection_engine/rules'; +import { useRuleDetailsContext } from '../rule_details_context'; import * as i18n from './translations'; import { EXECUTION_LOG_COLUMNS, GET_EXECUTION_LOG_METRICS_COLUMNS } from './execution_log_columns'; import { ExecutionLogSearchBar } from './execution_log_search_bar'; @@ -56,6 +76,12 @@ interface ExecutionLogTableProps { selectAlertsTab: () => void; } +interface CachedGlobalQueryState { + filters: Filter[]; + query: Query; + timerange: AbsoluteTimeRange | RelativeTimeRange; +} + const ExecutionLogTableComponent: React.FC = ({ ruleId, selectAlertsTab, @@ -68,28 +94,84 @@ const ExecutionLogTableComponent: React.FC = ({ storage, timelines, } = useKibana().services; - // Datepicker state - const [recentlyUsedRanges, setRecentlyUsedRanges] = useState([]); - const [refreshInterval, setRefreshInterval] = useState(1000); - const [isPaused, setIsPaused] = useState(true); - const [start, setStart] = useState('now-24h'); - const [end, setEnd] = useState('now'); - // Searchbar/Filter/Settings state - const [queryText, setQueryText] = useState(''); - const [statusFilters, setStatusFilters] = useState(undefined); - const [showMetricColumns, setShowMetricColumns] = useState( - storage.get(RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY) ?? false - ); + const { + [RuleDetailTabs.executionLogs]: { + state: { + superDatePicker: { recentlyUsedRanges, refreshInterval, isPaused, start, end }, + queryText, + statusFilters, + showMetricColumns, + pagination: { pageIndex, pageSize }, + sort: { sortField, sortDirection }, + }, + actions: { + setEnd, + setIsPaused, + setPageIndex, + setPageSize, + setQueryText, + setRecentlyUsedRanges, + setRefreshInterval, + setShowMetricColumns, + setSortDirection, + setSortField, + setStart, + setStatusFilters, + }, + }, + } = useRuleDetailsContext(); - // Pagination state - const [pageIndex, setPageIndex] = useState(1); - const [pageSize, setPageSize] = useState(5); - const [sortField, setSortField] = useState('timestamp'); - const [sortDirection, setSortDirection] = useState('desc'); // Index for `add filter` action and toasts for errors const { indexPattern } = useSourcererDataView(SourcererScopeName.detections); - const { addError, addSuccess } = useAppToasts(); + const { addError, addSuccess, remove } = useAppToasts(); + + // QueryString, Filters, and TimeRange state + const dispatch = useDispatch(); + const getGlobalFiltersQuerySelector = useMemo( + () => inputsSelectors.globalFiltersQuerySelector(), + [] + ); + const getGlobalQuerySelector = useMemo(() => inputsSelectors.globalQuerySelector(), []); + const timerange = useDeepEqualSelector(inputsSelectors.globalTimeRangeSelector); + const query = useDeepEqualSelector(getGlobalQuerySelector); + const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); + const cachedGlobalQueryState = useRef({ filters, query, timerange }); + const successToastId = useRef(''); + + const resetGlobalQueryState = useCallback(() => { + if (isAbsoluteTimeRange(cachedGlobalQueryState.current.timerange)) { + dispatch( + setAbsoluteRangeDatePicker({ + id: 'global', + from: cachedGlobalQueryState.current.timerange.from, + to: cachedGlobalQueryState.current.timerange.to, + }) + ); + } else if (isRelativeTimeRange(cachedGlobalQueryState.current.timerange)) { + dispatch( + setRelativeRangeDatePicker({ + id: 'global', + from: cachedGlobalQueryState.current.timerange.from, + fromStr: cachedGlobalQueryState.current.timerange.fromStr, + to: cachedGlobalQueryState.current.timerange.to, + toStr: cachedGlobalQueryState.current.timerange.toStr, + }) + ); + } + + dispatch( + setFilterQuery({ + id: 'global', + query: cachedGlobalQueryState.current.query.query, + language: cachedGlobalQueryState.current.query.language, + }) + ); + // Using filterManager directly as dispatch(setSearchBarFilter()) was not replacing filters + filterManager.removeAll(); + filterManager.addFilters(cachedGlobalQueryState.current.filters); + remove(successToastId.current); + }, [dispatch, filterManager, remove]); // Table data state const { @@ -118,15 +200,18 @@ const ExecutionLogTableComponent: React.FC = ({ }, [indexPattern]); // Callbacks - const onTableChangeCallback = useCallback(({ page = {}, sort = {} }) => { - const { index, size } = page; - const { field, direction } = sort; + const onTableChangeCallback = useCallback( + ({ page = {}, sort = {} }) => { + const { index, size } = page; + const { field, direction } = sort; - setPageIndex(index + 1); - setPageSize(size); - setSortField(field); - setSortDirection(direction); - }, []); + setPageIndex(index + 1); + setPageSize(size); + setSortField(field); + setSortDirection(direction); + }, + [setPageIndex, setPageSize, setSortDirection, setSortField] + ); const onTimeChangeCallback = useCallback( (props: OnTimeChangeProps) => { @@ -141,14 +226,17 @@ const ExecutionLogTableComponent: React.FC = ({ recentlyUsedRange.length > 10 ? recentlyUsedRange.slice(0, 9) : recentlyUsedRange ); }, - [recentlyUsedRanges] + [recentlyUsedRanges, setEnd, setRecentlyUsedRanges, setStart] ); - const onRefreshChangeCallback = useCallback((props: OnRefreshChangeProps) => { - setIsPaused(props.isPaused); - // Only support auto-refresh >= 1minute -- no current ability to limit within component - setRefreshInterval(props.refreshInterval > 60000 ? props.refreshInterval : 60000); - }, []); + const onRefreshChangeCallback = useCallback( + (props: OnRefreshChangeProps) => { + setIsPaused(props.isPaused); + // Only support auto-refresh >= 1minute -- no current ability to limit within component + setRefreshInterval(props.refreshInterval > 60000 ? props.refreshInterval : 60000); + }, + [setIsPaused, setRefreshInterval] + ); const onRefreshCallback = useCallback( (props: OnRefreshProps) => { @@ -157,19 +245,26 @@ const ExecutionLogTableComponent: React.FC = ({ [refetch] ); - const onSearchCallback = useCallback((updatedQueryText: string) => { - setQueryText(updatedQueryText); - }, []); + const onSearchCallback = useCallback( + (updatedQueryText: string) => { + setQueryText(updatedQueryText); + }, + [setQueryText] + ); - const onStatusFilterChangeCallback = useCallback((updatedStatusFilters: string[]) => { - setStatusFilters( - updatedStatusFilters.length ? updatedStatusFilters.sort().join(',') : undefined - ); - }, []); + const onStatusFilterChangeCallback = useCallback( + (updatedStatusFilters: RuleExecutionStatus[]) => { + setStatusFilters(updatedStatusFilters); + }, + [setStatusFilters] + ); const onFilterByExecutionIdCallback = useCallback( (executionId: string, executionStart: string) => { if (uuidDataViewField != null) { + // Update cached global query state with current state as a rollback point + cachedGlobalQueryState.current = { filters, query, timerange }; + // Create filter & daterange constraints const filter = buildFilter( indexPattern, uuidDataViewField, @@ -179,20 +274,55 @@ const ExecutionLogTableComponent: React.FC = ({ executionId, null ); + dispatch( + setAbsoluteRangeDatePicker({ + id: 'global', + from: moment(executionStart).subtract(1, 'days').toISOString(), + to: moment(executionStart).add(1, 'days').toISOString(), + }) + ); filterManager.removeAll(); filterManager.addFilters(filter); + dispatch(setFilterQuery({ id: 'global', query: '', language: 'kuery' })); selectAlertsTab(); - addSuccess({ - title: i18n.ACTIONS_SEARCH_FILTERS_HAVE_BEEN_UPDATED_TITLE, - text: i18n.ACTIONS_SEARCH_FILTERS_HAVE_BEEN_UPDATED_DESCRIPTION, - }); + successToastId.current = addSuccess( + { + title: i18n.ACTIONS_SEARCH_FILTERS_HAVE_BEEN_UPDATED_TITLE, + text: mountReactNode( + <> +

{i18n.ACTIONS_SEARCH_FILTERS_HAVE_BEEN_UPDATED_DESCRIPTION}

+ + + + {i18n.ACTIONS_SEARCH_FILTERS_HAVE_BEEN_UPDATED_RESTORE_BUTTON} + + + + + ), + }, + // Essentially keep toast around till user dismisses via 'x' + { toastLifeTimeMs: 10 * 60 * 1000 } + ).id; } else { addError(i18n.ACTIONS_FIELD_NOT_FOUND_ERROR, { title: i18n.ACTIONS_FIELD_NOT_FOUND_ERROR_TITLE, }); } }, - [addError, addSuccess, filterManager, indexPattern, selectAlertsTab, uuidDataViewField] + [ + addError, + addSuccess, + dispatch, + filterManager, + filters, + indexPattern, + query, + resetGlobalQueryState, + selectAlertsTab, + timerange, + uuidDataViewField, + ] ); const onShowMetricColumnsCallback = useCallback( @@ -200,7 +330,7 @@ const ExecutionLogTableComponent: React.FC = ({ storage.set(RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY, showMetrics); setShowMetricColumns(showMetrics); }, - [storage] + [setShowMetricColumns, storage] ); // Memoized state @@ -223,8 +353,6 @@ const ExecutionLogTableComponent: React.FC = ({ }; }, [sortDirection, sortField]); - // TODO: Re-add actions once alert count is displayed in table and UX is finalized - // @ts-expect-error unused constant const actions = useMemo( () => [ { @@ -258,9 +386,9 @@ const ExecutionLogTableComponent: React.FC = ({ const executionLogColumns = useMemo( () => showMetricColumns - ? [...EXECUTION_LOG_COLUMNS, ...GET_EXECUTION_LOG_METRICS_COLUMNS(docLinks)] - : [...EXECUTION_LOG_COLUMNS], - [docLinks, showMetricColumns] + ? [...EXECUTION_LOG_COLUMNS, ...GET_EXECUTION_LOG_METRICS_COLUMNS(docLinks), ...actions] + : [...EXECUTION_LOG_COLUMNS, ...actions], + [actions, docLinks, showMetricColumns] ); return ( @@ -271,6 +399,7 @@ const ExecutionLogTableComponent: React.FC = ({ onSearch={onSearchCallback} onStatusFilterChange={onStatusFilterChangeCallback} onlyShowFilters={true} + defaultSelectedStatusFilters={statusFilters} />
@@ -315,7 +444,7 @@ const ExecutionLogTableComponent: React.FC = ({ - + {timelines.getLastUpdated({ showUpdating: isLoading || isFetching, updatedAt: dataUpdatedAt, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.test.tsx index 44f765f934ae8..30e7d6e8f0a2e 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.test.tsx @@ -5,17 +5,82 @@ * 2.0. */ -import { shallow } from 'enzyme'; +import { render } from '@testing-library/react'; import React from 'react'; -import { RuleDurationFormat } from './rule_duration_format'; - -// TODO: Replace snapshot test with base test cases +import { getFormattedDuration, RuleDurationFormat } from './rule_duration_format'; describe('RuleDurationFormat', () => { - describe('snapshots', () => { - test('renders correctly against snapshot', () => { - const wrapper = shallow(); - expect(wrapper).toMatchSnapshot(); + describe('getFormattedDuration', () => { + test('if input value is 0, formatted response is also 0', () => { + const formattedDuration = getFormattedDuration(0); + expect(formattedDuration).toEqual('00:00:00:000'); + }); + + test('if input value only contains ms, formatted response also only contains ms (SSS)', () => { + const formattedDuration = getFormattedDuration(999); + expect(formattedDuration).toEqual('00:00:00:999'); + }); + + test('for milliseconds (SSS) to seconds (ss) overflow', () => { + const formattedDuration = getFormattedDuration(1000); + expect(formattedDuration).toEqual('00:00:01:000'); + }); + + test('for seconds (ss) to minutes (mm) overflow', () => { + const formattedDuration = getFormattedDuration(60000 + 1); + expect(formattedDuration).toEqual('00:01:00:001'); + }); + + test('for minutes (mm) to hours (hh) overflow', () => { + const formattedDuration = getFormattedDuration(60000 * 60 + 1); + expect(formattedDuration).toEqual('01:00:00:001'); + }); + + test('for hours (hh) to days (ddd) overflow', () => { + const formattedDuration = getFormattedDuration(60000 * 60 * 24 + 1); + expect(formattedDuration).toEqual('001:00:00:00:001'); + }); + + test('for overflow with all units up to hours (hh)', () => { + const formattedDuration = getFormattedDuration(25033167); + expect(formattedDuration).toEqual('06:57:13:167'); + }); + + test('for overflow with all units up to hours (ddd)', () => { + const formattedDuration = getFormattedDuration(2503316723); + expect(formattedDuration).toEqual('028:23:21:56:723'); + }); + + test('for overflow greater than a year', () => { + const formattedDuration = getFormattedDuration((60000 * 60 * 24 + 1) * 365); + expect(formattedDuration).toEqual('> 1 Year'); + }); + + test('for max overflow', () => { + const formattedDuration = getFormattedDuration(Number.MAX_SAFE_INTEGER); + expect(formattedDuration).toEqual('> 1 Year'); + }); + }); + + describe('RuleDurationFormatComponent', () => { + test('renders correctly with duration and no additional props', () => { + const { getByTestId } = render(); + expect(getByTestId('rule-duration-format-value')).toHaveTextContent('00:00:01:000'); + }); + + test('renders correctly with duration and isSeconds=true', () => { + const { getByTestId } = render(); + expect(getByTestId('rule-duration-format-value')).toHaveTextContent('00:00:01:000'); + }); + + test('renders correctly with allowZero=true', () => { + const { getByTestId } = render(); + expect(getByTestId('rule-duration-format-value')).toHaveTextContent('N/A'); + }); + + test('renders correctly with max overflow', () => { + const { getByTestId } = render(); + expect(getByTestId('rule-duration-format-value')).toHaveTextContent('> 1 Year'); }); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.tsx index cdbc19ce16c3b..c9f8e1d2734d8 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/rule_duration_format.tsx @@ -5,48 +5,59 @@ * 2.0. */ -import numeral from '@elastic/numeral'; import moment from 'moment'; import React, { useMemo } from 'react'; +import * as i18n from './translations'; + interface Props { duration: number; - isMillis?: boolean; + isSeconds?: boolean; allowZero?: boolean; } -export function getFormattedDuration(value: number) { +export const getFormattedDuration = (value: number) => { if (!value) { return '00:00:00:000'; } const duration = moment.duration(value); - const hours = Math.floor(duration.asHours()).toString().padStart(2, '0'); - const minutes = Math.floor(duration.asMinutes()).toString().padStart(2, '0'); + const days = Math.floor(duration.asDays()).toString().padStart(3, '0'); + const hours = Math.floor(duration.asHours() % 24) + .toString() + .padStart(2, '0'); + const minutes = Math.floor(duration.asMinutes() % 60) + .toString() + .padStart(2, '0'); const seconds = duration.seconds().toString().padStart(2, '0'); const ms = duration.milliseconds().toString().padStart(3, '0'); - return `${hours}:${minutes}:${seconds}:${ms}`; -} -export function getFormattedMilliseconds(value: number) { - const formatted = numeral(value).format('0,0'); - return `${formatted} ms`; -} + if (Math.floor(duration.asDays()) > 0) { + if (Math.floor(duration.asDays()) >= 365) { + return i18n.GREATER_THAN_YEAR; + } else { + return `${days}:${hours}:${minutes}:${seconds}:${ms}`; + } + } else { + return `${hours}:${minutes}:${seconds}:${ms}`; + } +}; /** - * Formats duration as (hh:mm:ss:SSS) - * @param props duration default as nanos, set isMillis:true to pass in ms + * Formats duration as (hh:mm:ss:SSS) by default, overflowing to include days + * as (ddd:hh:mm:ss:SSS) if necessary, and then finally to `> 1 Year` + * @param props duration as millis, set isSeconds:true to pass in seconds * @constructor */ const RuleDurationFormatComponent = (props: Props) => { - const { duration, isMillis = false, allowZero = true } = props; + const { duration, isSeconds = false, allowZero = true } = props; const formattedDuration = useMemo(() => { // Durations can be buggy and return negative if (allowZero && duration >= 0) { - return getFormattedDuration(isMillis ? duration * 1000 : duration); + return getFormattedDuration(isSeconds ? duration * 1000 : duration); } - return 'N/A'; - }, [allowZero, duration, isMillis]); + return i18n.DURATION_NOT_AVAILABLE; + }, [allowZero, duration, isSeconds]); return {formattedDuration}; }; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/translations.ts index d5d8d56664907..b161ae3662e0e 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/execution_log_table/translations.ts @@ -181,6 +181,13 @@ export const ACTIONS_SEARCH_FILTERS_HAVE_BEEN_UPDATED_DESCRIPTION = i18n.transla } ); +export const ACTIONS_SEARCH_FILTERS_HAVE_BEEN_UPDATED_RESTORE_BUTTON = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.actionSearchFiltersUpdatedRestoreButtonTitle', + { + defaultMessage: 'Restore previous filters', + } +); + export const ACTIONS_FIELD_NOT_FOUND_ERROR_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.actionFieldNotFoundErrorTitle', { @@ -194,3 +201,17 @@ export const ACTIONS_FIELD_NOT_FOUND_ERROR = i18n.translate( defaultMessage: "Cannot find field 'kibana.alert.rule.execution.uuid' in alerts index.", } ); + +export const DURATION_NOT_AVAILABLE = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.durationNotAvailableDescription', + { + defaultMessage: 'N/A', + } +); + +export const GREATER_THAN_YEAR = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.durationGreaterThanYearDescription', + { + defaultMessage: '> 1 Year', + } +); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index 8550d03eca2aa..cc8872b901f44 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -108,6 +108,7 @@ import { import * as detectionI18n from '../../translations'; import * as ruleI18n from '../translations'; import { ExecutionLogTable } from './execution_log_table/execution_log_table'; +import { RuleDetailsContextProvider } from './rule_details_context'; import * as i18n from './translations'; import { NeedAdminForUpdateRulesCallOut } from '../../../../components/callouts/need_admin_for_update_callout'; import { MissingPrivilegesCallOut } from '../../../../components/callouts/missing_privileges_callout'; @@ -131,7 +132,14 @@ const StyledFullHeightContainer = styled.div` flex: 1 1 auto; `; -enum RuleDetailTabs { +/** + * Sets min-height on tab container to minimize page hop when switching to tabs with less content + */ +const StyledMinHeightTabContainer = styled.div` + min-height: 800px; +`; + +export enum RuleDetailTabs { alerts = 'alerts', executionLogs = 'executionLogs', exceptions = 'exceptions', @@ -639,181 +647,186 @@ const RuleDetailsPageComponent: React.FC = ({ indexPattern={indexPattern} /> - - - - - - - {ruleStatusI18n.STATUS} - {':'} - - {ruleStatusInfo} - - - } - title={title} - badgeOptions={badgeOptions} - > - - - - - - {i18n.ENABLE_RULE} + + + + + + + {ruleStatusI18n.STATUS} + {':'} + + {ruleStatusInfo} - - - - - - {editRule} - - - - - - - - {ruleError} - {getLegacyUrlConflictCallout} - - - - - - - - - - - {defineRuleData != null && ( - + } + title={title} + badgeOptions={badgeOptions} + > + + + + + - )} - + {i18n.ENABLE_RULE} + + - - - - {scheduleRuleData != null && ( - + + {editRule} + + - )} - + + - - - - {tabs} - - - {ruleDetailTab === RuleDetailTabs.alerts && hasIndexRead && ( - <> - - - + {ruleError} + {getLegacyUrlConflictCallout} + + + + - - {updatedAt && - timelinesUi.getLastUpdated({ - updatedAt: updatedAt || Date.now(), - showUpdating, - })} + + + + + + {defineRuleData != null && ( + + )} + + + + + + {scheduleRuleData != null && ( + + )} + + + - - - - - - {ruleId != null && ( - + {tabs} + + + + {ruleDetailTab === RuleDetailTabs.alerts && hasIndexRead && ( + <> + + + + + + {updatedAt && + timelinesUi.getLastUpdated({ + updatedAt: updatedAt || Date.now(), + showUpdating, + })} + + + + + + + + {ruleId != null && ( + + )} + + )} + {ruleDetailTab === RuleDetailTabs.exceptions && ( + )} - - )} - {ruleDetailTab === RuleDetailTabs.exceptions && ( - - )} - {ruleDetailTab === RuleDetailTabs.executionLogs && ( - - )} - + {ruleDetailTab === RuleDetailTabs.executionLogs && ( + + )} + + + diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/rule_details_context.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/rule_details_context.tsx new file mode 100644 index 0000000000000..13b17d0493d43 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/rule_details_context.tsx @@ -0,0 +1,216 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SortOrder } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { DurationRange } from '@elastic/eui/src/components/date_picker/types'; +import React, { createContext, useContext, useMemo, useState } from 'react'; +import { RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY } from '../../../../../../common/constants'; +import { + AggregateRuleExecutionEvent, + RuleExecutionStatus, +} from '../../../../../../common/detection_engine/schemas/common'; +import { invariant } from '../../../../../../common/utils/invariant'; +import { useKibana } from '../../../../../common/lib/kibana'; +import { RuleDetailTabs } from '.'; + +export interface ExecutionLogTableState { + /** + * State of the SuperDatePicker component + */ + superDatePicker: { + /** + * DateRanges to display as recently used + */ + recentlyUsedRanges: DurationRange[]; + /** + * Interval to auto-refresh at + */ + refreshInterval: number; + /** + * State of auto-refresh + */ + isPaused: boolean; + /** + * Start datetime + */ + start: string; + /** + * End datetime + */ + end: string; + }; + /** + * SearchBar query + */ + queryText: string; + /** + * Selected Filters by Execution Status(es) + */ + statusFilters: RuleExecutionStatus[]; + /** + * Whether or not to show additional metric columnbs + */ + showMetricColumns: boolean; + /** + * Currently selected page and number of rows per page + */ + pagination: { + pageIndex: number; + pageSize: number; + }; + sort: { + sortField: keyof AggregateRuleExecutionEvent; + sortDirection: SortOrder; + }; +} + +// @ts-expect-error unused constant +const DEFAULT_STATE: ExecutionLogTableState = { + superDatePicker: { + recentlyUsedRanges: [], + refreshInterval: 1000, + isPaused: true, + start: 'now-24hr', + end: 'now', + }, + queryText: '', + statusFilters: [], + showMetricColumns: false, + pagination: { + pageIndex: 1, + pageSize: 5, + }, + sort: { + sortField: 'timestamp', + sortDirection: 'desc', + }, +}; + +export interface ExecutionLogTableActions { + setRecentlyUsedRanges: React.Dispatch>; + setRefreshInterval: React.Dispatch>; + setIsPaused: React.Dispatch>; + setStart: React.Dispatch>; + setEnd: React.Dispatch>; + setQueryText: React.Dispatch>; + setStatusFilters: React.Dispatch>; + setShowMetricColumns: React.Dispatch>; + setPageIndex: React.Dispatch>; + setPageSize: React.Dispatch>; + setSortField: React.Dispatch>; + setSortDirection: React.Dispatch>; +} + +export interface RuleDetailsContextType { + // TODO: Add section for RuleDetailTabs.exceptions and store query/pagination/etc. + // TODO: Let's discuss how to integration with ExceptionsViewerComponent state mgmt + [RuleDetailTabs.executionLogs]: { + state: ExecutionLogTableState; + actions: ExecutionLogTableActions; + }; +} + +const RuleDetailsContext = createContext(null); + +interface RuleDetailsContextProviderProps { + children: React.ReactNode; +} + +export const RuleDetailsContextProvider = ({ children }: RuleDetailsContextProviderProps) => { + const { storage } = useKibana().services; + + // Execution Log Table tab + // // SuperDatePicker State + const [recentlyUsedRanges, setRecentlyUsedRanges] = useState([]); + const [refreshInterval, setRefreshInterval] = useState(1000); + const [isPaused, setIsPaused] = useState(true); + const [start, setStart] = useState('now-24h'); + const [end, setEnd] = useState('now'); + // Searchbar/Filter/Settings state + const [queryText, setQueryText] = useState(''); + const [statusFilters, setStatusFilters] = useState([]); + const [showMetricColumns, setShowMetricColumns] = useState( + storage.get(RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY) ?? false + ); + // Pagination state + const [pageIndex, setPageIndex] = useState(1); + const [pageSize, setPageSize] = useState(5); + const [sortField, setSortField] = useState('timestamp'); + const [sortDirection, setSortDirection] = useState('desc'); + // // End Execution Log Table tab + + const providerValue = useMemo( + () => ({ + [RuleDetailTabs.executionLogs]: { + state: { + superDatePicker: { + recentlyUsedRanges, + refreshInterval, + isPaused, + start, + end, + }, + queryText, + statusFilters, + showMetricColumns, + pagination: { + pageIndex, + pageSize, + }, + sort: { + sortField, + sortDirection, + }, + }, + actions: { + setEnd, + setIsPaused, + setPageIndex, + setPageSize, + setQueryText, + setRecentlyUsedRanges, + setRefreshInterval, + setShowMetricColumns, + setSortDirection, + setSortField, + setStart, + setStatusFilters, + }, + }, + }), + [ + end, + isPaused, + pageIndex, + pageSize, + queryText, + recentlyUsedRanges, + refreshInterval, + showMetricColumns, + sortDirection, + sortField, + start, + statusFilters, + ] + ); + + return ( + {children} + ); +}; + +export const useRuleDetailsContext = (): RuleDetailsContextType => { + const ruleDetailsContext = useContext(RuleDetailsContext); + invariant( + ruleDetailsContext, + 'useRuleDetailsContext should be used inside RuleDetailsContextProvider' + ); + return ruleDetailsContext; +}; + +export const useRuleDetailsContextOptional = (): RuleDetailsContextType | null => + useContext(RuleDetailsContext); diff --git a/x-pack/plugins/security_solution/public/network/pages/network.test.tsx b/x-pack/plugins/security_solution/public/network/pages/network.test.tsx index a52c4e1560893..32ba03abe500b 100644 --- a/x-pack/plugins/security_solution/public/network/pages/network.test.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/network.test.tsx @@ -106,6 +106,7 @@ jest.mock('../../common/lib/kibana', () => { addError: jest.fn(), addSuccess: jest.fn(), addWarning: jest.fn(), + remove: jest.fn(), }), }; }); diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx index dd032016088b6..ee4af121dd054 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.test.tsx @@ -35,6 +35,7 @@ jest.mock('../../common/lib/kibana', () => ({ addError: jest.fn(), addSuccess: jest.fn(), addWarning: jest.fn(), + remove: jest.fn(), }), useKibana: jest.fn().mockReturnValue({ services: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts index e7f539d31ec0c..9f4670e3c252a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -577,7 +577,7 @@ export const getAggregateExecutionEvents = (): GetAggregateRuleExecutionEventsRe timed_out: false, indexing_duration_ms: 7, search_duration_ms: 551, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'succeeded', security_message: 'succeeded', }, @@ -600,7 +600,7 @@ export const getAggregateExecutionEvents = (): GetAggregateRuleExecutionEventsRe timed_out: false, indexing_duration_ms: 0, search_duration_ms: 0, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'partial failure', security_message: 'Check privileges failed to execute ResponseError: index_not_found_exception: [index_not_found_exception] Reason: no such index [broken-index] name: "This Rule Makes Alerts, Actions, AND Moar!" id: "f78f3550-a186-11ec-89a1-0bce95157aba" rule id: "b64b4540-d035-4826-a1e7-f505bf4b9653" execution id: "254d8400-9dc7-43c5-ad4b-227273d1a44b" space ID: "default"', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_rule_execution_events_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_rule_execution_events_route.test.ts index 37b1f41328674..c59a0e4dfe176 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_rule_execution_events_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_rule_execution_events_route.test.ts @@ -12,8 +12,6 @@ import { } from '../__mocks__/request_responses'; import { getRuleExecutionEventsRoute } from './get_rule_execution_events_route'; -// TODO: Add additional tests for param validation - describe('getRuleExecutionEventsRoute', () => { let server: ReturnType; let { clients, context } = requestContextMock.createTools(); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client_interface.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client_interface.ts index 8d0cae91f1987..3f353732abbc5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client_interface.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/client_for_routes/client_interface.ts @@ -9,7 +9,7 @@ import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ExecutionLogTableSortColumns, RuleExecutionEvent, - RuleExecutionStatusType, + RuleExecutionStatus, RuleExecutionSummary, } from '../../../../../common/detection_engine/schemas/common'; import { GetAggregateRuleExecutionEventsResponse } from '../../../../../common/detection_engine/schemas/response'; @@ -19,7 +19,7 @@ export interface GetAggregateExecutionEventsArgs { start: string; end: string; queryText: string; - statusFilters: RuleExecutionStatusType[]; + statusFilters: RuleExecutionStatus[]; page: number; perPage: number; sortField: ExecutionLogTableSortColumns; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/event_log_reader.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/event_log_reader.ts index 78e8e62702d47..20cc2f0e78c77 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/event_log_reader.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/event_log_reader.ts @@ -6,8 +6,8 @@ */ import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import { MAX_EXECUTION_EVENTS_DISPLAYED } from '@kbn/securitysolution-rules'; import { IEventLogClient } from '@kbn/event-log-plugin/server'; +import { MAX_EXECUTION_EVENTS_DISPLAYED } from '@kbn/securitysolution-rules'; import { RuleExecutionEvent, @@ -18,13 +18,14 @@ import { invariant } from '../../../../../common/utils/invariant'; import { withSecuritySpan } from '../../../../utils/with_security_span'; import { GetAggregateExecutionEventsArgs } from '../client_for_routes/client_interface'; import { - RULE_SAVED_OBJECT_TYPE, RULE_EXECUTION_LOG_PROVIDER, + RULE_SAVED_OBJECT_TYPE, RuleExecutionLogAction, } from './constants'; import { formatExecutionEventResponse, getExecutionEventAggregation, + mapRuleExecutionStatusToPlatformStatus, } from './get_execution_event_aggregation'; import { EXECUTION_UUID_FIELD, @@ -62,10 +63,15 @@ export const createEventLogReader = (eventLog: IEventLogClient): IEventLogReader let totalExecutions: number | undefined; // If 0 or 3 statuses are selected we can search for all statuses and don't need this pre-filter by ID if (statusFilters.length > 0 && statusFilters.length < 3) { + const outcomes = mapRuleExecutionStatusToPlatformStatus(statusFilters); + const outcomeFilter = outcomes.length ? `OR event.outcome:(${outcomes.join(' OR ')})` : ''; const statusResults = await eventLog.aggregateEventsBySavedObjectIds(soType, soIds, { start, end, - filter: `kibana.alert.rule.execution.status:(${statusFilters.join(' OR ')})`, + // Also query for `event.outcome` to catch executions that only contain platform events + filter: `kibana.alert.rule.execution.status:(${statusFilters.join( + ' OR ' + )}) ${outcomeFilter}`, aggs: { totalExecutions: { cardinality: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.test.ts index 7cee84cd64594..dcd592d7a70fc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.test.ts @@ -12,6 +12,7 @@ * 2.0. */ +import { RuleExecutionStatus } from '../../../../../../common/detection_engine/schemas/common'; import { MAX_EXECUTION_EVENTS_DISPLAYED } from '@kbn/securitysolution-rules'; import { @@ -20,6 +21,8 @@ import { formatSortForTermsSort, getExecutionEventAggregation, getProviderAndActionFilter, + mapPlatformStatusToRuleExecutionStatus, + mapRuleExecutionStatusToPlatformStatus, } from '.'; describe('getExecutionEventAggregation', () => { @@ -69,7 +72,7 @@ describe('getExecutionEventAggregation', () => { sort: [{ notsortable: { order: 'asc' } }], }); }).toThrowErrorMatchingInlineSnapshot( - `"Invalid sort field \\"notsortable\\" - must be one of [timestamp,duration_ms,indexing_duration_ms,search_duration_ms,gap_duration_ms,schedule_delay_ms,num_triggered_actions]"` + `"Invalid sort field \\"notsortable\\" - must be one of [timestamp,duration_ms,indexing_duration_ms,search_duration_ms,gap_duration_s,schedule_delay_ms,num_triggered_actions]"` ); }); @@ -82,7 +85,7 @@ describe('getExecutionEventAggregation', () => { sort: [{ notsortable: { order: 'asc' } }, { timestamp: { order: 'asc' } }], }); }).toThrowErrorMatchingInlineSnapshot( - `"Invalid sort field \\"notsortable\\" - must be one of [timestamp,duration_ms,indexing_duration_ms,search_duration_ms,gap_duration_ms,schedule_delay_ms,num_triggered_actions]"` + `"Invalid sort field \\"notsortable\\" - must be one of [timestamp,duration_ms,indexing_duration_ms,search_duration_ms,gap_duration_s,schedule_delay_ms,num_triggered_actions]"` ); }); @@ -206,7 +209,7 @@ describe('getExecutionEventAggregation', () => { top_hits: { size: 1, _source: { - includes: ['event.outcome', 'message'], + includes: ['error.message', 'event.outcome', 'message'], }, }, }, @@ -647,7 +650,7 @@ describe('formatExecutionEventResponse', () => { timed_out: false, indexing_duration_ms: 7, search_duration_ms: 480, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'succeeded', security_message: 'succeeded', }, @@ -670,7 +673,7 @@ describe('formatExecutionEventResponse', () => { timed_out: false, indexing_duration_ms: 0, search_duration_ms: 9, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'succeeded', security_message: 'succeeded', }, @@ -965,7 +968,7 @@ describe('formatExecutionEventResponse', () => { timed_out: true, indexing_duration_ms: 7, search_duration_ms: 480, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'succeeded', security_message: 'succeeded', }, @@ -988,7 +991,7 @@ describe('formatExecutionEventResponse', () => { timed_out: false, indexing_duration_ms: 0, search_duration_ms: 9, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'succeeded', security_message: 'succeeded', }, @@ -1288,7 +1291,7 @@ describe('formatExecutionEventResponse', () => { timed_out: true, indexing_duration_ms: 7, search_duration_ms: 480, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'succeeded', security_message: 'succeeded', }, @@ -1311,7 +1314,7 @@ describe('formatExecutionEventResponse', () => { timed_out: false, indexing_duration_ms: 0, search_duration_ms: 9, - gap_duration_ms: 0, + gap_duration_s: 0, security_status: 'succeeded', security_message: 'succeeded', }, @@ -1319,3 +1322,53 @@ describe('formatExecutionEventResponse', () => { }); }); }); + +describe('mapRuleStatusToPlatformStatus', () => { + test('should correctly translate empty array to empty array', () => { + expect(mapRuleExecutionStatusToPlatformStatus([])).toEqual([]); + }); + + test('should correctly translate RuleExecutionStatus.failed to `failure` platform status', () => { + expect(mapRuleExecutionStatusToPlatformStatus([RuleExecutionStatus.failed])).toEqual([ + 'failure', + ]); + }); + + test('should correctly translate RuleExecutionStatus.succeeded to `success` platform status', () => { + expect(mapRuleExecutionStatusToPlatformStatus([RuleExecutionStatus.succeeded])).toEqual([ + 'success', + ]); + }); + + test('should correctly translate RuleExecutionStatus.["going to run"] to empty array platform status', () => { + expect(mapRuleExecutionStatusToPlatformStatus([RuleExecutionStatus['going to run']])).toEqual( + [] + ); + }); + + test("should correctly translate multiple RuleExecutionStatus's to platform statuses", () => { + expect( + mapRuleExecutionStatusToPlatformStatus([ + RuleExecutionStatus.succeeded, + RuleExecutionStatus.failed, + RuleExecutionStatus['going to run'], + ]).sort() + ).toEqual(['failure', 'success']); + }); +}); + +describe('mapPlatformStatusToRuleExecutionStatus', () => { + test('should correctly translate `invalid` platform status to `undefined`', () => { + expect(mapPlatformStatusToRuleExecutionStatus('')).toEqual(undefined); + }); + + test('should correctly translate `failure` platform status to `RuleExecutionStatus.failed`', () => { + expect(mapPlatformStatusToRuleExecutionStatus('failure')).toEqual(RuleExecutionStatus.failed); + }); + + test('should correctly translate `success` platform status to `RuleExecutionStatus.succeeded`', () => { + expect(mapPlatformStatusToRuleExecutionStatus('success')).toEqual( + RuleExecutionStatus.succeeded + ); + }); +}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.ts index 4cf8e0bd5f1dc..dcf2fbfe911bd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_execution_log/event_log/get_execution_event_aggregation/index.ts @@ -10,7 +10,10 @@ import { BadRequestError } from '@kbn/securitysolution-es-utils'; import { flatMap, get } from 'lodash'; import { MAX_EXECUTION_EVENTS_DISPLAYED } from '@kbn/securitysolution-rules'; import { AggregateEventsBySavedObjectResult } from '@kbn/event-log-plugin/server'; -import { AggregateRuleExecutionEvent } from '../../../../../../common/detection_engine/schemas/common'; +import { + AggregateRuleExecutionEvent, + RuleExecutionStatus, +} from '../../../../../../common/detection_engine/schemas/common'; import { GetAggregateRuleExecutionEventsResponse } from '../../../../../../common/detection_engine/schemas/response'; import { ExecutionEventAggregationOptions, @@ -22,6 +25,7 @@ import { // Base ECS fields const ACTION_FIELD = 'event.action'; const DURATION_FIELD = 'event.duration'; +const ERROR_MESSAGE_FIELD = 'error.message'; const MESSAGE_FIELD = 'message'; const PROVIDER_FIELD = 'event.provider'; const OUTCOME_FIELD = 'event.outcome'; @@ -48,7 +52,7 @@ const SORT_FIELD_TO_AGG_MAPPING: Record = { duration_ms: 'ruleExecution>executionDuration', indexing_duration_ms: 'securityMetrics>indexDuration', search_duration_ms: 'securityMetrics>searchDuration', - gap_duration_ms: 'securityMetrics>gapDuration', + gap_duration_s: 'securityMetrics>gapDuration', schedule_delay_ms: 'ruleExecution>scheduleDelay', num_triggered_actions: 'ruleExecution>numTriggeredActions', // TODO: To be added in https://github.com/elastic/kibana/pull/126210 @@ -166,7 +170,7 @@ export const getExecutionEventAggregation = ({ top_hits: { size: 1, _source: { - includes: [OUTCOME_FIELD, MESSAGE_FIELD], + includes: [ERROR_MESSAGE_FIELD, OUTCOME_FIELD, MESSAGE_FIELD], }, }, }, @@ -293,11 +297,18 @@ export const formatAggExecutionEventFromBucket = ( // security fields indexing_duration_ms: bucket?.securityMetrics?.indexDuration?.value ?? 0, search_duration_ms: bucket?.securityMetrics?.searchDuration?.value ?? 0, - gap_duration_ms: bucket?.securityMetrics?.gapDuration?.value ?? 0, + gap_duration_s: bucket?.securityMetrics?.gapDuration?.value ?? 0, + // If security_status isn't available, use platform status from `event.outcome`, but translate to RuleExecutionStatus security_status: bucket?.securityStatus?.status?.hits?.hits[0]?._source?.kibana?.alert?.rule?.execution - ?.status, - security_message: bucket?.securityStatus?.message?.hits?.hits[0]?._source?.message, + ?.status ?? + mapPlatformStatusToRuleExecutionStatus( + bucket?.ruleExecution?.outcomeAndMessage?.hits?.hits[0]?._source?.event?.outcome + ), + // If security_message isn't available, use `error.message` instead for platform errors since it is more descriptive than `message` + security_message: + bucket?.securityStatus?.message?.hits?.hits[0]?._source?.message ?? + bucket?.ruleExecution?.outcomeAndMessage?.hits?.hits[0]?._source?.error?.message, }; }; @@ -353,3 +364,40 @@ export const formatSortForTermsSort = (sort: estypes.Sort) => { ) ); }; + +/** + * Maps a RuleExecutionStatus[] to string[] of associated platform statuses. Useful for querying specific platform + * events based on security status values + * @param ruleStatuses RuleExecutionStatus[] + */ +export const mapRuleExecutionStatusToPlatformStatus = ( + ruleStatuses: RuleExecutionStatus[] +): string[] => { + return flatMap(ruleStatuses, (rs) => { + switch (rs) { + case RuleExecutionStatus.failed: + return 'failure'; + case RuleExecutionStatus.succeeded: + return 'success'; + default: + return []; + } + }); +}; + +/** + * Maps a platform status string to RuleExecutionStatus + * @param platformStatus string, i.e. `failure` or `success` + */ +export const mapPlatformStatusToRuleExecutionStatus = ( + platformStatus: string +): RuleExecutionStatus | undefined => { + switch (platformStatus) { + case 'failure': + return RuleExecutionStatus.failed; + case 'success': + return RuleExecutionStatus.succeeded; + default: + return undefined; + } +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_rule_execution_events.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_rule_execution_events.ts index d3bddc8b0d46c..9fadbd39f7704 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_rule_execution_events.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_rule_execution_events.ts @@ -52,11 +52,6 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllEventLogExecutionEvents(es, log); }); - afterEach(async () => { - await deleteAllAlerts(supertest, log); - await deleteAllEventLogExecutionEvents(es, log); - }); - it('should return an error if rule does not exist', async () => { const start = dateMath.parse('now-24h')?.utc().toISOString(); const end = dateMath.parse('now', { roundUp: true })?.utc().toISOString(); @@ -90,7 +85,7 @@ export default ({ getService }: FtrProviderContext) => { expect(response.body.events[0].search_duration_ms).to.greaterThan(0); expect(response.body.events[0].schedule_delay_ms).to.greaterThan(0); expect(response.body.events[0].indexing_duration_ms).to.greaterThan(0); - expect(response.body.events[0].gap_duration_ms).to.eql(0); + expect(response.body.events[0].gap_duration_s).to.eql(0); expect(response.body.events[0].security_status).to.eql('succeeded'); expect(response.body.events[0].security_message).to.eql('succeeded'); }); @@ -114,7 +109,7 @@ export default ({ getService }: FtrProviderContext) => { expect(response.body.events[0].search_duration_ms).to.eql(0); expect(response.body.events[0].schedule_delay_ms).to.greaterThan(0); expect(response.body.events[0].indexing_duration_ms).to.eql(0); - expect(response.body.events[0].gap_duration_ms).to.eql(0); + expect(response.body.events[0].gap_duration_s).to.eql(0); expect(response.body.events[0].security_status).to.eql('partial failure'); expect( response.body.events[0].security_message.startsWith( @@ -123,16 +118,15 @@ export default ({ getService }: FtrProviderContext) => { ).to.eql(true); }); - // TODO: Debug indexing - it.skip('should return execution events for a rule that has executed in a failure state with a gap', async () => { + it('should return execution events for a rule that has executed in a failure state with a gap', async () => { const rule = getRuleForSignalTesting(['auditbeat-*'], uuid.v4(), false); const { id } = await createRule(supertest, log, rule); const start = dateMath.parse('now')?.utc().toISOString(); const end = dateMath.parse('now+24h', { roundUp: true })?.utc().toISOString(); - // Create 5 timestamps a minute apart to use in the templated data - const dateTimes = [...Array(5).keys()].map((i) => + // Create 5 timestamps (failedGapExecution.length) a minute apart to use in the templated data + const dateTimes = [...Array(failedGapExecution.length).keys()].map((i) => moment(start) .add(i + 1, 'm') .toDate() @@ -144,6 +138,7 @@ export default ({ getService }: FtrProviderContext) => { set(e, 'event.start', dateTimes[i]); set(e, 'event.end', dateTimes[i]); set(e, 'rule.id', id); + set(e, 'kibana.saved_objects[0].id', id); return e; }); @@ -155,73 +150,19 @@ export default ({ getService }: FtrProviderContext) => { .set('kbn-xsrf', 'true') .query({ start, end }); - // console.log(JSON.stringify(response)); - expect(response.status).to.eql(200); expect(response.body.total).to.eql(1); - expect(response.body.events[0].duration_ms).to.eql(4236); + expect(response.body.events[0].duration_ms).to.eql(1545); expect(response.body.events[0].search_duration_ms).to.eql(0); - expect(response.body.events[0].schedule_delay_ms).to.greaterThan(0); + expect(response.body.events[0].schedule_delay_ms).to.eql(544808); expect(response.body.events[0].indexing_duration_ms).to.eql(0); - expect(response.body.events[0].gap_duration_ms).to.greaterThan(0); + expect(response.body.events[0].gap_duration_s).to.eql(245); expect(response.body.events[0].security_status).to.eql('failed'); expect( response.body.events[0].security_message.startsWith( - 'Check privileges failed to execute ResponseError: index_not_found_exception: [index_not_found_exception] Reason: no such index [no-name-index]' + '4 minutes (244689ms) 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.' ) ).to.eql(true); }); - - // it('should return execution events when providing a status filter', async () => { - // const rule = getRuleForSignalTesting(['auditbeat-*', 'no-name-index']); - // const { id } = await createRule(supertest, log, rule); - // await waitForRuleSuccessOrStatus(supertest, log, id, RuleExecutionStatus.failed); - // await waitForSignalsToBePresent(supertest, log, 1, [id]); - // - // const start = dateMath.parse('now-24h')?.utc().toISOString(); - // const end = dateMath.parse('now', { roundUp: true })?.utc().toISOString(); - // const response = await supertest - // .get(detectionEngineRuleExecutionEventsUrl(id)) - // .set('kbn-xsrf', 'true') - // .query({ start, end }); - // - // expect(response.status).to.eql(200); - // expect(response.body.total).to.eql(1); - // expect(response.body.events[0].duration_ms).to.greaterThan(0); - // expect(response.body.events[0].search_duration_ms).to.eql(0); - // expect(response.body.events[0].schedule_delay_ms).to.greaterThan(0); - // expect(response.body.events[0].indexing_duration_ms).to.eql(0); - // expect(response.body.events[0].gap_duration_ms).to.eql(0); - // expect(response.body.events[0].security_status).to.eql('failed'); - // expect(response.body.events[0].security_message).to.include( - // 'were not queried between this rule execution and the last execution, so signals may have been missed. ' - // ); - // }); - - // it('should return execution events when providing a status filter and sortField', async () => { - // const rule = getRuleForSignalTesting(['auditbeat-*', 'no-name-index']); - // const { id } = await createRule(supertest, log, rule); - // await waitForRuleSuccessOrStatus(supertest, log, id, RuleExecutionStatus.failed); - // await waitForSignalsToBePresent(supertest, log, 1, [id]); - // - // const start = dateMath.parse('now-24h')?.utc().toISOString(); - // const end = dateMath.parse('now', { roundUp: true })?.utc().toISOString(); - // const response = await supertest - // .get(detectionEngineRuleExecutionEventsUrl(id)) - // .set('kbn-xsrf', 'true') - // .query({ start, end }); - // - // expect(response.status).to.eql(200); - // expect(response.body.total).to.eql(1); - // expect(response.body.events[0].duration_ms).to.greaterThan(0); - // expect(response.body.events[0].search_duration_ms).to.eql(0); - // expect(response.body.events[0].schedule_delay_ms).to.greaterThan(0); - // expect(response.body.events[0].indexing_duration_ms).to.eql(0); - // expect(response.body.events[0].gap_duration_ms).to.eql(0); - // expect(response.body.events[0].security_status).to.eql('failed'); - // expect(response.body.events[0].security_message).to.include( - // 'were not queried between this rule execution and the last execution, so signals may have been missed. ' - // ); - // }); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/template_data/execution_events.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/template_data/execution_events.ts index c4767bbcc5632..4a674c52fa1ed 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/template_data/execution_events.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/template_data/execution_events.ts @@ -5,6 +5,20 @@ * 2.0. */ +/** + * When using these execution events as templates be sure to replace all the following fields with their updated values + * + * E.g. + * set(e, '@timestamp', dateTimes[i]); + * set(e, 'event.start', dateTimes[i]); + * set(e, 'event.end', dateTimes[i]); + * set(e, 'rule.id', id); + * set(e, 'kibana.saved_objects[0].id', id); + */ + +/** + * Rule executed without issue + */ export const successfulExecution = [ { '@timestamp': '2022-03-17T22:59:31.360Z', @@ -226,30 +240,24 @@ export const successfulExecution = [ }, ]; +/** + * Rule execution identified gap since last execution + */ export const failedGapExecution = [ { - '@timestamp': '2022-03-17T12:36:16.413Z', + '@timestamp': '2022-03-17T12:36:14.868Z', event: { provider: 'alerting', - action: 'execute', + action: 'execute-start', kind: 'alert', category: ['siem'], start: '2022-03-17T12:36:14.868Z', - outcome: 'success', - end: '2022-03-17T12:36:16.413Z', - duration: 1545000000, }, kibana: { alert: { rule: { execution: { uuid: '38fa2d4a-94d3-4ea3-80d6-d1284eb98357', - metrics: { - number_of_triggered_actions: 0, - number_of_searches: 6, - es_search_duration_ms: 2, - total_search_duration_ms: 15, - }, }, }, }, @@ -265,9 +273,6 @@ export const failedGapExecution = [ scheduled: '2022-03-17T12:27:10.060Z', schedule_delay: 544808000000, }, - alerting: { - status: 'ok', - }, server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', version: '8.2.0', }, @@ -276,22 +281,21 @@ export const failedGapExecution = [ license: 'basic', category: 'siem.queryRule', ruleset: 'siem', - name: 'Lots of Execution Events', }, - message: - "rule executed: siem.queryRule:fb1fc150-a292-11ec-a2cf-c1b28b0392b0: 'Lots of Execution Events'", + message: 'rule execution start: "fb1fc150-a292-11ec-a2cf-c1b28b0392b0"', ecs: { version: '1.8.0', }, }, { - '@timestamp': '2022-03-17T12:36:15.382Z', + '@timestamp': '2022-03-17T12:36:14.888Z', event: { provider: 'securitySolution.ruleExecution', - kind: 'metric', - action: 'execution-metrics', - sequence: 1, + kind: 'event', + action: 'status-change', + sequence: 0, }, + message: '', rule: { id: 'fb1fc150-a292-11ec-a2cf-c1b28b0392b0', name: 'Lots of Execution Events', @@ -301,9 +305,8 @@ export const failedGapExecution = [ alert: { rule: { execution: { - metrics: { - execution_gap_duration_s: 245, - }, + status: 'running', + status_order: 15, uuid: '38fa2d4a-94d3-4ea3-80d6-d1284eb98357', }, }, @@ -364,14 +367,13 @@ export const failedGapExecution = [ }, }, { - '@timestamp': '2022-03-17T12:36:14.888Z', + '@timestamp': '2022-03-17T12:36:15.382Z', event: { provider: 'securitySolution.ruleExecution', - kind: 'event', - action: 'status-change', - sequence: 0, + kind: 'metric', + action: 'execution-metrics', + sequence: 1, }, - message: '', rule: { id: 'fb1fc150-a292-11ec-a2cf-c1b28b0392b0', name: 'Lots of Execution Events', @@ -381,8 +383,9 @@ export const failedGapExecution = [ alert: { rule: { execution: { - status: 'running', - status_order: 15, + metrics: { + execution_gap_duration_s: 245, + }, uuid: '38fa2d4a-94d3-4ea3-80d6-d1284eb98357', }, }, @@ -403,19 +406,28 @@ export const failedGapExecution = [ }, }, { - '@timestamp': '2022-03-17T12:36:14.868Z', + '@timestamp': '2022-03-17T12:36:16.413Z', event: { provider: 'alerting', - action: 'execute-start', + action: 'execute', kind: 'alert', category: ['siem'], start: '2022-03-17T12:36:14.868Z', + outcome: 'success', + end: '2022-03-17T12:36:16.413Z', + duration: 1545000000, }, kibana: { alert: { rule: { execution: { uuid: '38fa2d4a-94d3-4ea3-80d6-d1284eb98357', + metrics: { + number_of_triggered_actions: 0, + number_of_searches: 6, + es_search_duration_ms: 2, + total_search_duration_ms: 15, + }, }, }, }, @@ -431,6 +443,9 @@ export const failedGapExecution = [ scheduled: '2022-03-17T12:27:10.060Z', schedule_delay: 544808000000, }, + alerting: { + status: 'ok', + }, server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', version: '8.2.0', }, @@ -439,14 +454,19 @@ export const failedGapExecution = [ license: 'basic', category: 'siem.queryRule', ruleset: 'siem', + name: 'Lots of Execution Events', }, - message: 'rule execution start: "fb1fc150-a292-11ec-a2cf-c1b28b0392b0"', + message: + "rule executed: siem.queryRule:fb1fc150-a292-11ec-a2cf-c1b28b0392b0: 'Lots of Execution Events'", ecs: { version: '1.8.0', }, }, ]; +/** + * Rule execution resulted in partial warning, e.g. missing index pattern + */ export const partialWarningExecution = [ { '@timestamp': '2022-03-16T23:28:36.012Z', @@ -628,3 +648,112 @@ export const partialWarningExecution = [ }, }, ]; + +/** + * Rule execution failed because rule is disabled (configure 1s interval/lookback then rule + * is disabled while running) + */ +export const failedRanAfterDisabled = [ + { + '@timestamp': '2022-04-21T02:00:55.400Z', + event: { + provider: 'alerting', + action: 'execute', + kind: 'alert', + category: ['siem'], + start: '2022-04-21T02:00:55.397Z', + end: '2022-04-21T02:00:55.400Z', + duration: 3000000, + reason: 'disabled', + outcome: 'failure', + }, + kibana: { + alert: { + rule: { + rule_type_id: 'siem.queryRule', + consumer: 'siem', + execution: { + uuid: '50eb8b2e-8334-4387-b77f-d47fdb7fbe2d', + }, + }, + }, + saved_objects: [ + { + rel: 'primary', + type: 'alert', + id: 'a890e240-b9fb-11ec-8598-338317271cf4', + type_id: 'siem.queryRule', + }, + ], + space_ids: ['default'], + task: { + scheduled: '2022-04-21T02:00:53.325Z', + schedule_delay: 2072000000, + }, + alerting: { + status: 'error', + }, + server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', + version: '8.3.0', + }, + rule: { + id: 'a890e240-b9fb-11ec-8598-338317271cf4', + license: 'basic', + category: 'siem.queryRule', + ruleset: 'siem', + }, + error: { + message: 'Rule failed to execute because rule ran after it was disabled.', + }, + message: 'siem.queryRule:a890e240-b9fb-11ec-8598-338317271cf4: execution failed', + ecs: { + version: '1.8.0', + }, + }, + { + '@timestamp': '2022-04-21T02:00:55.397Z', + event: { + provider: 'alerting', + action: 'execute-start', + kind: 'alert', + category: ['siem'], + start: '2022-04-21T02:00:55.397Z', + }, + kibana: { + alert: { + rule: { + rule_type_id: 'siem.queryRule', + consumer: 'siem', + execution: { + uuid: '50eb8b2e-8334-4387-b77f-d47fdb7fbe2d', + }, + }, + }, + saved_objects: [ + { + rel: 'primary', + type: 'alert', + id: 'a890e240-b9fb-11ec-8598-338317271cf4', + type_id: 'siem.queryRule', + }, + ], + space_ids: ['default'], + task: { + scheduled: '2022-04-21T02:00:53.325Z', + schedule_delay: 2072000000, + }, + server_uuid: '5b2de169-2785-441b-ae8c-186a1936b17d', + version: '8.3.0', + }, + rule: { + id: 'a890e240-b9fb-11ec-8598-338317271cf4', + license: 'basic', + category: 'siem.queryRule', + ruleset: 'siem', + }, + message: 'rule execution start: "a890e240-b9fb-11ec-8598-338317271cf4"', + ecs: { + version: '1.8.0', + }, + }, +]; diff --git a/x-pack/test/detection_engine_api_integration/utils/index_event_log_execution_events.ts b/x-pack/test/detection_engine_api_integration/utils/index_event_log_execution_events.ts index 63f8c9f2c8e1b..8e354607d4002 100644 --- a/x-pack/test/detection_engine_api_integration/utils/index_event_log_execution_events.ts +++ b/x-pack/test/detection_engine_api_integration/utils/index_event_log_execution_events.ts @@ -19,8 +19,9 @@ export const indexEventLogExecutionEvents = async ( log: ToolingLog, events: object[] ): Promise => { + const aliases = await es.cat.aliases({ format: 'json', name: '.kibana-event-log-*' }); const operations = events.flatMap((doc: object) => [ - { index: { _index: '.kibana-event-log-*' } }, + { index: { _index: aliases[0].index } }, doc, ]); From 490bee238bea4f9ebddcedf9bc9272be4db0d3fc Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Wed, 4 May 2022 13:43:54 -0600 Subject: [PATCH 49/68] [ML] Anomaly Detection: Adds View in Maps item to Actions menu in the anomalies table (#131284) * add link to actions menu in anomalies table * set map start time to bucket start * simplify isGeoRecord value setting * lint fix * adds query and timerange to link * substract ms so as not to go into next bucket start time * lint fix --- x-pack/plugins/ml/common/types/anomalies.ts | 5 + .../anomalies_table_columns.js | 4 +- .../components/anomalies_table/links_menu.tsx | 94 +++++++++++++++---- .../explorer_charts_container.js | 61 +----------- .../application/explorer/explorer_utils.ts | 3 + .../maps/anomaly_layer_wizard_factory.tsx | 15 +-- x-pack/plugins/ml/public/maps/util.ts | 77 +++++++++++++++ 7 files changed, 168 insertions(+), 91 deletions(-) diff --git a/x-pack/plugins/ml/common/types/anomalies.ts b/x-pack/plugins/ml/common/types/anomalies.ts index 58d5e9df130af..9b6218e8c3f34 100644 --- a/x-pack/plugins/ml/common/types/anomalies.ts +++ b/x-pack/plugins/ml/common/types/anomalies.ts @@ -278,6 +278,11 @@ export interface AnomaliesTableRecord { * which can be plotted by the ML UI in an anomaly chart. */ isTimeSeriesViewRecord?: boolean; + + /** + * Returns true if the anomaly record represented by the table row can be shown in the maps plugin + */ + isGeoRecord?: boolean; } export type PartitionFieldsType = typeof PARTITION_FIELDS[number]; diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js b/x-pack/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js index 9e84dccf12b28..c24e294b54a5d 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js @@ -18,6 +18,7 @@ import { formatHumanReadableDateTime, formatHumanReadableDateTimeSeconds, } from '../../../../common/util/date_utils'; +import { ML_JOB_AGGREGATION } from '../../../../common/constants/aggregation_types'; import { DescriptionCell } from './description_cell'; import { DetectorCell } from './detector_cell'; @@ -47,7 +48,8 @@ function showLinksMenuForItem(item, showViewSeriesLink) { canConfigureRules || (showViewSeriesLink && item.isTimeSeriesViewRecord) || item.entityName === 'mlcategory' || - item.customUrls !== undefined + item.customUrls !== undefined || + item.detector.includes(ML_JOB_AGGREGATION.LAT_LONG) ); } diff --git a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx index cb299ee9dba33..ac67dbe35d9ec 100644 --- a/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx +++ b/x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.tsx @@ -8,7 +8,9 @@ import { cloneDeep } from 'lodash'; import moment from 'moment'; import rison, { RisonValue } from 'rison-node'; +import { escapeKuery } from '@kbn/es-query'; import React, { FC, useEffect, useMemo, useState } from 'react'; +import { APP_ID as MAPS_APP_ID } from '@kbn/maps-plugin/common'; import { EuiButtonIcon, EuiContextMenuItem, @@ -20,8 +22,10 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { ES_FIELD_TYPES } from '@kbn/field-types'; +import { MAPS_APP_LOCATOR } from '@kbn/maps-plugin/public'; import { mlJobService } from '../../services/job_service'; import { getDataViewIdFromName } from '../../util/index_utils'; +import { getInitialAnomaliesLayers } from '../../../maps/util'; import { formatHumanReadableDateTimeSeconds, timeFormatter, @@ -33,7 +37,7 @@ import { getUrlForRecord, openCustomUrlWindow } from '../../util/custom_url_util import { ML_APP_LOCATOR, ML_PAGES } from '../../../../common/constants/locator'; import { SEARCH_QUERY_LANGUAGE } from '../../../../common/constants/search'; // @ts-ignore -import { escapeDoubleQuotes } from '../../explorer/explorer_utils'; +import { escapeDoubleQuotes, getDateFormatTz } from '../../explorer/explorer_utils'; import { isCategorizationAnomaly, isRuleSupported } from '../../../../common/util/anomaly_utils'; import { checkPermission } from '../../capabilities/check_capabilities'; import type { @@ -49,6 +53,7 @@ import type { AnomaliesTableRecord } from '../../../../common/types/anomalies'; interface LinksMenuProps { anomaly: AnomaliesTableRecord; bounds: TimeRangeBounds; + showMapsLink: boolean; showViewSeriesLink: boolean; isAggregatedData: boolean; interval: 'day' | 'hour' | 'second'; @@ -66,9 +71,39 @@ export const LinksMenuUI = (props: LinksMenuProps) => { const kibana = useMlKibana(); const { - services: { share, application }, + services: { data, share, application }, } = kibana; + const getMapsLink = async (anomaly: AnomaliesTableRecord) => { + const initialLayers = getInitialAnomaliesLayers(anomaly.jobId); + const anomalyBucketStartMoment = moment(anomaly.time).tz(getDateFormatTz()); + const anomalyBucketStart = anomalyBucketStartMoment.toISOString(); + const anomalyBucketEnd = anomalyBucketStartMoment + .add(anomaly.source.bucket_span, 'seconds') + .subtract(1, 'ms') + .toISOString(); + const timeRange = data.query.timefilter.timefilter.getTime(); + + // Set 'from' in timeRange to start bucket time for the specific anomaly + timeRange.from = anomalyBucketStart; + timeRange.to = anomalyBucketEnd; + + const locator = share.url.locators.get(MAPS_APP_LOCATOR); + const location = await locator?.getLocation({ + initialLayers, + timeRange, + ...(anomaly.entityName && anomaly.entityValue + ? { + query: { + language: SEARCH_QUERY_LANGUAGE.KUERY, + query: `${escapeKuery(anomaly.entityName)}:${escapeKuery(anomaly.entityValue)}`, + }, + } + : {}), + }); + return location; + }; + useEffect(() => { let unmounted = false; const discoverLocator = share.url.locators.get('DISCOVER_APP_LOCATOR'); @@ -561,23 +596,44 @@ export const LinksMenuUI = (props: LinksMenuProps) => { ); } - if (showViewSeriesLink === true && anomaly.isTimeSeriesViewRecord === true) { - items.push( - { - closePopover(); - viewSeries(); - }} - data-test-subj="mlAnomaliesListRowActionViewSeriesButton" - > - - - ); + if (showViewSeriesLink === true) { + if (anomaly.isTimeSeriesViewRecord) { + items.push( + { + closePopover(); + viewSeries(); + }} + data-test-subj="mlAnomaliesListRowActionViewSeriesButton" + > + + + ); + } + + if (anomaly.isGeoRecord === true) { + items.push( + { + const mapsLink = await getMapsLink(anomaly); + await application.navigateToApp(MAPS_APP_ID, { path: mapsLink?.path }); + }} + data-test-subj="mlAnomaliesListRowActionViewInMapsButton" + > + + + ); + } } if (application.capabilities.discover?.show && isCategorizationAnomalyRecord) { diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js index ddaaa55e7a3a4..d3dc2681cf4c5 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container.js @@ -16,7 +16,6 @@ import { EuiFlexItem, EuiIconTip, EuiToolTip, - htmlIdGenerator, } from '@elastic/eui'; import { @@ -36,15 +35,13 @@ import { MlTooltipComponent } from '../../components/chart_tooltip'; import { withKibana } from '@kbn/kibana-react-plugin/public'; import { useMlKibana } from '../../contexts/kibana'; import { ML_JOB_AGGREGATION } from '../../../../common/constants/aggregation_types'; -import { AnomalySource } from '../../../maps/anomaly_source'; -import { CUSTOM_COLOR_RAMP } from '../../../maps/anomaly_layer_wizard_factory'; -import { LAYER_TYPE, APP_ID as MAPS_APP_ID } from '@kbn/maps-plugin/common'; +import { getInitialAnomaliesLayers } from '../../../maps/util'; +import { APP_ID as MAPS_APP_ID } from '@kbn/maps-plugin/common'; import { MAPS_APP_LOCATOR } from '@kbn/maps-plugin/public'; import { ExplorerChartsErrorCallOuts } from './explorer_charts_error_callouts'; import { addItemToRecentlyAccessed } from '../../util/recently_accessed'; import { EmbeddedMapComponentWrapper } from './explorer_chart_embedded_map'; import { useActiveCursor } from '@kbn/charts-plugin/public'; -import { ML_ANOMALY_LAYERS } from '../../../maps/util'; import { Chart, Settings } from '@elastic/charts'; import useObservable from 'react-use/lib/useObservable'; @@ -114,59 +111,7 @@ function ExplorerChartContainer({ const getMapsLink = useCallback(async () => { const { queryString, query } = getEntitiesQuery(series); - const initialLayers = []; - const typicalStyle = { - type: 'VECTOR', - properties: { - fillColor: { - type: 'STATIC', - options: { - color: '#98A2B2', - }, - }, - lineColor: { - type: 'STATIC', - options: { - color: '#fff', - }, - }, - lineWidth: { - type: 'STATIC', - options: { - size: 2, - }, - }, - iconSize: { - type: 'STATIC', - options: { - size: 6, - }, - }, - }, - }; - - const style = { - type: 'VECTOR', - properties: { - fillColor: CUSTOM_COLOR_RAMP, - lineColor: CUSTOM_COLOR_RAMP, - }, - isTimeAware: false, - }; - - for (const layer in ML_ANOMALY_LAYERS) { - if (ML_ANOMALY_LAYERS.hasOwnProperty(layer)) { - initialLayers.push({ - id: htmlIdGenerator()(), - type: LAYER_TYPE.GEOJSON_VECTOR, - sourceDescriptor: AnomalySource.createDescriptor({ - jobId: series.jobId, - typicalActual: ML_ANOMALY_LAYERS[layer], - }), - style: ML_ANOMALY_LAYERS[layer] === ML_ANOMALY_LAYERS.TYPICAL ? typicalStyle : style, - }); - } - } + const initialLayers = getInitialAnomaliesLayers(series.jobId); const locator = share.url.locators.get(MAPS_APP_LOCATOR); const location = await locator.getLocation({ diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_utils.ts b/x-pack/plugins/ml/public/application/explorer/explorer_utils.ts index d2c7c3f1fe2d2..6aa3444c9caaf 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_utils.ts +++ b/x-pack/plugins/ml/public/application/explorer/explorer_utils.ts @@ -19,6 +19,7 @@ import { } from '../../../common/constants/search'; import { EntityField, getEntityFieldList } from '../../../common/util/anomaly_utils'; import { extractErrorMessage } from '../../../common/util/errors'; +import { ML_JOB_AGGREGATION } from '../../../common/constants/aggregation_types'; import { isSourceDataChartableForDetector, isModelPlotChartableForDetector, @@ -495,6 +496,8 @@ export async function loadAnomaliesTableData( } anomaly.isTimeSeriesViewRecord = isChartable; + anomaly.isGeoRecord = + detector !== undefined && detector.function === ML_JOB_AGGREGATION.LAT_LONG; if (mlJobService.customUrlsByJob[jobId] !== undefined) { anomaly.customUrls = mlJobService.customUrlsByJob[jobId]; diff --git a/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx b/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx index b40a08fadd128..6b9ee6c2e6332 100644 --- a/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx +++ b/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx @@ -11,13 +11,13 @@ import type { StartServicesAccessor } from '@kbn/core/public'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { SerializableRecord } from '@kbn/utility-types'; import type { LayerWizard, RenderWizardArguments } from '@kbn/maps-plugin/public'; -import { FIELD_ORIGIN, LAYER_TYPE, STYLE_TYPE } from '@kbn/maps-plugin/common'; +import { LAYER_TYPE } from '@kbn/maps-plugin/common'; import { VectorLayerDescriptor, VectorStylePropertiesDescriptor, } from '@kbn/maps-plugin/common/descriptor_types'; -import { SEVERITY_COLOR_RAMP } from '../../common'; import { ML_APP_LOCATOR, ML_PAGES } from '../../common/constants/locator'; +import { CUSTOM_COLOR_RAMP } from './util'; import { CreateAnomalySourceEditor } from './create_anomaly_source_editor'; import { AnomalySource, AnomalySourceDescriptor } from './anomaly_source'; @@ -26,17 +26,6 @@ import type { MlPluginStart, MlStartDependencies } from '../plugin'; import type { MlApiServices } from '../application/services/ml_api_service'; export const ML_ANOMALY = 'ML_ANOMALIES'; -export const CUSTOM_COLOR_RAMP = { - type: STYLE_TYPE.DYNAMIC, - options: { - customColorRamp: SEVERITY_COLOR_RAMP, - field: { - name: 'record_score', - origin: FIELD_ORIGIN.SOURCE, - }, - useCustomColorRamp: true, - }, -}; export class AnomalyLayerWizardFactory { public readonly type = ML_ANOMALY; diff --git a/x-pack/plugins/ml/public/maps/util.ts b/x-pack/plugins/ml/public/maps/util.ts index c1cb3f9efaead..88e9994d303a9 100644 --- a/x-pack/plugins/ml/public/maps/util.ts +++ b/x-pack/plugins/ml/public/maps/util.ts @@ -7,14 +7,19 @@ import { FeatureCollection, Feature, Geometry } from 'geojson'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { htmlIdGenerator } from '@elastic/eui'; +import { FIELD_ORIGIN, STYLE_TYPE } from '@kbn/maps-plugin/common'; import { fromKueryExpression, luceneStringToDsl, toElasticsearchQuery } from '@kbn/es-query'; import { ESSearchResponse } from '@kbn/core/types/elasticsearch'; import { VectorSourceRequestMeta } from '@kbn/maps-plugin/common'; +import { LAYER_TYPE } from '@kbn/maps-plugin/common'; +import { SEVERITY_COLOR_RAMP } from '../../common'; import { formatHumanReadableDateTimeSeconds } from '../../common/util/date_utils'; import type { MlApiServices } from '../application/services/ml_api_service'; import { MLAnomalyDoc } from '../../common/types/anomalies'; import { SEARCH_QUERY_LANGUAGE } from '../../common/constants/search'; import { getIndexPattern } from '../application/explorer/reducers/explorer_reducer/get_index_pattern'; +import { AnomalySource } from './anomaly_source'; export const ML_ANOMALY_LAYERS = { TYPICAL: 'typical', @@ -22,6 +27,57 @@ export const ML_ANOMALY_LAYERS = { TYPICAL_TO_ACTUAL: 'typical to actual', } as const; +export const CUSTOM_COLOR_RAMP = { + type: STYLE_TYPE.DYNAMIC, + options: { + customColorRamp: SEVERITY_COLOR_RAMP, + field: { + name: 'record_score', + origin: FIELD_ORIGIN.SOURCE, + }, + useCustomColorRamp: true, + }, +}; + +export const ACTUAL_STYLE = { + type: 'VECTOR', + properties: { + fillColor: CUSTOM_COLOR_RAMP, + lineColor: CUSTOM_COLOR_RAMP, + }, + isTimeAware: false, +}; + +export const TYPICAL_STYLE = { + type: 'VECTOR', + properties: { + fillColor: { + type: 'STATIC', + options: { + color: '#98A2B2', + }, + }, + lineColor: { + type: 'STATIC', + options: { + color: '#fff', + }, + }, + lineWidth: { + type: 'STATIC', + options: { + size: 2, + }, + }, + iconSize: { + type: 'STATIC', + options: { + size: 6, + }, + }, + }, +}; + export type MlAnomalyLayersType = typeof ML_ANOMALY_LAYERS[keyof typeof ML_ANOMALY_LAYERS]; // Must reverse coordinates here. Map expects [lon, lat] - anomalies are stored as [lat, lon] for lat_lon jobs @@ -32,6 +88,27 @@ function getCoordinates(latLonString: string): number[] { .reverse(); } +export function getInitialAnomaliesLayers(jobId: string) { + const initialLayers = []; + for (const layer in ML_ANOMALY_LAYERS) { + if (ML_ANOMALY_LAYERS.hasOwnProperty(layer)) { + initialLayers.push({ + id: htmlIdGenerator()(), + type: LAYER_TYPE.GEOJSON_VECTOR, + sourceDescriptor: AnomalySource.createDescriptor({ + jobId, + typicalActual: ML_ANOMALY_LAYERS[layer as keyof typeof ML_ANOMALY_LAYERS], + }), + style: + ML_ANOMALY_LAYERS[layer as keyof typeof ML_ANOMALY_LAYERS] === ML_ANOMALY_LAYERS.TYPICAL + ? TYPICAL_STYLE + : ACTUAL_STYLE, + }); + } + } + return initialLayers; +} + export async function getResultsForJobId( mlResultsService: MlApiServices['results'], jobId: string, From 2d896d7c27c76d5646f17ae6b5e553cad73540f7 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Wed, 4 May 2022 12:45:45 -0700 Subject: [PATCH 50/68] [DOCS] Fix broken blob attributes (#131563) --- docs/index.asciidoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/index.asciidoc b/docs/index.asciidoc index 668a6edcad3db..41321f991c1b0 100644 --- a/docs/index.asciidoc +++ b/docs/index.asciidoc @@ -11,7 +11,6 @@ include::{docs-root}/shared/versions/stack/{source_branch}.asciidoc[] :docker-image: {docker-repo}:{version} :es-docker-repo: docker.elastic.co/elasticsearch/elasticsearch :es-docker-image: {es-docker-repo}:{version} -:blob: {kib-repo}blob/{branch}/ :security-ref: https://www.elastic.co/community/security/ :Data-source: Data view :data-source: data view @@ -20,6 +19,8 @@ include::{docs-root}/shared/versions/stack/{source_branch}.asciidoc[] include::{docs-root}/shared/attributes.asciidoc[] +:blob: {kib-repo}blob/{branch}/ + include::user/index.asciidoc[] include::accessibility.asciidoc[] From 6f0e4fab800ad3295416a37047a826af46718777 Mon Sep 17 00:00:00 2001 From: Kellen <9484709+goodroot@users.noreply.github.com> Date: Wed, 4 May 2022 13:35:14 -0700 Subject: [PATCH 51/68] Update nav-kibana-dev.docnav.json (#131568) --- nav-kibana-dev.docnav.json | 1 - 1 file changed, 1 deletion(-) diff --git a/nav-kibana-dev.docnav.json b/nav-kibana-dev.docnav.json index 43b23fd084673..4a1fd848a928e 100644 --- a/nav-kibana-dev.docnav.json +++ b/nav-kibana-dev.docnav.json @@ -100,7 +100,6 @@ { "id": "kibCoreSavedObjectsPluginApi" }, { "id": "kibFieldFormatsPluginApi" }, { "id": "kibDataPluginApi" }, - { "id": "kibDataAutocompletePluginApi" }, { "id": "kibDataEnhancedPluginApi" }, { "id": "kibDataViewsPluginApi" }, { "id": "kibDataQueryPluginApi" }, From 42ec15bd0b6c1b41cc4fc012190e77670c2f9d6a Mon Sep 17 00:00:00 2001 From: Jen Huang Date: Wed, 4 May 2022 13:50:05 -0700 Subject: [PATCH 52/68] Clean up unused status (#131558) --- x-pack/plugins/fleet/common/constants/epm.ts | 1 - x-pack/plugins/fleet/common/types/models/epm.ts | 13 ++----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/fleet/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts index 5952208007232..07f6fa048dc42 100644 --- a/x-pack/plugins/fleet/common/constants/epm.ts +++ b/x-pack/plugins/fleet/common/constants/epm.ts @@ -59,5 +59,4 @@ export const installationStatuses = { Installing: 'installing', InstallFailed: 'install_failed', NotInstalled: 'not_installed', - InstalledBundled: 'installed_bundled', } as const; diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 5217a6232a18c..2359b979d0a17 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -45,11 +45,7 @@ export interface DefaultPackagesInstallationError { export type InstallType = 'reinstall' | 'reupdate' | 'rollback' | 'update' | 'install' | 'unknown'; export type InstallSource = 'registry' | 'upload' | 'bundled'; -export type EpmPackageInstallStatus = - | 'installed' - | 'installing' - | 'install_failed' - | 'installed_bundled'; +export type EpmPackageInstallStatus = 'installed' | 'installing' | 'install_failed'; export type DetailViewPanelName = 'overview' | 'policies' | 'assets' | 'settings' | 'custom'; export type ServiceName = 'kibana' | 'elasticsearch'; @@ -431,8 +427,7 @@ export type Installable = | InstalledRegistry | Installing | NotInstalled - | InstallFailed - | InstalledBundled; + | InstallFailed; export type InstallStatusExcluded = T & { status: undefined; @@ -443,10 +438,6 @@ export type InstalledRegistry = T & { savedObject: SavedObject; }; -export type InstalledBundled = T & { - status: InstallationStatus['InstalledBundled']; -}; - export type Installing = T & { status: InstallationStatus['Installing']; savedObject: SavedObject; From 860261c864d8eb2d968514f39bf478e5cc0d6b35 Mon Sep 17 00:00:00 2001 From: Brandon Morelli Date: Wed, 4 May 2022 14:51:24 -0600 Subject: [PATCH 53/68] Fix broken/missing APM app links and use `docLinks` service (#128326) Co-authored-by: Kaarina Tungseth Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Giorgos Bamparopoulos --- packages/kbn-doc-links/src/get_doc_links.ts | 1 + packages/kbn-doc-links/src/types.ts | 1 + .../app/settings/custom_link/empty_prompt.tsx | 30 +++++++++++++---- .../app/settings/custom_link/index.test.tsx | 33 ++++++++++++------- .../app/settings/schema/schema_overview.tsx | 12 +++---- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 8 files changed, 51 insertions(+), 29 deletions(-) diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 14fd80c3a8552..79b41112768a6 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -47,6 +47,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => { metaData: `${APM_DOCS}guide/${DOC_LINK_VERSION}/data-model-metadata.html`, overview: `${APM_DOCS}guide/${DOC_LINK_VERSION}/apm-overview.html`, tailSamplingPolicies: `${APM_DOCS}guide/${DOC_LINK_VERSION}/configure-tail-based-sampling.html`, + elasticAgent: `${APM_DOCS}guide/${DOC_LINK_VERSION}/upgrade-to-apm-integration.html`, }, canvas: { guide: `${KIBANA_DOCS}canvas.html`, diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 4a5a9fdeb9576..645aad3af2bd2 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -33,6 +33,7 @@ export interface DocLinks { readonly metaData: string; readonly overview: string; readonly tailSamplingPolicies: string; + readonly elasticAgent: string; }; readonly canvas: { readonly guide: string; diff --git a/x-pack/plugins/apm/public/components/app/settings/custom_link/empty_prompt.tsx b/x-pack/plugins/apm/public/components/app/settings/custom_link/empty_prompt.tsx index dd9cd760d70cf..fd7a3d2587190 100644 --- a/x-pack/plugins/apm/public/components/app/settings/custom_link/empty_prompt.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/custom_link/empty_prompt.tsx @@ -5,16 +5,19 @@ * 2.0. */ -import { EuiEmptyPrompt } from '@elastic/eui'; +import { EuiEmptyPrompt, EuiLink, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; import { CreateCustomLinkButton } from './create_custom_link_button'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; export function EmptyPrompt({ onCreateCustomLinkClick, }: { onCreateCustomLinkClick: () => void; }) { + const { docLinks } = useApmPluginContext().core; return ( -

- {i18n.translate('xpack.apm.settings.customLink.emptyPromptText', { - defaultMessage: - "Let's change that! You can add custom links to the Actions context menu by the transaction details for each service. Create a helpful link to your company's support portal or open a new bug report. Learn more about it in our docs.", - })} -

+ + + {i18n.translate( + 'xpack.apm.settings.customLink.emptyPromptText.customLinkDocLinkText', + { defaultMessage: 'docs' } + )} + + ), + }} + /> + } actions={} diff --git a/x-pack/plugins/apm/public/components/app/settings/custom_link/index.test.tsx b/x-pack/plugins/apm/public/components/app/settings/custom_link/index.test.tsx index e9979746426a3..40f8f5ad1db25 100644 --- a/x-pack/plugins/apm/public/components/app/settings/custom_link/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/custom_link/index.test.tsx @@ -23,6 +23,7 @@ import { expectTextsNotInDocument, } from '../../../../utils/test_helpers'; import * as saveCustomLink from './create_edit_custom_link_flyout/save_custom_link'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; const data = { customLinks: [ @@ -73,9 +74,11 @@ describe('CustomLink', () => { it('shows when no link is available', () => { const component = render( - - - + + + + + ); expectTextsInDocument(component, ['No links found.']); @@ -360,9 +363,11 @@ describe('CustomLink', () => { }); const component = render( - - - + + + + + ); expectTextsNotInDocument(component, ['Start free 30-day trial']); @@ -375,9 +380,11 @@ describe('CustomLink', () => { const { getByTestId } = render( - - - + + + + + ); const createButton = getByTestId('createButton') as HTMLButtonElement; @@ -389,9 +396,11 @@ describe('CustomLink', () => { const { queryAllByText } = render( - - - + + + + + ); diff --git a/x-pack/plugins/apm/public/components/app/settings/schema/schema_overview.tsx b/x-pack/plugins/apm/public/components/app/settings/schema/schema_overview.tsx index 1e31eb8ccbe67..1f17b9f63c0a0 100644 --- a/x-pack/plugins/apm/public/components/app/settings/schema/schema_overview.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/schema/schema_overview.tsx @@ -11,6 +11,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiIcon, + EuiLink, EuiLoadingSpinner, EuiSpacer, EuiText, @@ -21,11 +22,11 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import semverLt from 'semver/functions/lt'; import { PackagePolicy } from '@kbn/fleet-plugin/common/types'; -import { ElasticDocsLink } from '../../../shared/links/elastic_docs_link'; import rocketLaunchGraphic from './blog_rocket_720x420.png'; import { MigrationInProgressPanel } from './migration_in_progress_panel'; import { UpgradeAvailableCard } from './migrated/upgrade_available_card'; import { SuccessfulMigrationCard } from './migrated/successful_migration_card'; +import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; interface Props { onSwitch: () => void; @@ -184,6 +185,7 @@ export function SchemaOverview({ } export function SchemaOverviewHeading() { + const { docLinks } = useApmPluginContext().core; return ( <> @@ -208,16 +210,12 @@ export function SchemaOverviewHeading() { ), elasticAgentDocLink: ( - + {i18n.translate( 'xpack.apm.settings.schema.descriptionText.elasticAgentDocLinkText', { defaultMessage: 'Elastic Agent' } )} - + ), }} /> diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 7ee56f53e1f89..cf9e0c25c346d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -8035,7 +8035,6 @@ "xpack.apm.settings.customLink.delete": "Supprimer", "xpack.apm.settings.customLink.delete.failed": "Impossible de supprimer le lien personnalisé", "xpack.apm.settings.customLink.delete.successed": "Lien personnalisé supprimé.", - "xpack.apm.settings.customLink.emptyPromptText": "Nous allons y remédier ! Vous pouvez ajouter des liens personnalisés au menu contextuel Actions à partir des détails de transaction de chaque service. Créez un lien utile vers le portail d'assistance de votre société, ou ouvrez un nouveau rapport de bug. Pour en savoir plus, consultez notre documentation.", "xpack.apm.settings.customLink.emptyPromptTitle": "Aucun lien trouvé.", "xpack.apm.settings.customLink.flyout.action.title": "Lien", "xpack.apm.settings.customLink.flyout.close": "Fermer", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 2cd3f174be443..847603367dd1b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -8001,7 +8001,6 @@ "xpack.apm.settings.customLink.delete": "削除", "xpack.apm.settings.customLink.delete.failed": "カスタムリンクを削除できませんでした", "xpack.apm.settings.customLink.delete.successed": "カスタムリンクを削除しました。", - "xpack.apm.settings.customLink.emptyPromptText": "変更しましょう。サービスごとのトランザクションの詳細でアクションコンテキストメニューにカスタムリンクを追加できます。自社のサポートポータルへの役立つリンクを作成するか、新しい不具合レポートを発行します。詳細はドキュメントをご覧ください。", "xpack.apm.settings.customLink.emptyPromptTitle": "リンクが見つかりません。", "xpack.apm.settings.customLink.flyout.action.title": "リンク", "xpack.apm.settings.customLink.flyout.close": "閉じる", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1afb1b21737da..aee146cced139 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -8021,7 +8021,6 @@ "xpack.apm.settings.customLink.delete": "删除", "xpack.apm.settings.customLink.delete.failed": "无法删除定制链接", "xpack.apm.settings.customLink.delete.successed": "已删除定制链接。", - "xpack.apm.settings.customLink.emptyPromptText": "让我们改动一下!可以通过每个服务的事务详情将定制链接添加到“操作”上下文菜单。创建指向公司支持门户或用于提交新错误报告的有用链接。在我们的文档中详细了解。", "xpack.apm.settings.customLink.emptyPromptTitle": "未找到链接。", "xpack.apm.settings.customLink.flyout.action.title": "链接", "xpack.apm.settings.customLink.flyout.close": "关闭", From fb453aca45afccfcec4ce3e0cd98a4fa4772a122 Mon Sep 17 00:00:00 2001 From: Melissa Burpo Date: Wed, 4 May 2022 16:13:54 -0500 Subject: [PATCH 54/68] Osquery pack attribution (#131462) * add new reference page for prebuilt packs * add link to new prebuilt pack ref page * convert list to table * add table close * Apply suggestions from code review Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> Co-authored-by: gchaps <33642766+gchaps@users.noreply.github.com> --- docs/osquery/osquery.asciidoc | 4 ++ docs/osquery/prebuilt-packs.asciidoc | 63 ++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 docs/osquery/prebuilt-packs.asciidoc diff --git a/docs/osquery/osquery.asciidoc b/docs/osquery/osquery.asciidoc index e450bcbcb7d6f..9e384d79a4d6b 100644 --- a/docs/osquery/osquery.asciidoc +++ b/docs/osquery/osquery.asciidoc @@ -127,6 +127,8 @@ The Osquery Manager integration includes a set of prebuilt Osquery packs that yo You can modify the scheduled agent policies for a prebuilt pack, but you cannot edit queries in the pack. To edit the queries, you must first create a copy of the pack. +For information about the prebuilt packs that are available, refer to <>. + [float] [[load-prebuilt-packs]] === Load and activate prebuilt Elastic packs @@ -310,3 +312,5 @@ https://osquery.readthedocs.io/en/stable/deployment/logging/#differential-logs[d include::manage-integration.asciidoc[] include::exported-fields-reference.asciidoc[] + +include::prebuilt-packs.asciidoc[] diff --git a/docs/osquery/prebuilt-packs.asciidoc b/docs/osquery/prebuilt-packs.asciidoc new file mode 100644 index 0000000000000..776a1937b7a69 --- /dev/null +++ b/docs/osquery/prebuilt-packs.asciidoc @@ -0,0 +1,63 @@ +[[prebuilt-packs]] +== Prebuilt packs reference + +This section lists all prebuilt packs available for Osquery Manager. +Each pack is also available as a saved object, with the name `Pack: `. + +For more information, refer to <>. + + +|=== +|Name |Description |Source |Added + +|`hardware-monitoring` +|Monitor for hardware changes. +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`incident-response` +|Detect and respond to breaches. +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`it-compliance` +a|Identify outdated and vulnerable software. + +Dashboard: `[Osquery Manager] Compliance pack` + +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`osquery-monitoring` +|Monitor Osquery info and performance. +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`ossec-rootkit` +a|Run rootkit detection queries to monitor for compromise. + +Dashboard: `[Osquery Manager] OSSEC rootkit pack` + +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`osx-attacks` +|Identify compromised macOS systems. +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`unwanted-chrome-extensions` +|Monitor for malicious Chrome extensions. +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`vuln-management` +|Identify system vulnerabilities. +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 + +|`windows-attacks` +|Monitor for evidence of Windows attacks. +|https://github.com/osquery/osquery/tree/master/packs[Osquery] +|8.2 +|=== From 542b381fa51703fe95708dff956fdac93dd5d3dc Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 4 May 2022 15:05:58 -0700 Subject: [PATCH 55/68] [ftr] automatically determine config run order (#130983) * [ftr] automatically determine config run order * split lens config into two groups * support ftr configs always running against CI * Split detection_engine_api_integration rule exception list tests * Add configs from previous commit * [ftr] remove testMetadata and maintain a unique lifecycle instance per run * Revert "[ftr] remove testMetadata and maintain a unique lifecycle instance per run" This reverts commit d2b4fdb8249ff4d8b835f0c6c74df8d1a29ddb3c. * Split alerting_api_integration/security_and_spaces tests * Add groups to yaml * Revert "Revert "[ftr] remove testMetadata and maintain a unique lifecycle instance per run"" This reverts commit 56232eea682a4d1393d9ecef575e4906dc2862b3. * stop ES more forcefully and fix timeout * only cleanup lifecycle phases when the cleanup is totally complete * only use kill when cleaning up an esTestInstance * fix broken import * fix runOptions.alwaysUseSource implementation * fix config access * fix x-pack/ccs config * fix ml import file paths * update kibana build id * revert array.concat() change * fix baseConfig usage * fix pie chart data * split up maps tests * pull in all of group5 so that es archives are loaded correctly * add to ftr configs.yml * fix pie chart data without breaking legacy version * fix more pie_chart stuff in new vis lib * restore normal PR tasks * bump kibana-buildkite-library * remove ciGroup validation * remove the script which is no longer called from checks.sh * [CI] Auto-commit changed files from 'yarn kbn run build -i @kbn/pm' * adapt flaky test runner scripts to handle ftrConfig paths * fix types in alerting_api_integration * improve flaky config parsing and use non-local var name for passing explicit configs to ftr_configs.sh * Split xpack dashboard tests * Add configs * [flaky] remove key from ftr-config steps * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * restore cypress builds * remove ciGroups from FTR config files * fixup some docs * add temporary script to hunt for FTR config files * use config.base.js naming for clarity * use script to power ftr_configs.yml * remove usage of removed x-pack/scripts/functional_tests * fix test names in dashboard snapshots * bump kibana-buildkite-library * Try retrying only failed configs * be a little quieter about trying to get testStats from configs with testRunners defined * Remove test code * bump kibana-buildkite-library * update es_snapshot and on_merge jobs too * track duration and exit code for each config and print it at the end of the script * store results in order, rather than by key, in case there are duplicates in $config * bash is hard * fix env source and use +e rather than disabling e for whole file * bash sucks * print config summary in jest jobs too * define results in jest_parallel.sh * simplify config summary print, format times a little better * fix reference to unbound time variable, use better variable name * skip the newline between each result * finish with the nitpicking * sync changes with ftr_configs.sh * refuse to execute config files which aren't listed in the .buildkite/ftr_configs.yml * fix config.edge.js base config import paths * fix some readmes * resolve paths from ftr_configs manifest * fix readConfigFile tests * just allow __fixtures__ configs * list a few more cypress config files * install the main branch of kibana-buildkite-library * split up lens group1 * move ml data_visualizer tests to their own config * fix import paths * fix more imports * install specific commit of buildkite-pipeline-library * sort configs in ftr_configs.yml * bump kibana-buildkite-library * remove temporary script * fix env var for limiting config types * Update docs/developer/contributing/development-functional-tests.asciidoc Co-authored-by: Christiane (Tina) Heiligers * produce a JUnit report for saved objects field count * apply standard concurrency limits from flaky test runner * support customizing FTR concurrency via the env Co-authored-by: Brian Seeders Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Christiane (Tina) Heiligers --- .buildkite/ftr_configs.yml | 236 ++++++++++++++++++ .buildkite/package-lock.json | 12 +- .buildkite/package.json | 2 +- .buildkite/pipelines/es_snapshots/verify.yml | 39 +-- .buildkite/pipelines/flaky_tests/groups.json | 34 +-- .buildkite/pipelines/flaky_tests/pipeline.js | 155 ++++++------ .buildkite/pipelines/on_merge.yml | 123 +-------- .buildkite/pipelines/pull_request/base.yml | 123 +-------- .buildkite/scripts/steps/checks.sh | 1 - .../steps/checks/validate_ci_groups.sh | 9 - .../scripts/steps/functional/fleet_cypress.sh | 4 +- .../steps/functional/osquery_cypress.sh | 4 +- .../steps/functional/oss_accessibility.sh | 13 - .../scripts/steps/functional/oss_cigroup.sh | 16 -- .../scripts/steps/functional/oss_firefox.sh | 14 -- .../scripts/steps/functional/oss_misc.sh | 51 ---- .../functional/performance_playwright.sh | 10 +- .../scripts/steps/functional/response_ops.sh | 4 +- .../steps/functional/response_ops_cases.sh | 4 +- .../steps/functional/security_solution.sh | 4 +- .../steps/functional/xpack_accessibility.sh | 15 -- .../scripts/steps/functional/xpack_cigroup.sh | 20 -- .../scripts/steps/functional/xpack_firefox.sh | 17 -- .../xpack_saved_object_field_metrics.sh | 17 -- .../scripts/steps/test/api_integration.sh | 16 -- .buildkite/scripts/steps/test/ftr_configs.sh | 88 +++++++ .../scripts/steps/test/jest_parallel.sh | 29 ++- .../steps/test/pick_jest_config_run_order.sh | 9 - ..._order.js => pick_test_group_run_order.js} | 0 .../steps/test/pick_test_group_run_order.sh | 9 + .../test/{jest_env.sh => test_group_env.sh} | 1 + .../development-functional-tests.asciidoc | 7 +- .../external-plugin-functional-tests.asciidoc | 2 +- .../kbn-dev-utils/src/proc_runner/proc.ts | 14 +- .../src/proc_runner/proc_runner.ts | 48 ++-- packages/kbn-es-archiver/src/cli.ts | 2 +- packages/kbn-es/src/cluster.js | 18 ++ packages/kbn-pm/dist/index.js | 21 +- .../src/observe_lines.ts | 17 +- .../src/observe_readable.ts | 10 +- packages/kbn-test/BUILD.bazel | 2 + packages/kbn-test/README.md | 4 +- packages/kbn-test/src/es/test_es_cluster.ts | 23 +- .../src/functional_test_runner/cli.ts | 6 +- .../functional_test_runner.ts | 163 ++++++------ .../src/functional_test_runner/index.ts | 1 - .../lib/config/ftr_configs_manifest.ts | 23 ++ ..._file.test.js => read_config_file.test.ts} | 25 +- .../lib/config/read_config_file.ts | 38 ++- .../lib/config/schema.ts | 5 + .../src/functional_test_runner/lib/index.ts | 1 - .../functional_test_runner/lib/lifecycle.ts | 38 ++- .../lib/lifecycle_phase.test.ts | 12 +- .../lib/lifecycle_phase.ts | 7 + .../lib/mocha/decorate_mocha_ui.js | 32 +++ .../lib/mocha/filter_suites.test.js | 5 +- .../lib/mocha/filter_suites.ts | 2 +- .../mocha/reporter/ci_stats_ftr_reporter.ts | 15 +- .../lib/mocha/reporter/reporter.js | 2 - .../lib/mocha/validate_ci_group_tags.js | 6 +- .../lib/providers/index.ts | 2 +- .../snapshots/decorate_snapshot_ui.test.ts | 17 +- .../lib/suite_tracker.test.ts | 4 +- .../lib/test_metadata.ts | 41 --- .../functional_test_runner/public_types.ts | 9 +- .../src/functional_tests/lib/run_ftr.ts | 8 +- .../functional_tests/lib/run_kibana_server.ts | 11 +- .../kbn-test/src/functional_tests/tasks.ts | 28 +-- scripts/README.md | 8 +- scripts/functional_tests.js | 24 +- scripts/functional_tests_server.js | 2 +- test/accessibility/config.ts | 2 +- test/analytics/config.ts | 2 +- .../lib/saved_objects_test_utils.ts | 3 +- test/api_integration/config.js | 2 +- test/examples/bfetch_explorer/index.ts | 1 - test/examples/config.js | 2 +- .../data_view_field_editor_example/index.ts | 1 - test/examples/embeddables/index.ts | 1 - test/examples/expressions_explorer/index.ts | 1 - test/examples/field_formats/index.ts | 1 - test/examples/hello_world/index.ts | 1 - test/examples/partial_results/index.ts | 1 - test/examples/routing/index.ts | 1 - test/examples/state_sync/index.ts | 1 - test/examples/ui_actions/index.ts | 1 - .../bundles/config.ts} | 17 +- test/functional/apps/bundles/index.js | 2 +- test/functional/apps/console/config.ts | 18 ++ test/functional/apps/console/index.js | 2 - test/functional/apps/context/config.ts | 18 ++ test/functional/apps/context/index.ts | 2 - test/functional/apps/dashboard/README.md | 7 + .../apps/dashboard/group1/config.ts | 18 ++ .../create_and_add_embeddables.ts | 2 +- .../{ => group1}/dashboard_back_button.ts | 2 +- .../{ => group1}/dashboard_error_handling.ts | 2 +- .../{ => group1}/dashboard_options.ts | 2 +- .../{ => group1}/dashboard_query_bar.ts | 2 +- .../{ => group1}/dashboard_unsaved_listing.ts | 2 +- .../{ => group1}/dashboard_unsaved_state.ts | 2 +- .../{ => group1}/data_shared_attributes.ts | 2 +- .../{ => group1}/edit_embeddable_redirects.ts | 2 +- .../{ => group1}/edit_visualizations.js | 0 .../apps/dashboard/{ => group1}/embed_mode.ts | 2 +- .../{ => group1}/embeddable_data_grid.ts | 2 +- .../{ => group1}/embeddable_rendering.ts | 2 +- .../dashboard/{ => group1}/empty_dashboard.ts | 2 +- .../functional/apps/dashboard/group1/index.ts | 54 ++++ .../dashboard/{ => group1}/legacy_urls.ts | 2 +- .../{ => group1}/saved_search_embeddable.ts | 2 +- .../apps/dashboard/{ => group1}/share.ts | 2 +- .../{ => group1}/url_field_formatter.ts | 4 +- .../apps/dashboard/group2/config.ts | 18 ++ .../{ => group2}/dashboard_filter_bar.ts | 2 +- .../{ => group2}/dashboard_filtering.ts | 2 +- .../dashboard/{ => group2}/dashboard_grid.ts | 2 +- .../{ => group2}/dashboard_saved_query.ts | 2 +- .../{ => group2}/dashboard_snapshots.ts | 2 +- .../{ => group2}/embeddable_library.ts | 2 +- .../{ => group2}/full_screen_mode.ts | 2 +- .../functional/apps/dashboard/group2/index.ts | 43 ++++ .../{ => group2}/panel_expand_toggle.ts | 2 +- .../apps/dashboard/{ => group2}/view_edit.ts | 2 +- .../dashboard/{ => group3}/bwc_shared_urls.ts | 2 +- .../apps/dashboard/group3/config.ts | 18 ++ .../dashboard/{ => group3}/copy_panel_to.ts | 2 +- .../dashboard/{ => group3}/dashboard_state.ts | 4 +- .../{ => group3}/dashboard_time_picker.ts | 4 +- .../functional/apps/dashboard/group3/index.ts | 36 +++ .../dashboard/{ => group3}/panel_cloning.ts | 4 +- .../{ => group3}/panel_context_menu.ts | 4 +- .../dashboard/{ => group3}/panel_replacing.ts | 4 +- .../apps/dashboard/group4/config.ts | 18 ++ .../dashboard/{ => group4}/dashboard_clone.ts | 2 +- .../{ => group4}/dashboard_listing.ts | 2 +- .../dashboard/{ => group4}/dashboard_save.ts | 2 +- .../dashboard/{ => group4}/dashboard_time.ts | 2 +- .../functional/apps/dashboard/group4/index.ts | 33 +++ .../apps/dashboard/group5/config.ts | 18 ++ .../functional/apps/dashboard/group5/index.ts | 48 ++++ test/functional/apps/dashboard/index.ts | 139 ----------- .../apps/dashboard_elements/config.ts | 18 ++ .../apps/dashboard_elements/index.ts | 4 +- test/functional/apps/discover/config.ts | 18 ++ test/functional/apps/discover/index.ts | 2 - .../functional/apps/getting_started/config.ts | 18 ++ test/functional/apps/getting_started/index.ts | 2 - test/functional/apps/home/config.ts | 18 ++ test/functional/apps/home/index.js | 4 +- test/functional/apps/management/config.ts | 18 ++ test/functional/apps/management/index.ts | 47 ++-- .../apps/saved_objects_management/config.ts | 18 ++ .../apps/saved_objects_management/index.ts | 1 - test/functional/apps/status_page/config.ts | 18 ++ test/functional/apps/status_page/index.ts | 2 - test/functional/apps/visualize/README.md | 7 + .../visualize/{ => group1}/_chart_types.ts | 2 +- .../visualize/{ => group1}/_data_table.ts | 2 +- .../{ => group1}/_data_table_nontimeindex.ts | 2 +- .../_data_table_notimeindex_filters.ts | 2 +- .../{ => group1}/_embedding_chart.ts | 2 +- .../apps/visualize/group1/config.ts | 18 ++ .../functional/apps/visualize/group1/index.ts | 32 +++ .../{ => group2}/_experimental_vis.ts | 2 +- .../visualize/{ => group2}/_gauge_chart.ts | 2 +- .../visualize/{ => group2}/_heatmap_chart.ts | 2 +- .../{ => group2}/_histogram_request_start.ts | 2 +- .../apps/visualize/{ => group2}/_inspector.ts | 2 +- .../visualize/{ => group2}/_metric_chart.ts | 2 +- .../apps/visualize/group2/config.ts | 18 ++ .../functional/apps/visualize/group2/index.ts | 33 +++ .../{ => group3}/_add_to_dashboard.ts | 2 +- .../apps/visualize/{ => group3}/_lab_mode.ts | 2 +- .../{ => group3}/_linked_saved_searches.ts | 2 +- .../apps/visualize/{ => group3}/_pie_chart.ts | 22 +- .../visualize/{ => group3}/_shared_item.ts | 2 +- .../{ => group3}/_visualize_listing.ts | 2 +- .../apps/visualize/group3/config.ts | 18 ++ .../functional/apps/visualize/group3/index.ts | 33 +++ .../visualize/{ => group4}/_tsvb_chart.ts | 2 +- .../apps/visualize/group4/config.ts | 18 ++ .../functional/apps/visualize/group4/index.ts | 28 +++ .../{ => group5}/_tsvb_time_series.ts | 2 +- .../apps/visualize/group5/config.ts | 18 ++ .../functional/apps/visualize/group5/index.ts | 28 +++ .../apps/visualize/{ => group6}/_tag_cloud.ts | 2 +- .../visualize/{ => group6}/_tsvb_markdown.ts | 2 +- .../visualize/{ => group6}/_tsvb_table.ts | 2 +- .../visualize/{ => group6}/_vega_chart.ts | 2 +- .../apps/visualize/group6/config.ts | 18 ++ .../functional/apps/visualize/group6/index.ts | 31 +++ test/functional/apps/visualize/index.ts | 112 --------- .../_area_chart.ts | 2 +- .../_line_chart_split_chart.ts | 2 +- .../_line_chart_split_series.ts | 2 +- .../_point_series_options.ts | 2 +- .../_timelion.ts | 2 +- .../_vertical_bar_chart.ts | 2 +- .../_vertical_bar_chart_nontimeindex.ts | 2 +- .../replaced_vislib_chart_types/config.ts | 18 ++ .../replaced_vislib_chart_types/index.ts | 55 ++++ test/functional/{config.js => config.base.js} | 14 -- test/functional/config.ccs.ts | 16 +- test/functional/config.edge.js | 4 +- test/functional/config.firefox.js | 14 +- .../functional/services/common/screenshots.ts | 37 +-- .../tests/enrollment_flow.ts | 2 +- .../tests/manual_configuration_flow.ts | 2 +- .../manual_configuration_flow_without_tls.ts | 2 +- ...l_configuration_without_security.config.ts | 2 +- .../tests/enrollment_token.ts | 2 +- .../tests/manual_configuration.ts | 2 +- .../manual_configuration_without_security.ts | 2 +- .../tests/manual_configuration_without_tls.ts | 2 +- test/interpreter_functional/config.ts | 2 +- test/new_visualize_flow/config.ts | 2 +- test/new_visualize_flow/index.ts | 1 - test/plugin_functional/config.ts | 2 +- .../test_suites/core_plugins/rendering.ts | 2 +- .../{config.js => config.base.js} | 2 +- .../http/platform/config.status.ts | 3 +- .../http/platform/config.ts | 2 +- test/server_integration/http/ssl/config.js | 2 +- .../http/ssl_redirect/config.js | 2 +- .../http/ssl_with_p12/config.js | 2 +- .../http/ssl_with_p12_intermediate/config.js | 2 +- test/ui_capabilities/newsfeed_err/config.ts | 10 +- test/ui_capabilities/newsfeed_err/test.ts | 2 - test/visual_regression/config.ts | 2 +- .../visual_regression/tests/discover/index.ts | 2 - test/visual_regression/tests/vega/index.ts | 2 - x-pack/README.md | 2 +- x-pack/plugins/apm/dev_docs/testing.md | 4 +- .../apm/ftr_e2e/cypress/tasks/es_archiver.ts | 6 +- x-pack/plugins/apm/ftr_e2e/ftr_config.ts | 2 +- x-pack/plugins/fleet/cypress/README.md | 4 +- x-pack/plugins/graph/README.md | 4 +- x-pack/plugins/lens/readme.md | 5 +- x-pack/plugins/maps/README.md | 5 +- x-pack/plugins/osquery/cypress/README.md | 4 +- .../security_solution/cypress/README.md | 8 +- .../cypress/tasks/es_archiver.ts | 2 +- x-pack/plugins/synthetics/e2e/config.ts | 2 +- .../synthetics/e2e/tasks/es_archiver.ts | 6 +- x-pack/scripts/functional_tests.js | 96 ------- x-pack/scripts/functional_tests_server.js | 2 +- .../accessibility/apps/advanced_settings.ts | 2 +- x-pack/test/accessibility/apps/canvas.ts | 2 +- .../apps/dashboard_edit_panel.ts | 2 +- .../accessibility/apps/enterprise_search.ts | 2 +- .../test/accessibility/apps/grok_debugger.ts | 2 +- x-pack/test/accessibility/apps/home.ts | 2 +- .../apps/index_lifecycle_management.ts | 4 +- .../apps/ingest_node_pipelines.ts | 2 +- .../accessibility/apps/kibana_overview.ts | 2 +- x-pack/test/accessibility/apps/lens.ts | 2 +- .../accessibility/apps/license_management.ts | 2 +- x-pack/test/accessibility/apps/login_page.ts | 3 +- x-pack/test/accessibility/apps/maps.ts | 2 +- x-pack/test/accessibility/apps/ml.ts | 16 +- .../apps/ml_embeddables_in_dashboard.ts | 2 +- .../test/accessibility/apps/painless_lab.ts | 2 +- .../accessibility/apps/remote_clusters.ts | 2 +- x-pack/test/accessibility/apps/reporting.ts | 2 +- x-pack/test/accessibility/apps/roles.ts | 2 +- .../accessibility/apps/search_profiler.ts | 2 +- .../accessibility/apps/search_sessions.ts | 2 +- .../accessibility/apps/security_solution.ts | 2 +- x-pack/test/accessibility/apps/spaces.ts | 2 +- x-pack/test/accessibility/apps/tags.ts | 2 +- x-pack/test/accessibility/apps/transform.ts | 2 +- .../accessibility/apps/upgrade_assistant.ts | 2 +- x-pack/test/accessibility/apps/uptime.ts | 2 +- x-pack/test/accessibility/apps/users.ts | 2 +- x-pack/test/accessibility/config.ts | 2 +- .../basic/tests/index.ts | 2 - .../alerting_api_integration/common/config.ts | 4 +- .../{ => group1}/config.ts | 3 +- .../{ => group1}/tests/alerting/create.ts | 6 +- .../{ => group1}/tests/alerting/delete.ts | 6 +- .../{ => group1}/tests/alerting/disable.ts | 6 +- .../{ => group1}/tests/alerting/enable.ts | 6 +- .../tests/alerting/execution_status.ts | 6 +- .../{ => group1}/tests/alerting/find.ts | 6 +- .../{ => group1}/tests/alerting/get.ts | 6 +- .../tests/alerting/get_alert_state.ts | 6 +- .../tests/alerting/get_alert_summary.ts | 6 +- .../group1/tests/alerting/index.ts | 35 +++ .../{ => group1}/tests/alerting/rule_types.ts | 6 +- .../security_and_spaces/group1/tests/index.ts | 17 ++ .../security_and_spaces/group2/config.ts | 18 ++ .../actions/builtin_action_types/email.ts | 4 +- .../actions/builtin_action_types/es_index.ts | 2 +- .../es_index_preconfigured.ts | 2 +- .../actions/builtin_action_types/jira.ts | 6 +- .../actions/builtin_action_types/pagerduty.ts | 6 +- .../actions/builtin_action_types/resilient.ts | 6 +- .../builtin_action_types/server_log.ts | 2 +- .../builtin_action_types/servicenow_itom.ts | 6 +- .../builtin_action_types/servicenow_itsm.ts | 6 +- .../builtin_action_types/servicenow_sir.ts | 6 +- .../actions/builtin_action_types/slack.ts | 6 +- .../actions/builtin_action_types/swimlane.ts | 6 +- .../actions/builtin_action_types/webhook.ts | 6 +- .../actions/builtin_action_types/xmatters.ts | 6 +- .../group2/tests/actions/config.ts | 18 ++ .../tests/actions/connector_types.ts | 6 +- .../{ => group2}/tests/actions/create.ts | 6 +- .../{ => group2}/tests/actions/delete.ts | 6 +- .../{ => group2}/tests/actions/execute.ts | 6 +- .../{ => group2}/tests/actions/get.ts | 6 +- .../{ => group2}/tests/actions/get_all.ts | 6 +- .../{ => group2}/tests/actions/index.ts | 4 +- .../tests/actions/manual/pr_40694.js | 0 .../{ => group2}/tests/actions/update.ts | 6 +- .../{ => group2}/tests/alerting/alerts.ts | 6 +- .../{ => group2}/tests/alerting/event_log.ts | 8 +- .../{ => group2}/tests/alerting/excluded.ts | 6 +- .../{ => group2}/tests/alerting/health.ts | 6 +- .../group2/tests/alerting/index.ts | 49 ++++ .../tests/alerting/mustache_templates.ts | 10 +- .../{ => group2}/tests/alerting/mute_all.ts | 6 +- .../tests/alerting/mute_instance.ts | 6 +- .../tests/alerting/rbac_legacy.ts | 8 +- .../{ => group2}/tests/alerting/snooze.ts | 6 +- .../{ => group2}/tests/alerting/unmute_all.ts | 6 +- .../tests/alerting/unmute_instance.ts | 6 +- .../{ => group2}/tests/alerting/unsnooze.ts | 6 +- .../{ => group2}/tests/alerting/update.ts | 6 +- .../tests/alerting/update_api_key.ts | 6 +- .../security_and_spaces/group2/tests/index.ts | 17 ++ .../tests/telemetry/actions_telemetry.ts | 6 +- .../tests/telemetry/alerting_telemetry.ts | 6 +- .../group2/tests/telemetry/config.ts | 18 ++ .../{ => group2}/tests/telemetry/index.ts | 4 +- .../{tests/index.ts => setup.ts} | 19 +- .../tests/alerting/index.ts | 68 ----- .../spaces_only/tests/index.ts | 2 - .../spaces_only_legacy/tests/index.ts | 2 - x-pack/test/api_integration/apis/index.ts | 2 - .../api_integration/apis/security/index.ts | 2 - .../apis/security/security_basic.ts | 2 - .../apis/security/security_trial.ts | 2 - .../test/api_integration/apis/spaces/index.ts | 2 - x-pack/test/api_integration/config.ts | 2 +- .../test/api_integration_basic/apis/index.ts | 2 - .../test/apm_api_integration/tests/index.ts | 2 - x-pack/test/banners_functional/config.ts | 4 +- x-pack/test/banners_functional/tests/index.ts | 2 - .../security_and_spaces/tests/basic/index.ts | 3 - .../security_and_spaces/tests/trial/index.ts | 24 +- .../spaces_only/tests/trial/index.ts | 3 - x-pack/test/cloud_integration/config.ts | 2 +- .../basic/config.ts | 11 +- .../basic/tests/index.ts | 2 - .../common/config.ts | 4 +- .../security_and_spaces/README.md | 33 +++ .../{config.ts => config.base.ts} | 2 +- .../{tests => group1}/add_actions.ts | 0 .../add_prepackaged_rules.ts | 0 .../{tests => group1}/aliases.ts | 0 .../{tests => group1}/check_privileges.ts | 0 .../security_and_spaces/group1/config.ts} | 19 +- .../{tests => group1}/create_index.ts | 0 .../{tests => group1}/create_ml.ts | 0 .../{tests => group1}/create_rules.ts | 0 .../{tests => group1}/create_rules_bulk.ts | 0 .../create_signals_migrations.ts | 0 .../create_threat_matching.ts | 0 .../{tests => group1}/delete_rules.ts | 0 .../{tests => group1}/delete_rules_bulk.ts | 0 .../delete_signals_migrations.ts | 0 .../{tests => group1}/export_rules.ts | 0 .../finalize_signals_migrations.ts | 0 .../{tests => group1}/find_rules.ts | 0 .../{tests => group1}/generating_signals.ts | 0 .../get_prepackaged_rules_status.ts | 0 .../get_rule_execution_events.ts | 0 .../get_signals_migration_status.ts | 0 .../{tests => group1}/ignore_fields.ts | 0 .../{tests => group1}/import_export_rules.ts | 0 .../{tests => group1}/import_rules.ts | 0 .../security_and_spaces/group1/index.ts | 57 +++++ .../legacy_actions_migrations.ts | 0 .../{tests => group1}/migrations.ts | 0 .../{tests => group1}/open_close_signals.ts | 0 .../{tests => group1}/patch_rules.ts | 0 .../{tests => group1}/patch_rules_bulk.ts | 0 .../{tests => group1}/perform_bulk_action.ts | 0 .../{tests => group1}/preview_rules.ts | 0 .../{tests => group1}/read_privileges.ts | 0 .../{tests => group1}/read_rules.ts | 0 .../{tests => group1}/resolve_read_rules.ts | 0 .../{tests => group1}/runtime.ts | 0 .../template_data/execution_events.ts | 0 .../{tests => group1}/throttle.ts | 0 .../{tests => group1}/timestamps.ts | 0 .../{tests => group1}/update_actions.ts | 0 .../{tests => group1}/update_rules.ts | 0 .../{tests => group1}/update_rules_bulk.ts | 0 .../security_and_spaces/group2/config.ts | 18 ++ .../create_endpoint_exceptions.ts | 0 .../security_and_spaces/group2/index.ts | 15 ++ .../security_and_spaces/group3/config.ts | 18 ++ .../{tests => group3}/create_exceptions.ts | 0 .../security_and_spaces/group3/index.ts | 15 ++ .../security_and_spaces/group4/config.ts | 18 ++ .../security_and_spaces/group4/index.ts | 15 ++ .../{tests => group4}/telemetry/README.md | 0 .../{tests => group4}/telemetry/index.ts | 15 +- .../telemetry/task_based/all_types.ts | 0 .../telemetry/task_based/detection_rules.ts | 0 .../telemetry/task_based/security_lists.ts | 0 .../telemetry/usage_collector/all_types.ts | 0 .../usage_collector/detection_rule_status.ts | 0 .../usage_collector/detection_rules.ts | 0 .../security_and_spaces/group5/config.ts | 18 ++ .../security_and_spaces/group5/index.ts | 15 ++ .../keyword_family/README.md | 0 .../keyword_family/const_keyword.ts | 0 .../{tests => group5}/keyword_family/index.ts | 10 +- .../keyword_family/keyword.ts | 0 .../keyword_mixed_with_const.ts | 0 .../alerts/alerts_compatibility.ts | 0 .../{tests => group6}/alerts/index.ts | 6 +- .../security_and_spaces/group6/config.ts | 18 ++ .../security_and_spaces/group6/index.ts | 15 ++ .../security_and_spaces/group7/config.ts | 18 ++ .../exception_operators_data_types/date.ts | 0 .../exception_operators_data_types/double.ts | 0 .../exception_operators_data_types/float.ts | 0 .../exception_operators_data_types/index.ts | 18 ++ .../exception_operators_data_types/integer.ts | 0 .../security_and_spaces/group7/index.ts | 15 ++ .../security_and_spaces/group8/config.ts | 18 ++ .../exception_operators_data_types/index.ts | 18 ++ .../exception_operators_data_types/keyword.ts | 0 .../keyword_array.ts | 0 .../exception_operators_data_types/long.ts | 0 .../exception_operators_data_types/text.ts | 0 .../security_and_spaces/group8/index.ts | 15 ++ .../security_and_spaces/group9/config.ts | 18 ++ .../exception_operators_data_types/index.ts | 17 ++ .../exception_operators_data_types/ip.ts | 0 .../ip_array.ts | 0 .../text_array.ts | 0 .../security_and_spaces/group9/index.ts | 15 ++ .../exception_operators_data_types/README.md | 21 -- .../exception_operators_data_types/index.ts | 44 ---- .../security_and_spaces/tests/index.ts | 92 ------- .../tests/index.ts | 1 - .../apis/index.ts | 1 - x-pack/test/examples/config.ts | 4 +- x-pack/test/examples/embedded_lens/index.ts | 8 +- .../test/examples/reporting_examples/index.ts | 2 - x-pack/test/examples/screenshotting/index.ts | 2 - x-pack/test/examples/search_examples/index.ts | 1 - .../test/fleet_api_integration/apis/index.js | 2 - x-pack/test/fleet_cypress/config.ts | 2 +- .../apps/fleet/agents_page.ts | 2 - .../test/fleet_functional/apps/fleet/index.ts | 1 - .../test/fleet_functional/apps/home/index.ts | 1 - x-pack/test/fleet_functional/config.ts | 4 +- .../apps/advanced_settings/config.ts | 17 ++ .../apps/advanced_settings/index.ts | 2 +- .../test/functional/apps/api_keys/config.ts | 17 ++ x-pack/test/functional/apps/api_keys/index.ts | 1 - x-pack/test/functional/apps/apm/config.ts | 17 ++ x-pack/test/functional/apps/apm/index.ts | 1 - x-pack/test/functional/apps/canvas/config.ts | 17 ++ x-pack/test/functional/apps/canvas/index.js | 1 - .../apps/cross_cluster_replication/config.ts | 17 ++ .../apps/cross_cluster_replication/index.ts | 2 +- .../test/functional/apps/dashboard/README.md | 7 + .../apps/dashboard/group1/config.ts | 17 ++ .../dashboard_to_dashboard_drilldown.ts | 2 +- .../drilldowns/dashboard_to_url_drilldown.ts | 2 +- .../drilldowns/explore_data_chart_action.ts | 2 +- .../drilldowns/explore_data_panel_action.ts | 2 +- .../{ => group1}/drilldowns/index.ts | 2 +- .../feature_controls/dashboard_security.ts | 2 +- .../feature_controls/dashboard_spaces.ts | 2 +- .../{ => group1}/feature_controls/index.ts | 2 +- .../time_to_visualize_security.ts | 2 +- .../functional/apps/dashboard/group1/index.ts | 17 ++ .../dashboard/{ => group1}/preserve_url.ts | 2 +- .../{ => group1}/reporting/README.md | 4 +- .../reporting/__snapshots__/download_csv.snap | 8 +- .../{ => group1}/reporting/download_csv.ts | 2 +- .../dashboard/{ => group1}/reporting/index.ts | 2 +- .../large_dashboard_preserve_layout.png | Bin .../small_dashboard_preserve_layout.png | Bin .../{ => group1}/reporting/screenshots.ts | 2 +- .../{ => group2}/_async_dashboard.ts | 2 +- .../apps/dashboard/group2/config.ts | 17 ++ .../{ => group2}/dashboard_lens_by_value.ts | 2 +- .../{ => group2}/dashboard_maps_by_value.ts | 2 +- .../{ => group2}/dashboard_tagging.ts | 2 +- .../functional/apps/dashboard/group2/index.ts | 24 ++ .../controls_migration_smoke_test.ts | 2 +- ...rols_dashboard_migration_test_8_0_0.ndjson | 0 ...ens_dashboard_migration_test_7_12_1.ndjson | 0 ...svb_dashboard_migration_test_7_12_1.ndjson | 0 ...svb_dashboard_migration_test_7_13_3.ndjson | 0 ...ize_dashboard_migration_test_7_12_1.ndjson | 0 .../lens_migration_smoke_test.ts | 2 +- .../tsvb_migration_smoke_test.ts | 2 +- .../visualize_migration_smoke_test.ts | 2 +- .../dashboard/{ => group2}/panel_titles.ts | 2 +- .../dashboard/{ => group2}/sync_colors.ts | 2 +- .../test/functional/apps/dashboard/index.ts | 35 --- .../test/functional/apps/data_views/config.ts | 17 ++ .../test/functional/apps/data_views/index.ts | 1 - .../test/functional/apps/dev_tools/config.ts | 17 ++ .../test/functional/apps/dev_tools/index.ts | 2 - .../test/functional/apps/discover/config.ts | 17 ++ x-pack/test/functional/apps/discover/index.ts | 2 - x-pack/test/functional/apps/graph/config.ts | 17 ++ x-pack/test/functional/apps/graph/index.ts | 2 - .../functional/apps/grok_debugger/config.ts | 17 ++ .../functional/apps/grok_debugger/index.ts | 1 - x-pack/test/functional/apps/home/config.ts | 17 ++ x-pack/test/functional/apps/home/index.ts | 1 - .../apps/index_lifecycle_management/config.ts | 17 ++ .../index_lifecycle_management/home_page.ts | 2 +- .../apps/index_lifecycle_management/index.ts | 1 - .../apps/index_management/config.ts | 17 ++ .../functional/apps/index_management/index.ts | 1 - x-pack/test/functional/apps/infra/config.ts | 17 ++ x-pack/test/functional/apps/infra/index.ts | 3 +- .../apps/ingest_pipelines/config.ts | 17 ++ .../functional/apps/ingest_pipelines/index.ts | 1 - x-pack/test/functional/apps/lens/README.md | 7 + .../functional/apps/lens/group1/config.ts | 17 ++ .../apps/lens/{ => group1}/index.ts | 56 +---- .../lens/{ => group1}/persistent_context.ts | 2 +- .../apps/lens/{ => group1}/smokescreen.ts | 2 +- .../apps/lens/{ => group1}/table.ts | 2 +- .../apps/lens/{ => group1}/table_dashboard.ts | 2 +- .../lens/{ => group2}/add_to_dashboard.ts | 2 +- .../functional/apps/lens/group2/config.ts | 17 ++ .../apps/lens/{ => group2}/dashboard.ts | 2 +- .../apps/lens/{ => group2}/epoch_millis.ts | 2 +- .../test/functional/apps/lens/group2/index.ts | 80 ++++++ .../apps/lens/{ => group2}/multi_terms.ts | 2 +- .../apps/lens/{ => group2}/runtime_fields.ts | 2 +- .../lens/{ => group2}/show_underlying_data.ts | 2 +- .../show_underlying_data_dashboard.ts | 2 +- .../apps/lens/{ => group3}/annotations.ts | 2 +- .../apps/lens/{ => group3}/chart_data.ts | 2 +- .../apps/lens/{ => group3}/colors.ts | 2 +- .../functional/apps/lens/group3/config.ts | 17 ++ .../lens/{ => group3}/disable_auto_apply.ts | 2 +- .../apps/lens/{ => group3}/drag_and_drop.ts | 2 +- .../apps/lens/{ => group3}/error_handling.ts | 2 +- .../apps/lens/{ => group3}/formula.ts | 2 +- .../apps/lens/{ => group3}/gauge.ts | 2 +- .../apps/lens/{ => group3}/geo_field.ts | 2 +- .../apps/lens/{ => group3}/heatmap.ts | 2 +- .../test/functional/apps/lens/group3/index.ts | 92 +++++++ .../apps/lens/{ => group3}/inspector.ts | 2 +- .../apps/lens/{ => group3}/lens_reporting.ts | 2 +- .../apps/lens/{ => group3}/lens_tagging.ts | 2 +- .../apps/lens/{ => group3}/metrics.ts | 2 +- .../apps/lens/{ => group3}/reference_lines.ts | 2 +- .../apps/lens/{ => group3}/rollup.ts | 2 +- .../apps/lens/{ => group3}/time_shift.ts | 2 +- .../lens/{ => group3}/tsvb_open_in_lens.ts | 2 +- .../apps/license_management/config.ts | 17 ++ .../apps/license_management/index.ts | 1 - .../test/functional/apps/logstash/config.ts | 17 ++ .../apps/logstash/feature_controls/index.ts | 2 - x-pack/test/functional/apps/logstash/index.js | 2 - .../test/functional/apps/management/config.ts | 17 ++ .../apps/management/feature_controls/index.ts | 2 - .../test/functional/apps/management/index.ts | 2 - x-pack/test/functional/apps/maps/README.md | 7 + .../maps/{ => group1}/auto_fit_to_bounds.js | 0 .../maps/{ => group1}/blended_vector_layer.js | 0 .../functional/apps/maps/group1/config.ts | 17 ++ .../documents_source/docvalue_fields.js | 0 .../{ => group1}/documents_source/index.js | 0 .../documents_source/search_hits.js | 0 .../{ => group1}/documents_source/top_hits.js | 0 .../feature_controls/maps_security.ts | 2 +- .../feature_controls/maps_spaces.ts | 2 +- .../maps/{ => group1}/full_screen_mode.js | 0 .../test/functional/apps/maps/group1/index.js | 72 ++++++ .../maps/{ => group1}/layer_visibility.js | 0 .../apps/maps/{ => group1}/sample_data.js | 0 .../{ => group1}/saved_object_management.js | 0 .../apps/maps/{ => group1}/vector_styling.js | 0 .../functional/apps/maps/group2/config.ts | 17 ++ .../embeddable/add_to_dashboard.js | 0 .../maps/{ => group2}/embeddable/dashboard.js | 0 .../embeddable/embeddable_library.js | 0 .../embeddable/embeddable_state.js | 0 .../embeddable/filter_by_map_extent.js | 0 .../maps/{ => group2}/embeddable/index.js | 0 .../embeddable/save_and_return.js | 0 .../embeddable/tooltip_filter_actions.js | 0 .../maps/{ => group2}/es_geo_grid_source.js | 0 .../test/functional/apps/maps/group2/index.js | 64 +++++ .../functional/apps/maps/group3/config.ts | 17 ++ .../test/functional/apps/maps/group3/index.js | 63 +++++ .../reports/baseline/example_map_report.png | Bin .../reports/baseline/geo_map_report.png | Bin .../apps/maps/{ => group3}/reports/index.ts | 2 +- .../apps/maps/{ => group4}/add_layer_panel.js | 0 .../functional/apps/maps/group4/config.ts | 17 ++ .../apps/maps/{ => group4}/discover.js | 0 .../maps/{ => group4}/es_pew_pew_source.js | 0 .../file_upload/files/cb_2018_us_csa_500k.dbf | Bin .../file_upload/files/cb_2018_us_csa_500k.prj | 0 .../file_upload/files/cb_2018_us_csa_500k.shp | Bin .../file_upload/files/cb_2018_us_csa_500k.shx | Bin .../{ => group4}/file_upload/files/point.json | 0 .../file_upload/files/polygon.json | 0 .../files/world_countries_v7.geo.json | 0 .../maps/{ => group4}/file_upload/geojson.js | 0 .../maps/{ => group4}/file_upload/index.js | 0 .../{ => group4}/file_upload/shapefile.js | 0 .../maps/{ => group4}/file_upload/wizard.js | 0 .../{ => group4}/geofile_wizard_auto_open.ts | 2 +- .../apps/maps/{ => group4}/index.js | 54 +--- .../apps/maps/{ => group4}/joins.js | 0 .../apps/maps/{ => group4}/layer_errors.js | 0 .../{ => group4}/lens/choropleth_chart.ts | 2 +- .../apps/maps/{ => group4}/lens/index.ts | 2 +- .../apps/maps/{ => group4}/mapbox_styles.js | 0 .../maps/{ => group4}/mvt_geotile_grid.js | 0 .../apps/maps/{ => group4}/mvt_joins.ts | 2 +- .../apps/maps/{ => group4}/mvt_scaling.js | 0 .../{ => group4}/visualize_create_menu.js | 0 x-pack/test/functional/apps/ml/README.md | 7 + .../apps/ml/data_visualizer/config.ts | 17 ++ .../data_visualizer/file_data_visualizer.ts | 10 +- .../apps/ml/data_visualizer/index.ts | 32 ++- .../test/functional/apps/ml/group1/config.ts | 17 ++ .../classification_creation.ts | 4 +- .../classification_creation_saved_search.ts | 4 +- .../data_frame_analytics/cloning.ts | 2 +- .../data_frame_analytics/index.ts | 2 +- .../outlier_detection_creation.ts | 4 +- ...outlier_detection_creation_saved_search.ts | 4 +- .../regression_creation.ts | 4 +- .../regression_creation_saved_search.ts | 4 +- .../results_view_content.ts | 2 +- .../functional/apps/ml/{ => group1}/index.ts | 29 +-- .../ml/{ => group1}/model_management/index.ts | 2 +- .../model_management/model_list.ts | 2 +- .../functional/apps/ml/{ => group1}/pages.ts | 4 +- .../permissions/full_ml_access.ts | 14 +- .../apps/ml/{ => group1}/permissions/index.ts | 2 +- .../{ => group1}/permissions/no_ml_access.ts | 4 +- .../permissions/read_ml_access.ts | 14 +- .../anomaly_detection/advanced_job.ts | 2 +- .../aggregated_scripted_job.ts | 2 +- .../anomaly_detection/annotations.ts | 2 +- .../anomaly_detection/anomaly_explorer.ts | 2 +- .../anomaly_detection/categorization_job.ts | 2 +- .../anomaly_detection/custom_urls.ts | 4 +- .../anomaly_detection/date_nanos_job.ts | 2 +- .../anomaly_detection/forecasts.ts | 2 +- .../{ => group2}/anomaly_detection/index.ts | 2 +- .../anomaly_detection/multi_metric_job.ts | 2 +- .../anomaly_detection/population_job.ts | 2 +- .../anomaly_detection/saved_search_job.ts | 2 +- .../anomaly_detection/single_metric_job.ts | 2 +- ...ingle_metric_job_without_datafeed_start.ts | 2 +- .../anomaly_detection/single_metric_viewer.ts | 2 +- .../test/functional/apps/ml/group2/config.ts | 17 ++ .../test/functional/apps/ml/group2/index.ts | 42 ++++ .../test/functional/apps/ml/group3/config.ts | 17 ++ .../anomaly_charts_dashboard_embeddables.ts | 2 +- .../anomaly_embeddables_migration.ts | 2 +- .../ml/{ => group3}/embeddables/constants.ts | 0 .../apps/ml/{ => group3}/embeddables/index.ts | 2 +- .../ml/{ => group3}/feature_controls/index.ts | 2 +- .../feature_controls/ml_security.ts | 2 +- .../feature_controls/ml_spaces.ts | 2 +- .../test/functional/apps/ml/group3/index.ts | 45 ++++ .../settings/calendar_creation.ts | 2 +- .../{ => group3}/settings/calendar_delete.ts | 2 +- .../ml/{ => group3}/settings/calendar_edit.ts | 2 +- .../apps/ml/{ => group3}/settings/common.ts | 5 +- .../settings/filter_list_creation.ts | 2 +- .../settings/filter_list_delete.ts | 2 +- .../{ => group3}/settings/filter_list_edit.ts | 2 +- .../apps/ml/{ => group3}/settings/index.ts | 2 +- .../stack_management_jobs/export_jobs.ts | 2 +- .../anomaly_detection_jobs_7.16.json | 0 .../files_to_import/bad_data.json | 0 .../data_frame_analytics_jobs_7.16.json | 0 .../stack_management_jobs/import_jobs.ts | 10 +- .../stack_management_jobs/index.ts | 2 +- .../stack_management_jobs/manage_spaces.ts | 2 +- .../stack_management_jobs/synchronize.ts | 2 +- .../test/functional/apps/monitoring/config.ts | 17 ++ .../test/functional/apps/monitoring/index.js | 1 - .../functional/apps/remote_clusters/config.ts | 17 ++ .../functional/apps/remote_clusters/index.ts | 2 +- .../test/functional/apps/reporting/README.md | 2 +- .../apps/reporting_management/config.ts | 17 ++ .../apps/reporting_management/index.js | 1 - .../test/functional/apps/rollup_job/config.ts | 17 ++ .../test/functional/apps/rollup_job/index.js | 2 - .../apps/saved_objects_management/config.ts | 17 ++ .../apps/saved_objects_management/index.ts | 2 +- .../apps/security/basic_license/index.ts | 2 - .../test/functional/apps/security/config.ts | 17 ++ x-pack/test/functional/apps/security/index.ts | 2 - .../apps/snapshot_restore/config.ts | 17 ++ .../functional/apps/snapshot_restore/index.ts | 2 +- x-pack/test/functional/apps/spaces/config.ts | 17 ++ x-pack/test/functional/apps/spaces/index.ts | 2 - .../functional/apps/status_page/config.ts | 17 ++ .../test/functional/apps/status_page/index.ts | 2 - .../test/functional/apps/transform/config.ts | 17 ++ .../test/functional/apps/transform/index.ts | 2 +- .../apps/upgrade_assistant/config.ts | 17 ++ .../apps/upgrade_assistant/index.ts | 2 - x-pack/test/functional/apps/uptime/config.ts | 17 ++ x-pack/test/functional/apps/uptime/index.ts | 2 - .../test/functional/apps/visualize/config.ts | 17 ++ .../test/functional/apps/visualize/index.ts | 2 +- x-pack/test/functional/apps/watcher/config.ts | 17 ++ x-pack/test/functional/apps/watcher/index.js | 2 +- .../functional/{config.js => config.base.js} | 44 +--- x-pack/test/functional/config.ccs.ts | 4 +- x-pack/test/functional/config.coverage.js | 22 -- x-pack/test/functional/config.edge.js | 4 +- x-pack/test/functional/config.firefox.js | 12 +- .../test/functional/config_security_basic.ts | 2 +- .../services/ml/common_data_grid.ts | 4 +- x-pack/test/functional_basic/apps/ml/index.ts | 2 +- .../apps/ml/permissions/full_ml_access.ts | 16 +- .../apps/ml/permissions/read_ml_access.ts | 16 +- x-pack/test/functional_basic/config.ts | 4 +- x-pack/test/functional_cors/config.ts | 4 +- x-pack/test/functional_cors/tests/index.ts | 1 - x-pack/test/functional_embedded/config.ts | 4 +- .../test/functional_embedded/tests/index.ts | 1 - .../without_host_configured/index.ts | 2 - .../base_config.ts | 4 +- .../functional_execution_context/config.ts | 2 +- .../tests/index.ts | 1 - .../apps/uptime/index.ts | 1 - x-pack/test/functional_synthetics/config.js | 2 +- .../apps/cases/index.ts | 1 - .../apps/discover/index.ts | 1 - .../apps/ml/alert_flyout.ts | 2 - .../apps/triggers_actions_ui/index.ts | 1 - .../apps/uptime/index.ts | 2 - x-pack/test/functional_with_es_ssl/config.ts | 4 +- x-pack/test/licensing_plugin/config.ts | 4 +- x-pack/test/licensing_plugin/public/index.ts | 1 - x-pack/test/licensing_plugin/server/index.ts | 1 - .../security_and_spaces/tests/index.ts | 2 - x-pack/test/load/config.ts | 2 +- .../basic/tests/index.ts | 1 - .../trial/tests/index.ts | 1 - .../apps/observability/index.ts | 2 - .../with_rac_write.config.ts | 4 +- x-pack/test/osquery_cypress/config.ts | 2 +- x-pack/test/performance/config.playwright.ts | 2 +- .../test_suites/event_log/index.ts | 1 - .../licensed_feature_usage/index.ts | 1 - .../test_suites/platform/index.ts | 1 - .../test_suites/task_manager/index.ts | 1 - x-pack/test/plugin_api_perf/README.md | 2 +- .../test_suites/task_manager/index.ts | 1 - x-pack/test/plugin_functional/config.ts | 4 +- .../test_suites/global_search/index.ts | 1 - .../test_suites/resolver/index.ts | 2 - .../test_suites/timelines/index.ts | 1 - .../reporting_and_security/index.ts | 2 - .../reporting_without_security/index.ts | 2 +- .../index.ts | 2 - .../reporting_and_security.config.ts | 2 +- .../reporting_and_security/index.ts | 2 - .../reporting_without_security/index.ts | 2 - .../security_and_spaces/tests/basic/index.ts | 3 - .../tests/basic/search_strategy.ts | 2 +- .../security_and_spaces/tests/trial/index.ts | 3 - .../spaces_only/tests/basic/index.ts | 3 - .../spaces_only/tests/trial/index.ts | 3 - .../common/config.ts | 4 +- .../security_and_spaces/apis/index.ts | 2 - .../spaces_only/apis/index.ts | 2 - .../security_and_spaces/apis/index.ts | 2 - .../api_integration/tagging_api/apis/index.ts | 2 - .../saved_object_tagging/functional/config.ts | 2 +- .../functional/tests/index.ts | 2 - .../test/saved_objects_field_count/config.ts | 7 +- .../test/saved_objects_field_count/runner.ts | 67 ----- x-pack/test/saved_objects_field_count/test.ts | 73 ++++++ x-pack/test/screenshot_creation/config.ts | 4 +- .../search_sessions_integration/config.ts | 4 +- .../apps/dashboard/async_search/index.ts | 2 - .../apps/dashboard/session_sharing/index.ts | 2 - .../tests/apps/discover/index.ts | 2 - .../tests/apps/lens/index.ts | 2 - .../apps/management/search_sessions/index.ts | 2 - .../tests/anonymous/index.ts | 1 - .../tests/audit/index.ts | 1 - .../tests/http_bearer/index.ts | 1 - .../tests/http_no_auth_providers/index.ts | 1 - .../tests/kerberos/index.ts | 2 - .../tests/login_selector/index.ts | 1 - .../oidc/authorization_code_flow/index.ts | 1 - .../tests/oidc/implicit_flow/index.ts | 1 - .../tests/pki/index.ts | 2 - .../tests/saml/index.ts | 2 - .../tests/session_idle/index.ts | 2 - .../tests/session_invalidate/index.ts | 2 - .../tests/session_lifespan/index.ts | 2 - .../tests/token/index.ts | 1 - .../login_selector.config.ts | 2 +- .../test/security_functional/oidc.config.ts | 2 +- .../test/security_functional/saml.config.ts | 2 +- .../tests/login_selector/index.ts | 2 - .../security_functional/tests/oidc/index.ts | 2 - .../security_functional/tests/saml/index.ts | 2 - .../config.firefox.ts | 2 +- .../test/security_solution_cypress/config.ts | 2 +- .../apps/endpoint/index.ts | 1 - .../test/security_solution_endpoint/config.ts | 4 +- .../apis/index.ts | 2 - .../spaces_api_integration/common/config.ts | 4 +- .../security_and_spaces/apis/index.ts | 2 - .../spaces_only/apis/index.ts | 2 - .../apps/telemetry/index.js | 1 - ...onfig.stack_functional_integration_base.js | 4 +- .../security_and_spaces/tests/basic/index.ts | 3 - .../security_and_spaces/tests/trial/index.ts | 3 - x-pack/test/ui_capabilities/common/config.ts | 2 +- .../security_and_spaces/tests/index.ts | 2 - .../spaces_only/tests/index.ts | 2 - x-pack/test/upgrade/config.ts | 2 +- .../upgrade_assistant_integration/config.js | 2 +- .../upgrade_assistant/index.js | 2 - x-pack/test/usage_collection/config.ts | 4 +- .../test_suites/application_usage/index.ts | 1 - .../stack_management_usage/index.ts | 1 - x-pack/test/visual_regression/config.ts | 2 +- .../visual_regression/tests/canvas/index.js | 1 - .../visual_regression/tests/infra/index.js | 1 - .../visual_regression/tests/maps/index.js | 1 - 850 files changed, 4367 insertions(+), 2774 deletions(-) create mode 100644 .buildkite/ftr_configs.yml delete mode 100755 .buildkite/scripts/steps/checks/validate_ci_groups.sh delete mode 100755 .buildkite/scripts/steps/functional/oss_accessibility.sh delete mode 100755 .buildkite/scripts/steps/functional/oss_cigroup.sh delete mode 100755 .buildkite/scripts/steps/functional/oss_firefox.sh delete mode 100755 .buildkite/scripts/steps/functional/oss_misc.sh delete mode 100755 .buildkite/scripts/steps/functional/xpack_accessibility.sh delete mode 100755 .buildkite/scripts/steps/functional/xpack_cigroup.sh delete mode 100755 .buildkite/scripts/steps/functional/xpack_firefox.sh delete mode 100755 .buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh delete mode 100755 .buildkite/scripts/steps/test/api_integration.sh create mode 100755 .buildkite/scripts/steps/test/ftr_configs.sh delete mode 100644 .buildkite/scripts/steps/test/pick_jest_config_run_order.sh rename .buildkite/scripts/steps/test/{pick_jest_config_run_order.js => pick_test_group_run_order.js} (100%) create mode 100644 .buildkite/scripts/steps/test/pick_test_group_run_order.sh rename .buildkite/scripts/steps/test/{jest_env.sh => test_group_env.sh} (80%) create mode 100644 packages/kbn-test/src/functional_test_runner/lib/config/ftr_configs_manifest.ts rename packages/kbn-test/src/functional_test_runner/lib/config/{read_config_file.test.js => read_config_file.test.ts} (70%) delete mode 100644 packages/kbn-test/src/functional_test_runner/lib/test_metadata.ts rename test/functional/{config.coverage.js => apps/bundles/config.ts} (55%) create mode 100644 test/functional/apps/console/config.ts create mode 100644 test/functional/apps/context/config.ts create mode 100644 test/functional/apps/dashboard/README.md create mode 100644 test/functional/apps/dashboard/group1/config.ts rename test/functional/apps/dashboard/{ => group1}/create_and_add_embeddables.ts (99%) rename test/functional/apps/dashboard/{ => group1}/dashboard_back_button.ts (96%) rename test/functional/apps/dashboard/{ => group1}/dashboard_error_handling.ts (97%) rename test/functional/apps/dashboard/{ => group1}/dashboard_options.ts (96%) rename test/functional/apps/dashboard/{ => group1}/dashboard_query_bar.ts (96%) rename test/functional/apps/dashboard/{ => group1}/dashboard_unsaved_listing.ts (99%) rename test/functional/apps/dashboard/{ => group1}/dashboard_unsaved_state.ts (99%) rename test/functional/apps/dashboard/{ => group1}/data_shared_attributes.ts (98%) rename test/functional/apps/dashboard/{ => group1}/edit_embeddable_redirects.ts (98%) rename test/functional/apps/dashboard/{ => group1}/edit_visualizations.js (100%) rename test/functional/apps/dashboard/{ => group1}/embed_mode.ts (98%) rename test/functional/apps/dashboard/{ => group1}/embeddable_data_grid.ts (97%) rename test/functional/apps/dashboard/{ => group1}/embeddable_rendering.ts (99%) rename test/functional/apps/dashboard/{ => group1}/empty_dashboard.ts (97%) create mode 100644 test/functional/apps/dashboard/group1/index.ts rename test/functional/apps/dashboard/{ => group1}/legacy_urls.ts (98%) rename test/functional/apps/dashboard/{ => group1}/saved_search_embeddable.ts (98%) rename test/functional/apps/dashboard/{ => group1}/share.ts (95%) rename test/functional/apps/dashboard/{ => group1}/url_field_formatter.ts (95%) create mode 100644 test/functional/apps/dashboard/group2/config.ts rename test/functional/apps/dashboard/{ => group2}/dashboard_filter_bar.ts (99%) rename test/functional/apps/dashboard/{ => group2}/dashboard_filtering.ts (99%) rename test/functional/apps/dashboard/{ => group2}/dashboard_grid.ts (96%) rename test/functional/apps/dashboard/{ => group2}/dashboard_saved_query.ts (98%) rename test/functional/apps/dashboard/{ => group2}/dashboard_snapshots.ts (98%) rename test/functional/apps/dashboard/{ => group2}/embeddable_library.ts (97%) rename test/functional/apps/dashboard/{ => group2}/full_screen_mode.ts (98%) create mode 100644 test/functional/apps/dashboard/group2/index.ts rename test/functional/apps/dashboard/{ => group2}/panel_expand_toggle.ts (97%) rename test/functional/apps/dashboard/{ => group2}/view_edit.ts (99%) rename test/functional/apps/dashboard/{ => group3}/bwc_shared_urls.ts (99%) create mode 100644 test/functional/apps/dashboard/group3/config.ts rename test/functional/apps/dashboard/{ => group3}/copy_panel_to.ts (98%) rename test/functional/apps/dashboard/{ => group3}/dashboard_state.ts (98%) rename test/functional/apps/dashboard/{ => group3}/dashboard_time_picker.ts (97%) create mode 100644 test/functional/apps/dashboard/group3/index.ts rename test/functional/apps/dashboard/{ => group3}/panel_cloning.ts (96%) rename test/functional/apps/dashboard/{ => group3}/panel_context_menu.ts (98%) rename test/functional/apps/dashboard/{ => group3}/panel_replacing.ts (97%) create mode 100644 test/functional/apps/dashboard/group4/config.ts rename test/functional/apps/dashboard/{ => group4}/dashboard_clone.ts (97%) rename test/functional/apps/dashboard/{ => group4}/dashboard_listing.ts (99%) rename test/functional/apps/dashboard/{ => group4}/dashboard_save.ts (98%) rename test/functional/apps/dashboard/{ => group4}/dashboard_time.ts (98%) create mode 100644 test/functional/apps/dashboard/group4/index.ts create mode 100644 test/functional/apps/dashboard/group5/config.ts create mode 100644 test/functional/apps/dashboard/group5/index.ts delete mode 100644 test/functional/apps/dashboard/index.ts create mode 100644 test/functional/apps/dashboard_elements/config.ts create mode 100644 test/functional/apps/discover/config.ts create mode 100644 test/functional/apps/getting_started/config.ts create mode 100644 test/functional/apps/home/config.ts create mode 100644 test/functional/apps/management/config.ts create mode 100644 test/functional/apps/saved_objects_management/config.ts create mode 100644 test/functional/apps/status_page/config.ts create mode 100644 test/functional/apps/visualize/README.md rename test/functional/apps/visualize/{ => group1}/_chart_types.ts (96%) rename test/functional/apps/visualize/{ => group1}/_data_table.ts (99%) rename test/functional/apps/visualize/{ => group1}/_data_table_nontimeindex.ts (98%) rename test/functional/apps/visualize/{ => group1}/_data_table_notimeindex_filters.ts (97%) rename test/functional/apps/visualize/{ => group1}/_embedding_chart.ts (98%) create mode 100644 test/functional/apps/visualize/group1/config.ts create mode 100644 test/functional/apps/visualize/group1/index.ts rename test/functional/apps/visualize/{ => group2}/_experimental_vis.ts (97%) rename test/functional/apps/visualize/{ => group2}/_gauge_chart.ts (98%) rename test/functional/apps/visualize/{ => group2}/_heatmap_chart.ts (98%) rename test/functional/apps/visualize/{ => group2}/_histogram_request_start.ts (98%) rename test/functional/apps/visualize/{ => group2}/_inspector.ts (98%) rename test/functional/apps/visualize/{ => group2}/_metric_chart.ts (99%) create mode 100644 test/functional/apps/visualize/group2/config.ts create mode 100644 test/functional/apps/visualize/group2/index.ts rename test/functional/apps/visualize/{ => group3}/_add_to_dashboard.ts (99%) rename test/functional/apps/visualize/{ => group3}/_lab_mode.ts (97%) rename test/functional/apps/visualize/{ => group3}/_linked_saved_searches.ts (98%) rename test/functional/apps/visualize/{ => group3}/_pie_chart.ts (95%) rename test/functional/apps/visualize/{ => group3}/_shared_item.ts (95%) rename test/functional/apps/visualize/{ => group3}/_visualize_listing.ts (98%) create mode 100644 test/functional/apps/visualize/group3/config.ts create mode 100644 test/functional/apps/visualize/group3/index.ts rename test/functional/apps/visualize/{ => group4}/_tsvb_chart.ts (99%) create mode 100644 test/functional/apps/visualize/group4/config.ts create mode 100644 test/functional/apps/visualize/group4/index.ts rename test/functional/apps/visualize/{ => group5}/_tsvb_time_series.ts (99%) create mode 100644 test/functional/apps/visualize/group5/config.ts create mode 100644 test/functional/apps/visualize/group5/index.ts rename test/functional/apps/visualize/{ => group6}/_tag_cloud.ts (99%) rename test/functional/apps/visualize/{ => group6}/_tsvb_markdown.ts (99%) rename test/functional/apps/visualize/{ => group6}/_tsvb_table.ts (99%) rename test/functional/apps/visualize/{ => group6}/_vega_chart.ts (99%) create mode 100644 test/functional/apps/visualize/group6/config.ts create mode 100644 test/functional/apps/visualize/group6/index.ts delete mode 100644 test/functional/apps/visualize/index.ts rename test/functional/apps/visualize/{ => replaced_vislib_chart_types}/_area_chart.ts (99%) rename test/functional/apps/visualize/{ => replaced_vislib_chart_types}/_line_chart_split_chart.ts (99%) rename test/functional/apps/visualize/{ => replaced_vislib_chart_types}/_line_chart_split_series.ts (99%) rename test/functional/apps/visualize/{ => replaced_vislib_chart_types}/_point_series_options.ts (99%) rename test/functional/apps/visualize/{ => replaced_vislib_chart_types}/_timelion.ts (99%) rename test/functional/apps/visualize/{ => replaced_vislib_chart_types}/_vertical_bar_chart.ts (99%) rename test/functional/apps/visualize/{ => replaced_vislib_chart_types}/_vertical_bar_chart_nontimeindex.ts (99%) create mode 100644 test/functional/apps/visualize/replaced_vislib_chart_types/config.ts create mode 100644 test/functional/apps/visualize/replaced_vislib_chart_types/index.ts rename test/functional/{config.js => config.base.js} (95%) rename test/server_integration/{config.js => config.base.js} (97%) delete mode 100644 x-pack/scripts/functional_tests.js rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/config.ts (82%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/create.ts (99%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/delete.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/disable.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/enable.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/execution_status.ts (95%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/find.ts (99%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/get.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/get_alert_state.ts (97%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/get_alert_summary.ts (97%) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group1}/tests/alerting/rule_types.ts (96%) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/index.ts create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group2/config.ts rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/email.ts (99%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/es_index.ts (99%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/es_index_preconfigured.ts (96%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/jira.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/pagerduty.ts (96%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/resilient.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/server_log.ts (96%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/servicenow_itom.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/servicenow_itsm.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/servicenow_sir.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/slack.ts (96%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/swimlane.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/webhook.ts (97%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/builtin_action_types/xmatters.ts (96%) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/config.ts rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/connector_types.ts (91%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/create.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/delete.ts (97%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/execute.ts (99%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/get.ts (96%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/get_all.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/index.ts (93%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/manual/pr_40694.js (100%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/actions/update.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/alerts.ts (99%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/event_log.ts (92%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/excluded.ts (94%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/health.ts (97%) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/mustache_templates.ts (92%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/mute_all.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/mute_instance.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/rbac_legacy.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/snooze.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/unmute_all.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/unmute_instance.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/unsnooze.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/update.ts (99%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/alerting/update_api_key.ts (98%) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/index.ts rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/telemetry/actions_telemetry.ts (98%) rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/telemetry/alerting_telemetry.ts (99%) create mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/config.ts rename x-pack/test/alerting_api_integration/security_and_spaces/{ => group2}/tests/telemetry/index.ts (84%) rename x-pack/test/alerting_api_integration/security_and_spaces/{tests/index.ts => setup.ts} (73%) delete mode 100644 x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/index.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/README.md rename x-pack/test/detection_engine_api_integration/security_and_spaces/{config.ts => config.base.ts} (87%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/add_actions.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/add_prepackaged_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/aliases.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/check_privileges.ts (100%) rename x-pack/test/{functional_embedded/config.firefox.ts => detection_engine_api_integration/security_and_spaces/group1/config.ts} (54%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/create_index.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/create_ml.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/create_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/create_rules_bulk.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/create_signals_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/create_threat_matching.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/delete_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/delete_rules_bulk.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/delete_signals_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/export_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/finalize_signals_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/find_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/generating_signals.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/get_prepackaged_rules_status.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/get_rule_execution_events.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/get_signals_migration_status.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/ignore_fields.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/import_export_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/import_rules.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/legacy_actions_migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/migrations.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/open_close_signals.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/patch_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/patch_rules_bulk.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/perform_bulk_action.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/preview_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/read_privileges.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/read_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/resolve_read_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/runtime.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/template_data/execution_events.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/throttle.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/timestamps.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/update_actions.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/update_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group1}/update_rules_bulk.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group2/config.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group2}/create_endpoint_exceptions.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group2/index.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group3/config.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group3}/create_exceptions.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group3/index.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group4/index.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/README.md (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/index.ts (51%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/task_based/all_types.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/task_based/detection_rules.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/task_based/security_lists.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/usage_collector/all_types.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/usage_collector/detection_rule_status.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group4}/telemetry/usage_collector/detection_rules.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group5/index.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group5}/keyword_family/README.md (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group5}/keyword_family/const_keyword.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group5}/keyword_family/index.ts (68%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group5}/keyword_family/keyword.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group5}/keyword_family/keyword_mixed_with_const.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group6}/alerts/alerts_compatibility.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group6}/alerts/index.ts (79%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group6/config.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group6/index.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group7/config.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group7}/exception_operators_data_types/date.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group7}/exception_operators_data_types/double.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group7}/exception_operators_data_types/float.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/index.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group7}/exception_operators_data_types/integer.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group7/index.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group8/config.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/index.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group8}/exception_operators_data_types/keyword.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group8}/exception_operators_data_types/keyword_array.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group8}/exception_operators_data_types/long.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group8}/exception_operators_data_types/text.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group8/index.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group9/config.ts create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/index.ts rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group9}/exception_operators_data_types/ip.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group9}/exception_operators_data_types/ip_array.ts (100%) rename x-pack/test/detection_engine_api_integration/security_and_spaces/{tests => group9}/exception_operators_data_types/text_array.ts (100%) create mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/group9/index.ts delete mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/README.md delete mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/index.ts delete mode 100644 x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts create mode 100644 x-pack/test/functional/apps/advanced_settings/config.ts create mode 100644 x-pack/test/functional/apps/api_keys/config.ts create mode 100644 x-pack/test/functional/apps/apm/config.ts create mode 100644 x-pack/test/functional/apps/canvas/config.ts create mode 100644 x-pack/test/functional/apps/cross_cluster_replication/config.ts create mode 100644 x-pack/test/functional/apps/dashboard/README.md create mode 100644 x-pack/test/functional/apps/dashboard/group1/config.ts rename x-pack/test/functional/apps/dashboard/{ => group1}/drilldowns/dashboard_to_dashboard_drilldown.ts (99%) rename x-pack/test/functional/apps/dashboard/{ => group1}/drilldowns/dashboard_to_url_drilldown.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group1}/drilldowns/explore_data_chart_action.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group1}/drilldowns/explore_data_panel_action.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group1}/drilldowns/index.ts (95%) rename x-pack/test/functional/apps/dashboard/{ => group1}/feature_controls/dashboard_security.ts (99%) rename x-pack/test/functional/apps/dashboard/{ => group1}/feature_controls/dashboard_spaces.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group1}/feature_controls/index.ts (89%) rename x-pack/test/functional/apps/dashboard/{ => group1}/feature_controls/time_to_visualize_security.ts (99%) create mode 100644 x-pack/test/functional/apps/dashboard/group1/index.ts rename x-pack/test/functional/apps/dashboard/{ => group1}/preserve_url.ts (97%) rename x-pack/test/functional/apps/dashboard/{ => group1}/reporting/README.md (92%) rename x-pack/test/functional/apps/dashboard/{ => group1}/reporting/__snapshots__/download_csv.snap (99%) rename x-pack/test/functional/apps/dashboard/{ => group1}/reporting/download_csv.ts (99%) rename x-pack/test/functional/apps/dashboard/{ => group1}/reporting/index.ts (86%) rename x-pack/test/functional/apps/dashboard/{ => group1}/reporting/reports/baseline/large_dashboard_preserve_layout.png (100%) rename x-pack/test/functional/apps/dashboard/{ => group1}/reporting/reports/baseline/small_dashboard_preserve_layout.png (100%) rename x-pack/test/functional/apps/dashboard/{ => group1}/reporting/screenshots.ts (99%) rename x-pack/test/functional/apps/dashboard/{ => group2}/_async_dashboard.ts (98%) create mode 100644 x-pack/test/functional/apps/dashboard/group2/config.ts rename x-pack/test/functional/apps/dashboard/{ => group2}/dashboard_lens_by_value.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group2}/dashboard_maps_by_value.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group2}/dashboard_tagging.ts (98%) create mode 100644 x-pack/test/functional/apps/dashboard/group2/index.ts rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/controls_migration_smoke_test.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/exports/controls_dashboard_migration_test_8_0_0.ndjson (100%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/exports/lens_dashboard_migration_test_7_12_1.ndjson (100%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_12_1.ndjson (100%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_13_3.ndjson (100%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/exports/visualize_dashboard_migration_test_7_12_1.ndjson (100%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/lens_migration_smoke_test.ts (97%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/tsvb_migration_smoke_test.ts (98%) rename x-pack/test/functional/apps/dashboard/{ => group2}/migration_smoke_tests/visualize_migration_smoke_test.ts (97%) rename x-pack/test/functional/apps/dashboard/{ => group2}/panel_titles.ts (99%) rename x-pack/test/functional/apps/dashboard/{ => group2}/sync_colors.ts (98%) delete mode 100644 x-pack/test/functional/apps/dashboard/index.ts create mode 100644 x-pack/test/functional/apps/data_views/config.ts create mode 100644 x-pack/test/functional/apps/dev_tools/config.ts create mode 100644 x-pack/test/functional/apps/discover/config.ts create mode 100644 x-pack/test/functional/apps/graph/config.ts create mode 100644 x-pack/test/functional/apps/grok_debugger/config.ts create mode 100644 x-pack/test/functional/apps/home/config.ts create mode 100644 x-pack/test/functional/apps/index_lifecycle_management/config.ts create mode 100644 x-pack/test/functional/apps/index_management/config.ts create mode 100644 x-pack/test/functional/apps/infra/config.ts create mode 100644 x-pack/test/functional/apps/ingest_pipelines/config.ts create mode 100644 x-pack/test/functional/apps/lens/README.md create mode 100644 x-pack/test/functional/apps/lens/group1/config.ts rename x-pack/test/functional/apps/lens/{ => group1}/index.ts (55%) rename x-pack/test/functional/apps/lens/{ => group1}/persistent_context.ts (99%) rename x-pack/test/functional/apps/lens/{ => group1}/smokescreen.ts (99%) rename x-pack/test/functional/apps/lens/{ => group1}/table.ts (99%) rename x-pack/test/functional/apps/lens/{ => group1}/table_dashboard.ts (97%) rename x-pack/test/functional/apps/lens/{ => group2}/add_to_dashboard.ts (99%) create mode 100644 x-pack/test/functional/apps/lens/group2/config.ts rename x-pack/test/functional/apps/lens/{ => group2}/dashboard.ts (99%) rename x-pack/test/functional/apps/lens/{ => group2}/epoch_millis.ts (97%) create mode 100644 x-pack/test/functional/apps/lens/group2/index.ts rename x-pack/test/functional/apps/lens/{ => group2}/multi_terms.ts (97%) rename x-pack/test/functional/apps/lens/{ => group2}/runtime_fields.ts (97%) rename x-pack/test/functional/apps/lens/{ => group2}/show_underlying_data.ts (99%) rename x-pack/test/functional/apps/lens/{ => group2}/show_underlying_data_dashboard.ts (98%) rename x-pack/test/functional/apps/lens/{ => group3}/annotations.ts (97%) rename x-pack/test/functional/apps/lens/{ => group3}/chart_data.ts (98%) rename x-pack/test/functional/apps/lens/{ => group3}/colors.ts (96%) create mode 100644 x-pack/test/functional/apps/lens/group3/config.ts rename x-pack/test/functional/apps/lens/{ => group3}/disable_auto_apply.ts (98%) rename x-pack/test/functional/apps/lens/{ => group3}/drag_and_drop.ts (99%) rename x-pack/test/functional/apps/lens/{ => group3}/error_handling.ts (97%) rename x-pack/test/functional/apps/lens/{ => group3}/formula.ts (99%) rename x-pack/test/functional/apps/lens/{ => group3}/gauge.ts (98%) rename x-pack/test/functional/apps/lens/{ => group3}/geo_field.ts (95%) rename x-pack/test/functional/apps/lens/{ => group3}/heatmap.ts (99%) create mode 100644 x-pack/test/functional/apps/lens/group3/index.ts rename x-pack/test/functional/apps/lens/{ => group3}/inspector.ts (96%) rename x-pack/test/functional/apps/lens/{ => group3}/lens_reporting.ts (96%) rename x-pack/test/functional/apps/lens/{ => group3}/lens_tagging.ts (98%) rename x-pack/test/functional/apps/lens/{ => group3}/metrics.ts (97%) rename x-pack/test/functional/apps/lens/{ => group3}/reference_lines.ts (98%) rename x-pack/test/functional/apps/lens/{ => group3}/rollup.ts (98%) rename x-pack/test/functional/apps/lens/{ => group3}/time_shift.ts (97%) rename x-pack/test/functional/apps/lens/{ => group3}/tsvb_open_in_lens.ts (99%) create mode 100644 x-pack/test/functional/apps/license_management/config.ts create mode 100644 x-pack/test/functional/apps/logstash/config.ts create mode 100644 x-pack/test/functional/apps/management/config.ts create mode 100644 x-pack/test/functional/apps/maps/README.md rename x-pack/test/functional/apps/maps/{ => group1}/auto_fit_to_bounds.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/blended_vector_layer.js (100%) create mode 100644 x-pack/test/functional/apps/maps/group1/config.ts rename x-pack/test/functional/apps/maps/{ => group1}/documents_source/docvalue_fields.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/documents_source/index.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/documents_source/search_hits.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/documents_source/top_hits.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/feature_controls/maps_security.ts (99%) rename x-pack/test/functional/apps/maps/{ => group1}/feature_controls/maps_spaces.ts (98%) rename x-pack/test/functional/apps/maps/{ => group1}/full_screen_mode.js (100%) create mode 100644 x-pack/test/functional/apps/maps/group1/index.js rename x-pack/test/functional/apps/maps/{ => group1}/layer_visibility.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/sample_data.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/saved_object_management.js (100%) rename x-pack/test/functional/apps/maps/{ => group1}/vector_styling.js (100%) create mode 100644 x-pack/test/functional/apps/maps/group2/config.ts rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/add_to_dashboard.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/dashboard.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/embeddable_library.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/embeddable_state.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/filter_by_map_extent.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/index.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/save_and_return.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/embeddable/tooltip_filter_actions.js (100%) rename x-pack/test/functional/apps/maps/{ => group2}/es_geo_grid_source.js (100%) create mode 100644 x-pack/test/functional/apps/maps/group2/index.js create mode 100644 x-pack/test/functional/apps/maps/group3/config.ts create mode 100644 x-pack/test/functional/apps/maps/group3/index.js rename x-pack/test/functional/apps/maps/{ => group3}/reports/baseline/example_map_report.png (100%) rename x-pack/test/functional/apps/maps/{ => group3}/reports/baseline/geo_map_report.png (100%) rename x-pack/test/functional/apps/maps/{ => group3}/reports/index.ts (97%) rename x-pack/test/functional/apps/maps/{ => group4}/add_layer_panel.js (100%) create mode 100644 x-pack/test/functional/apps/maps/group4/config.ts rename x-pack/test/functional/apps/maps/{ => group4}/discover.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/es_pew_pew_source.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/files/cb_2018_us_csa_500k.dbf (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/files/cb_2018_us_csa_500k.prj (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/files/cb_2018_us_csa_500k.shp (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/files/cb_2018_us_csa_500k.shx (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/files/point.json (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/files/polygon.json (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/files/world_countries_v7.geo.json (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/geojson.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/index.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/shapefile.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/file_upload/wizard.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/geofile_wizard_auto_open.ts (95%) rename x-pack/test/functional/apps/maps/{ => group4}/index.js (57%) rename x-pack/test/functional/apps/maps/{ => group4}/joins.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/layer_errors.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/lens/choropleth_chart.ts (97%) rename x-pack/test/functional/apps/maps/{ => group4}/lens/index.ts (85%) rename x-pack/test/functional/apps/maps/{ => group4}/mapbox_styles.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/mvt_geotile_grid.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/mvt_joins.ts (98%) rename x-pack/test/functional/apps/maps/{ => group4}/mvt_scaling.js (100%) rename x-pack/test/functional/apps/maps/{ => group4}/visualize_create_menu.js (100%) create mode 100644 x-pack/test/functional/apps/ml/README.md create mode 100644 x-pack/test/functional/apps/ml/data_visualizer/config.ts create mode 100644 x-pack/test/functional/apps/ml/group1/config.ts rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/classification_creation.ts (98%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/classification_creation_saved_search.ts (98%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/cloning.ts (99%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/index.ts (93%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/outlier_detection_creation.ts (98%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/outlier_detection_creation_saved_search.ts (99%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/regression_creation.ts (98%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/regression_creation_saved_search.ts (98%) rename x-pack/test/functional/apps/ml/{ => group1}/data_frame_analytics/results_view_content.ts (99%) rename x-pack/test/functional/apps/ml/{ => group1}/index.ts (64%) rename x-pack/test/functional/apps/ml/{ => group1}/model_management/index.ts (86%) rename x-pack/test/functional/apps/ml/{ => group1}/model_management/model_list.ts (99%) rename x-pack/test/functional/apps/ml/{ => group1}/pages.ts (94%) rename x-pack/test/functional/apps/ml/{ => group1}/permissions/full_ml_access.ts (98%) rename x-pack/test/functional/apps/ml/{ => group1}/permissions/index.ts (88%) rename x-pack/test/functional/apps/ml/{ => group1}/permissions/no_ml_access.ts (93%) rename x-pack/test/functional/apps/ml/{ => group1}/permissions/read_ml_access.ts (98%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/advanced_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/aggregated_scripted_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/annotations.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/anomaly_explorer.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/categorization_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/custom_urls.ts (98%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/date_nanos_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/forecasts.ts (98%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/index.ts (94%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/multi_metric_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/population_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/saved_search_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/single_metric_job.ts (99%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/single_metric_job_without_datafeed_start.ts (98%) rename x-pack/test/functional/apps/ml/{ => group2}/anomaly_detection/single_metric_viewer.ts (99%) create mode 100644 x-pack/test/functional/apps/ml/group2/config.ts create mode 100644 x-pack/test/functional/apps/ml/group2/index.ts create mode 100644 x-pack/test/functional/apps/ml/group3/config.ts rename x-pack/test/functional/apps/ml/{ => group3}/embeddables/anomaly_charts_dashboard_embeddables.ts (98%) rename x-pack/test/functional/apps/ml/{ => group3}/embeddables/anomaly_embeddables_migration.ts (98%) rename x-pack/test/functional/apps/ml/{ => group3}/embeddables/constants.ts (100%) rename x-pack/test/functional/apps/ml/{ => group3}/embeddables/index.ts (88%) rename x-pack/test/functional/apps/ml/{ => group3}/feature_controls/index.ts (87%) rename x-pack/test/functional/apps/ml/{ => group3}/feature_controls/ml_security.ts (98%) rename x-pack/test/functional/apps/ml/{ => group3}/feature_controls/ml_spaces.ts (97%) create mode 100644 x-pack/test/functional/apps/ml/group3/index.ts rename x-pack/test/functional/apps/ml/{ => group3}/settings/calendar_creation.ts (98%) rename x-pack/test/functional/apps/ml/{ => group3}/settings/calendar_delete.ts (96%) rename x-pack/test/functional/apps/ml/{ => group3}/settings/calendar_edit.ts (98%) rename x-pack/test/functional/apps/ml/{ => group3}/settings/common.ts (89%) rename x-pack/test/functional/apps/ml/{ => group3}/settings/filter_list_creation.ts (96%) rename x-pack/test/functional/apps/ml/{ => group3}/settings/filter_list_delete.ts (96%) rename x-pack/test/functional/apps/ml/{ => group3}/settings/filter_list_edit.ts (97%) rename x-pack/test/functional/apps/ml/{ => group3}/settings/index.ts (91%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/export_jobs.ts (99%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/files_to_import/anomaly_detection_jobs_7.16.json (100%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/files_to_import/bad_data.json (100%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/files_to_import/data_frame_analytics_jobs_7.16.json (100%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/import_jobs.ts (92%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/index.ts (89%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/manage_spaces.ts (99%) rename x-pack/test/functional/apps/ml/{ => group3}/stack_management_jobs/synchronize.ts (98%) create mode 100644 x-pack/test/functional/apps/monitoring/config.ts create mode 100644 x-pack/test/functional/apps/remote_clusters/config.ts create mode 100644 x-pack/test/functional/apps/reporting_management/config.ts create mode 100644 x-pack/test/functional/apps/rollup_job/config.ts create mode 100644 x-pack/test/functional/apps/saved_objects_management/config.ts create mode 100644 x-pack/test/functional/apps/security/config.ts create mode 100644 x-pack/test/functional/apps/snapshot_restore/config.ts create mode 100644 x-pack/test/functional/apps/spaces/config.ts create mode 100644 x-pack/test/functional/apps/status_page/config.ts create mode 100644 x-pack/test/functional/apps/transform/config.ts create mode 100644 x-pack/test/functional/apps/upgrade_assistant/config.ts create mode 100644 x-pack/test/functional/apps/uptime/config.ts create mode 100644 x-pack/test/functional/apps/visualize/config.ts create mode 100644 x-pack/test/functional/apps/watcher/config.ts rename x-pack/test/functional/{config.js => config.base.js} (88%) delete mode 100644 x-pack/test/functional/config.coverage.js delete mode 100644 x-pack/test/saved_objects_field_count/runner.ts create mode 100644 x-pack/test/saved_objects_field_count/test.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml new file mode 100644 index 0000000000000..26dd1b4bcfc3c --- /dev/null +++ b/.buildkite/ftr_configs.yml @@ -0,0 +1,236 @@ +disabled: + # TODO: Enable once RBAC timeline search strategy test updated + - x-pack/test/timeline/security_and_spaces/config_basic.ts + + # Base config files, only necessary to inform config finding script + - test/functional/config.base.js + - x-pack/test/functional/config.base.js + - x-pack/test/detection_engine_api_integration/security_and_spaces/config.base.ts + - x-pack/test/functional_enterprise_search/base_config.ts + - test/server_integration/config.base.js + + # QA suites that are run out-of-band + - x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js + - x-pack/test/upgrade/config.ts + - test/functional/config.edge.js + - x-pack/test/functional/config.edge.js + + # Cypress configs, for now these are still run manually + - x-pack/test/fleet_cypress/cli_config.ts + - x-pack/test/fleet_cypress/config.ts + - x-pack/test/fleet_cypress/visual_config.ts + - x-pack/test/functional_enterprise_search/cypress.config.ts + - x-pack/test/osquery_cypress/cli_config.ts + - x-pack/test/osquery_cypress/config.ts + - x-pack/test/osquery_cypress/visual_config.ts + - x-pack/test/security_solution_cypress/cases_cli_config.ts + - x-pack/test/security_solution_cypress/ccs_config.ts + - x-pack/test/security_solution_cypress/cli_config.ts + - x-pack/test/security_solution_cypress/config.firefox.ts + - x-pack/test/security_solution_cypress/config.ts + - x-pack/test/security_solution_cypress/response_ops_cli_config.ts + - x-pack/test/security_solution_cypress/upgrade_config.ts + - x-pack/test/security_solution_cypress/visual_config.ts + - x-pack/test/functional_enterprise_search/with_host_configured.config.ts + - x-pack/plugins/apm/ftr_e2e/ftr_config_run.ts + - x-pack/plugins/apm/ftr_e2e/ftr_config.ts + - x-pack/plugins/synthetics/e2e/config.ts + + # Configs that exist but weren't running in CI when this file was introduced + - test/visual_regression/config.ts + - x-pack/test/visual_regression/config.ts + - x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/config.ts + - x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/config.ts + - x-pack/test/alerting_api_integration/spaces_only_legacy/config.ts + - x-pack/test/banners_functional/config.ts + - x-pack/test/cloud_integration/config.ts + - x-pack/test/performance/config.playwright.ts + - x-pack/test/load/config.ts + - x-pack/test/plugin_api_perf/config.js + - x-pack/test/screenshot_creation/config.ts + +enabled: + - test/accessibility/config.ts + - test/analytics/config.ts + - test/api_integration/config.js + - test/examples/config.js + - test/functional/apps/bundles/config.ts + - test/functional/apps/console/config.ts + - test/functional/apps/context/config.ts + - test/functional/apps/dashboard_elements/config.ts + - test/functional/apps/dashboard/group1/config.ts + - test/functional/apps/dashboard/group2/config.ts + - test/functional/apps/dashboard/group3/config.ts + - test/functional/apps/dashboard/group4/config.ts + - test/functional/apps/dashboard/group5/config.ts + - test/functional/apps/discover/config.ts + - test/functional/apps/getting_started/config.ts + - test/functional/apps/home/config.ts + - test/functional/apps/management/config.ts + - test/functional/apps/saved_objects_management/config.ts + - test/functional/apps/status_page/config.ts + - test/functional/apps/visualize/group1/config.ts + - test/functional/apps/visualize/group2/config.ts + - test/functional/apps/visualize/group3/config.ts + - test/functional/apps/visualize/group4/config.ts + - test/functional/apps/visualize/group5/config.ts + - test/functional/apps/visualize/group6/config.ts + - test/functional/apps/visualize/replaced_vislib_chart_types/config.ts + - test/functional/config.ccs.ts + - test/functional/config.firefox.js + - test/interactive_setup_api_integration/enrollment_flow.config.ts + - test/interactive_setup_api_integration/manual_configuration_flow_without_tls.config.ts + - test/interactive_setup_api_integration/manual_configuration_flow.config.ts + - test/interactive_setup_functional/enrollment_token.config.ts + - test/interactive_setup_functional/manual_configuration_without_security.config.ts + - test/interactive_setup_functional/manual_configuration_without_tls.config.ts + - test/interactive_setup_functional/manual_configuration.config.ts + - test/interpreter_functional/config.ts + - test/new_visualize_flow/config.ts + - test/plugin_functional/config.ts + - test/server_integration/http/platform/config.status.ts + - test/server_integration/http/platform/config.ts + - test/server_integration/http/ssl_redirect/config.js + - test/server_integration/http/ssl_with_p12_intermediate/config.js + - test/server_integration/http/ssl_with_p12/config.js + - test/server_integration/http/ssl/config.js + - test/ui_capabilities/newsfeed_err/config.ts + - x-pack/test/accessibility/config.ts + - x-pack/test/alerting_api_integration/basic/config.ts + - x-pack/test/alerting_api_integration/security_and_spaces/group1/config.ts + - x-pack/test/alerting_api_integration/security_and_spaces/group2/config.ts + - x-pack/test/alerting_api_integration/spaces_only/config.ts + - x-pack/test/api_integration_basic/config.ts + - x-pack/test/api_integration/config_security_basic.ts + - x-pack/test/api_integration/config_security_trial.ts + - x-pack/test/api_integration/config.ts + - x-pack/test/apm_api_integration/basic/config.ts + - x-pack/test/apm_api_integration/rules/config.ts + - x-pack/test/apm_api_integration/trial/config.ts + - x-pack/test/cases_api_integration/security_and_spaces/config_basic.ts + - x-pack/test/cases_api_integration/security_and_spaces/config_trial.ts + - x-pack/test/cases_api_integration/spaces_only/config.ts + - x-pack/test/detection_engine_api_integration/basic/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group1/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group2/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group3/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group6/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group7/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group8/config.ts + - x-pack/test/detection_engine_api_integration/security_and_spaces/group9/config.ts + - x-pack/test/encrypted_saved_objects_api_integration/config.ts + - x-pack/test/endpoint_api_integration_no_ingest/config.ts + - x-pack/test/examples/config.ts + - x-pack/test/fleet_api_integration/config.ts + - x-pack/test/fleet_functional/config.ts + - x-pack/test/functional_basic/config.ts + - x-pack/test/functional_cors/config.ts + - x-pack/test/functional_embedded/config.ts + - x-pack/test/functional_enterprise_search/without_host_configured.config.ts + - x-pack/test/functional_execution_context/config.ts + - x-pack/test/functional_synthetics/config.js + - x-pack/test/functional_with_es_ssl/config.ts + - x-pack/test/functional/apps/advanced_settings/config.ts + - x-pack/test/functional/apps/api_keys/config.ts + - x-pack/test/functional/apps/apm/config.ts + - x-pack/test/functional/apps/canvas/config.ts + - x-pack/test/functional/apps/cross_cluster_replication/config.ts + - x-pack/test/functional/apps/dashboard/group1/config.ts + - x-pack/test/functional/apps/dashboard/group2/config.ts + - x-pack/test/functional/apps/data_views/config.ts + - x-pack/test/functional/apps/dev_tools/config.ts + - x-pack/test/functional/apps/discover/config.ts + - x-pack/test/functional/apps/graph/config.ts + - x-pack/test/functional/apps/grok_debugger/config.ts + - x-pack/test/functional/apps/home/config.ts + - x-pack/test/functional/apps/index_lifecycle_management/config.ts + - x-pack/test/functional/apps/index_management/config.ts + - x-pack/test/functional/apps/infra/config.ts + - x-pack/test/functional/apps/ingest_pipelines/config.ts + - x-pack/test/functional/apps/lens/group1/config.ts + - x-pack/test/functional/apps/lens/group2/config.ts + - x-pack/test/functional/apps/lens/group3/config.ts + - x-pack/test/functional/apps/license_management/config.ts + - x-pack/test/functional/apps/logstash/config.ts + - x-pack/test/functional/apps/management/config.ts + - x-pack/test/functional/apps/maps/group1/config.ts + - x-pack/test/functional/apps/maps/group2/config.ts + - x-pack/test/functional/apps/maps/group3/config.ts + - x-pack/test/functional/apps/maps/group4/config.ts + - x-pack/test/functional/apps/ml/data_visualizer/config.ts + - x-pack/test/functional/apps/ml/group1/config.ts + - x-pack/test/functional/apps/ml/group2/config.ts + - x-pack/test/functional/apps/ml/group3/config.ts + - x-pack/test/functional/apps/monitoring/config.ts + - x-pack/test/functional/apps/remote_clusters/config.ts + - x-pack/test/functional/apps/reporting_management/config.ts + - x-pack/test/functional/apps/rollup_job/config.ts + - x-pack/test/functional/apps/saved_objects_management/config.ts + - x-pack/test/functional/apps/security/config.ts + - x-pack/test/functional/apps/snapshot_restore/config.ts + - x-pack/test/functional/apps/spaces/config.ts + - x-pack/test/functional/apps/status_page/config.ts + - x-pack/test/functional/apps/transform/config.ts + - x-pack/test/functional/apps/upgrade_assistant/config.ts + - x-pack/test/functional/apps/uptime/config.ts + - x-pack/test/functional/apps/visualize/config.ts + - x-pack/test/functional/apps/watcher/config.ts + - x-pack/test/functional/config_security_basic.ts + - x-pack/test/functional/config.ccs.ts + - x-pack/test/functional/config.firefox.js + - x-pack/test/licensing_plugin/config.public.ts + - x-pack/test/licensing_plugin/config.ts + - x-pack/test/lists_api_integration/security_and_spaces/config.ts + - x-pack/test/observability_api_integration/basic/config.ts + - x-pack/test/observability_api_integration/trial/config.ts + - x-pack/test/observability_functional/with_rac_write.config.ts + - x-pack/test/plugin_api_integration/config.ts + - x-pack/test/plugin_functional/config.ts + - x-pack/test/reporting_api_integration/reporting_and_security.config.ts + - x-pack/test/reporting_api_integration/reporting_without_security.config.ts + - x-pack/test/reporting_functional/reporting_and_deprecated_security.config.ts + - x-pack/test/reporting_functional/reporting_and_security.config.ts + - x-pack/test/reporting_functional/reporting_without_security.config.ts + - x-pack/test/rule_registry/security_and_spaces/config_basic.ts + - x-pack/test/rule_registry/security_and_spaces/config_trial.ts + - x-pack/test/rule_registry/spaces_only/config_basic.ts + - x-pack/test/rule_registry/spaces_only/config_trial.ts + - x-pack/test/saved_object_api_integration/security_and_spaces/config_basic.ts + - x-pack/test/saved_object_api_integration/security_and_spaces/config_trial.ts + - x-pack/test/saved_object_api_integration/spaces_only/config.ts + - x-pack/test/saved_object_tagging/api_integration/security_and_spaces/config.ts + - x-pack/test/saved_object_tagging/api_integration/tagging_api/config.ts + - x-pack/test/saved_object_tagging/functional/config.ts + - x-pack/test/saved_objects_field_count/config.ts + - x-pack/test/search_sessions_integration/config.ts + - x-pack/test/security_api_integration/anonymous_es_anonymous.config.ts + - x-pack/test/security_api_integration/anonymous.config.ts + - x-pack/test/security_api_integration/audit.config.ts + - x-pack/test/security_api_integration/http_bearer.config.ts + - x-pack/test/security_api_integration/http_no_auth_providers.config.ts + - x-pack/test/security_api_integration/kerberos_anonymous_access.config.ts + - x-pack/test/security_api_integration/kerberos.config.ts + - x-pack/test/security_api_integration/login_selector.config.ts + - x-pack/test/security_api_integration/oidc_implicit_flow.config.ts + - x-pack/test/security_api_integration/oidc.config.ts + - x-pack/test/security_api_integration/pki.config.ts + - x-pack/test/security_api_integration/saml.config.ts + - x-pack/test/security_api_integration/session_idle.config.ts + - x-pack/test/security_api_integration/session_invalidate.config.ts + - x-pack/test/security_api_integration/session_lifespan.config.ts + - x-pack/test/security_api_integration/token.config.ts + - x-pack/test/security_functional/login_selector.config.ts + - x-pack/test/security_functional/oidc.config.ts + - x-pack/test/security_functional/saml.config.ts + - x-pack/test/security_solution_endpoint_api_int/config.ts + - x-pack/test/security_solution_endpoint/config.ts + - x-pack/test/spaces_api_integration/security_and_spaces/config_basic.ts + - x-pack/test/spaces_api_integration/security_and_spaces/config_trial.ts + - x-pack/test/spaces_api_integration/spaces_only/config.ts + - x-pack/test/timeline/security_and_spaces/config_trial.ts + - x-pack/test/ui_capabilities/security_and_spaces/config.ts + - x-pack/test/ui_capabilities/spaces_only/config.ts + - x-pack/test/upgrade_assistant_integration/config.js + - x-pack/test/usage_collection/config.ts diff --git a/.buildkite/package-lock.json b/.buildkite/package-lock.json index cfbcb9ec1aae8..734db1a6ef234 100644 --- a/.buildkite/package-lock.json +++ b/.buildkite/package-lock.json @@ -8,7 +8,7 @@ "name": "kibana-buildkite", "version": "1.0.0", "dependencies": { - "kibana-buildkite-library": "git+https://git@github.com/elastic/kibana-buildkite-library#0f95579ace8100de9f1ad4cc16976b9ec6d5841e" + "kibana-buildkite-library": "git+https://git@github.com/elastic/kibana-buildkite-library#f5381bea52e0a71f50a6919cb6357ff3262cf2d6" } }, "node_modules/@nodelib/fs.scandir": { @@ -355,8 +355,8 @@ }, "node_modules/kibana-buildkite-library": { "version": "1.0.0", - "resolved": "git+https://git@github.com/elastic/kibana-buildkite-library.git#0f95579ace8100de9f1ad4cc16976b9ec6d5841e", - "integrity": "sha512-Ayiyy3rAE/jOWcR65vxiv4zacMlpxuRZ+WKvly6magfClWTWIUTcW1aiOH2/PYWP3faiCbIDHOyxLeGGajk5dQ==", + "resolved": "git+https://git@github.com/elastic/kibana-buildkite-library.git#f5381bea52e0a71f50a6919cb6357ff3262cf2d6", + "integrity": "sha512-L1JP2NvXR7mhKn9JBwROPgTEV4vDr5HWwZtkdvxtHjZ/MeOnJYFSDqB4JUY/gXTz6v3CO3eUm3GQ0BP/kewoqQ==", "license": "MIT", "dependencies": { "@octokit/rest": "^18.10.0", @@ -801,9 +801,9 @@ } }, "kibana-buildkite-library": { - "version": "git+https://git@github.com/elastic/kibana-buildkite-library.git#0f95579ace8100de9f1ad4cc16976b9ec6d5841e", - "integrity": "sha512-Ayiyy3rAE/jOWcR65vxiv4zacMlpxuRZ+WKvly6magfClWTWIUTcW1aiOH2/PYWP3faiCbIDHOyxLeGGajk5dQ==", - "from": "kibana-buildkite-library@git+https://git@github.com/elastic/kibana-buildkite-library#0f95579ace8100de9f1ad4cc16976b9ec6d5841e", + "version": "git+https://git@github.com/elastic/kibana-buildkite-library.git#f5381bea52e0a71f50a6919cb6357ff3262cf2d6", + "integrity": "sha512-L1JP2NvXR7mhKn9JBwROPgTEV4vDr5HWwZtkdvxtHjZ/MeOnJYFSDqB4JUY/gXTz6v3CO3eUm3GQ0BP/kewoqQ==", + "from": "kibana-buildkite-library@git+https://git@github.com/elastic/kibana-buildkite-library#f5381bea52e0a71f50a6919cb6357ff3262cf2d6", "requires": { "@octokit/rest": "^18.10.0", "axios": "^0.21.4", diff --git a/.buildkite/package.json b/.buildkite/package.json index 551def1fa1800..079f200a4cbc9 100644 --- a/.buildkite/package.json +++ b/.buildkite/package.json @@ -3,6 +3,6 @@ "version": "1.0.0", "private": true, "dependencies": { - "kibana-buildkite-library": "git+https://git@github.com/elastic/kibana-buildkite-library#0f95579ace8100de9f1ad4cc16976b9ec6d5841e" + "kibana-buildkite-library": "git+https://git@github.com/elastic/kibana-buildkite-library#f5381bea52e0a71f50a6919cb6357ff3262cf2d6" } } diff --git a/.buildkite/pipelines/es_snapshots/verify.yml b/.buildkite/pipelines/es_snapshots/verify.yml index 729d0d1b37b5f..0d8e11e1c8e8b 100755 --- a/.buildkite/pipelines/es_snapshots/verify.yml +++ b/.buildkite/pipelines/es_snapshots/verify.yml @@ -27,50 +27,17 @@ steps: if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" timeout_in_minutes: 60 - - command: .buildkite/scripts/steps/functional/xpack_cigroup.sh - label: 'Default CI Group' - parallelism: 31 - agents: - queue: n2-4 - depends_on: build - timeout_in_minutes: 150 - key: default-cigroup - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_cigroup.sh - label: 'OSS CI Group' - parallelism: 12 - agents: - queue: ci-group-4d - depends_on: build - timeout_in_minutes: 120 - key: oss-cigroup - retry: - automatic: - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/test/pick_jest_config_run_order.sh - label: 'Pick Jest Config Run Order' + - command: .buildkite/scripts/steps/test/pick_test_group_run_order.sh + label: 'Pick Test Group Run Order' agents: queue: kibana-default env: - FILTER_JEST_CONFIG_TYPE: integration + LIMIT_CONFIG_TYPE: integration,functional retry: automatic: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/test/api_integration.sh - label: 'API Integration Tests' - agents: - queue: n2-2 - timeout_in_minutes: 120 - key: api-integration - - command: .buildkite/scripts/steps/es_snapshots/trigger_promote.sh label: Trigger promotion timeout_in_minutes: 10 diff --git a/.buildkite/pipelines/flaky_tests/groups.json b/.buildkite/pipelines/flaky_tests/groups.json index e471d5c6a8679..78f8e6e56b904 100644 --- a/.buildkite/pipelines/flaky_tests/groups.json +++ b/.buildkite/pipelines/flaky_tests/groups.json @@ -1,46 +1,20 @@ { "groups": [ { - "key": "oss/cigroup", - "name": "OSS CI Group", - "ciGroups": 12 - }, - { - "key": "oss/firefox", - "name": "OSS Firefox" - }, - { - "key": "oss/accessibility", - "name": "OSS Accessibility" - }, - { - "key": "xpack/cypress/security_solution", + "key": "cypress/security_solution", "name": "Security Solution - Cypress" }, { - "key": "xpack/cypress/osquery_cypress", + "key": "cypress/osquery_cypress", "name": "Osquery - Cypress" }, { - "key": "xpack/cypress/fleet_cypress", + "key": "cypress/fleet_cypress", "name": "Fleet - Cypress" }, { - "key": "xpack/cypress/apm_cypress", + "key": "cypress/apm_cypress", "name": "APM - Cypress" - }, - { - "key": "xpack/cigroup", - "name": "Default CI Group", - "ciGroups": 30 - }, - { - "key": "xpack/firefox", - "name": "Default Firefox" - }, - { - "key": "xpack/accessibility", - "name": "Default Accessibility" } ] } diff --git a/.buildkite/pipelines/flaky_tests/pipeline.js b/.buildkite/pipelines/flaky_tests/pipeline.js index 000f9954b76f1..d62156a08c55a 100644 --- a/.buildkite/pipelines/flaky_tests/pipeline.js +++ b/.buildkite/pipelines/flaky_tests/pipeline.js @@ -20,8 +20,18 @@ const groups = /** @type {Array<{key: string, name: string, ciGroups: number }>} require('./groups.json').groups ); -const concurrency = 25; -const initialJobs = 3; +const concurrency = process.env.KIBANA_FLAKY_TEST_CONCURRENCY + ? parseInt(process.env.KIBANA_FLAKY_TEST_CONCURRENCY, 10) + : 25; + +if (Number.isNaN(concurrency)) { + throw new Error( + `invalid KIBANA_FLAKY_TEST_CONCURRENCY: ${process.env.KIBANA_FLAKY_TEST_CONCURRENCY}` + ); +} + +const BASE_JOBS = 1; +const MAX_JOBS = 500; function getTestSuitesFromJson(json) { const fail = (errorMsg) => { @@ -41,20 +51,40 @@ function getTestSuitesFromJson(json) { fail(`JSON test config must be an array`); } - /** @type {Array<{ key: string, count: number }>} */ + /** @type {Array<{ type: 'group', key: string; count: number } | { type: 'ftrConfig', ftrConfig: string; count: number }>} */ const testSuites = []; for (const item of parsed) { if (typeof item !== 'object' || item === null) { fail(`testSuites must be objects`); } - const key = item.key; - if (typeof key !== 'string') { - fail(`testSuite.key must be a string`); - } + const count = item.count; if (typeof count !== 'number') { fail(`testSuite.count must be a number`); } + + const type = item.type; + if (type !== 'ftrConfig' && type !== 'group') { + fail(`testSuite.type must be either "ftrConfig" or "group"`); + } + + if (item.type === 'ftrConfig') { + const ftrConfig = item.ftrConfig; + if (typeof ftrConfig !== 'string') { + fail(`testSuite.ftrConfig must be a string`); + } + + testSuites.push({ + ftrConfig, + count, + }); + continue; + } + + const key = item.key; + if (typeof key !== 'string') { + fail(`testSuite.key must be a string`); + } testSuites.push({ key, count, @@ -65,13 +95,14 @@ function getTestSuitesFromJson(json) { } const testSuites = getTestSuitesFromJson(configJson); -const totalJobs = testSuites.reduce((acc, t) => acc + t.count, initialJobs); -if (totalJobs > 500) { +const totalJobs = testSuites.reduce((acc, t) => acc + t.count, BASE_JOBS); + +if (totalJobs > MAX_JOBS) { console.error('+++ Too many tests'); console.error( - `Buildkite builds can only contain 500 steps in total. Found ${totalJobs} in total. Make sure your test runs are less than ${ - 500 - initialJobs + `Buildkite builds can only contain ${MAX_JOBS} jobs in total. Found ${totalJobs} based on this config. Make sure your test runs are less than ${ + MAX_JOBS - BASE_JOBS }` ); process.exit(1); @@ -82,7 +113,7 @@ const pipeline = { env: { IGNORE_SHIP_CI_STATS_ERROR: 'true', }, - steps: steps, + steps, }; steps.push({ @@ -94,76 +125,40 @@ steps.push({ }); for (const testSuite of testSuites) { - const TEST_SUITE = testSuite.key; - const RUN_COUNT = testSuite.count; - const UUID = process.env.UUID; - - const JOB_PARTS = TEST_SUITE.split('/'); - const IS_XPACK = JOB_PARTS[0] === 'xpack'; - const TASK = JOB_PARTS[1]; - const CI_GROUP = JOB_PARTS.length > 2 ? JOB_PARTS[2] : ''; - - if (RUN_COUNT < 1) { + if (testSuite.count <= 0) { continue; } - switch (TASK) { - case 'cigroup': - if (IS_XPACK) { - steps.push({ - command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/xpack_cigroup.sh`, - label: `Default CI Group ${CI_GROUP}`, - agents: { queue: 'n2-4' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - } else { - steps.push({ - command: `CI_GROUP=${CI_GROUP} .buildkite/scripts/steps/functional/oss_cigroup.sh`, - label: `OSS CI Group ${CI_GROUP}`, - agents: { queue: 'ci-group-4d' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - } - break; - - case 'firefox': - steps.push({ - command: `.buildkite/scripts/steps/functional/${IS_XPACK ? 'xpack' : 'oss'}_firefox.sh`, - label: `${IS_XPACK ? 'Default' : 'OSS'} Firefox`, - agents: { queue: IS_XPACK ? 'n2-4' : 'ci-group-4d' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - break; - - case 'accessibility': - steps.push({ - command: `.buildkite/scripts/steps/functional/${ - IS_XPACK ? 'xpack' : 'oss' - }_accessibility.sh`, - label: `${IS_XPACK ? 'Default' : 'OSS'} Accessibility`, - agents: { queue: IS_XPACK ? 'n2-4' : 'ci-group-4d' }, - depends_on: 'build', - parallelism: RUN_COUNT, - concurrency: concurrency, - concurrency_group: UUID, - concurrency_method: 'eager', - }); - break; + if (testSuite.ftrConfig) { + steps.push({ + command: `.buildkite/scripts/steps/test/ftr_configs.sh`, + env: { + FTR_CONFIG: testSuite.ftrConfig, + }, + label: `FTR Config: ${testSuite.ftrConfig}`, + parallelism: testSuite.count, + concurrency: concurrency, + concurrency_group: process.env.UUID, + concurrency_method: 'eager', + agents: { + queue: 'n2-4-spot-2', + }, + depends_on: 'build', + timeout_in_minutes: 150, + retry: { + automatic: [ + { exit_status: '-1', limit: 3 }, + // { exit_status: '*', limit: 1 }, + ], + }, + }); + continue; + } + const keyParts = testSuite.key.split('/'); + switch (keyParts[0]) { case 'cypress': - const CYPRESS_SUITE = CI_GROUP; + const CYPRESS_SUITE = keyParts[1]; const group = groups.find((group) => group.key.includes(CYPRESS_SUITE)); if (!group) { throw new Error( @@ -175,12 +170,14 @@ for (const testSuite of testSuites) { label: group.name, agents: { queue: 'ci-group-6' }, depends_on: 'build', - parallelism: RUN_COUNT, + parallelism: testSuite.count, concurrency: concurrency, - concurrency_group: UUID, + concurrency_group: process.env.UUID, concurrency_method: 'eager', }); break; + default: + throw new Error(`unknown test suite: ${testSuite.key}`); } } diff --git a/.buildkite/pipelines/on_merge.yml b/.buildkite/pipelines/on_merge.yml index 1c89c4e90893b..26b3afbf081a2 100644 --- a/.buildkite/pipelines/on_merge.yml +++ b/.buildkite/pipelines/on_merge.yml @@ -49,116 +49,8 @@ steps: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/functional/xpack_cigroup.sh - label: 'Default CI Group' - parallelism: 31 - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 250 - key: default-cigroup - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_cigroup.sh - label: 'OSS CI Group' - parallelism: 12 - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - key: oss-cigroup - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_accessibility.sh - label: 'OSS Accessibility Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_accessibility.sh - label: 'Default Accessibility Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_firefox.sh - label: 'OSS Firefox Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_firefox.sh - label: 'Default Firefox Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_misc.sh - label: 'OSS Misc Functional Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh - label: 'Saved Object Field Metrics' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/test/pick_jest_config_run_order.sh - label: 'Pick Jest Config Run Order' + - command: .buildkite/scripts/steps/test/pick_test_group_run_order.sh + label: 'Pick Test Group Run Order' agents: queue: kibana-default retry: @@ -166,17 +58,6 @@ steps: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/test/api_integration.sh - label: 'API Integration Tests' - agents: - queue: n2-2-spot - timeout_in_minutes: 120 - key: api-integration - retry: - automatic: - - exit_status: '-1' - limit: 3 - - command: .buildkite/scripts/steps/lint.sh label: 'Linting' agents: diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml index 4b4104f18c627..dc771e53d9d75 100644 --- a/.buildkite/pipelines/pull_request/base.yml +++ b/.buildkite/pipelines/pull_request/base.yml @@ -15,116 +15,8 @@ steps: if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" timeout_in_minutes: 60 - - command: .buildkite/scripts/steps/functional/xpack_cigroup.sh - label: 'Default CI Group' - parallelism: 31 - agents: - queue: n2-4-spot-2 - depends_on: build - timeout_in_minutes: 150 - key: default-cigroup - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_cigroup.sh - label: 'OSS CI Group' - parallelism: 12 - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - key: oss-cigroup - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_accessibility.sh - label: 'OSS Accessibility Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_accessibility.sh - label: 'Default Accessibility Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_firefox.sh - label: 'OSS Firefox Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_firefox.sh - label: 'Default Firefox Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_misc.sh - label: 'OSS Misc Functional Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh - label: 'Saved Object Field Metrics' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/test/pick_jest_config_run_order.sh - label: 'Pick Jest Config Run Order' + - command: .buildkite/scripts/steps/test/pick_test_group_run_order.sh + label: 'Pick Test Group Run Order' agents: queue: kibana-default retry: @@ -132,17 +24,6 @@ steps: - exit_status: '*' limit: 1 - - command: .buildkite/scripts/steps/test/api_integration.sh - label: 'API Integration Tests' - agents: - queue: n2-2-spot - timeout_in_minutes: 120 - key: api-integration - retry: - automatic: - - exit_status: '-1' - limit: 3 - - command: .buildkite/scripts/steps/lint.sh label: 'Linting' agents: diff --git a/.buildkite/scripts/steps/checks.sh b/.buildkite/scripts/steps/checks.sh index 42de0f2cf2393..cae019150b626 100755 --- a/.buildkite/scripts/steps/checks.sh +++ b/.buildkite/scripts/steps/checks.sh @@ -8,7 +8,6 @@ export DISABLE_BOOTSTRAP_VALIDATION=false .buildkite/scripts/steps/checks/commit/commit.sh .buildkite/scripts/steps/checks/bazel_packages.sh .buildkite/scripts/steps/checks/telemetry.sh -.buildkite/scripts/steps/checks/validate_ci_groups.sh .buildkite/scripts/steps/checks/ts_projects.sh .buildkite/scripts/steps/checks/jest_configs.sh .buildkite/scripts/steps/checks/doc_api_changes.sh diff --git a/.buildkite/scripts/steps/checks/validate_ci_groups.sh b/.buildkite/scripts/steps/checks/validate_ci_groups.sh deleted file mode 100755 index 1216ff0a55e10..0000000000000 --- a/.buildkite/scripts/steps/checks/validate_ci_groups.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/common/util.sh - -echo --- Ensure that all tests are in a CI Group -checks-reporter-with-killswitch "Ensure that all tests are in a CI Group" \ - node scripts/ensure_all_tests_in_ci_group diff --git a/.buildkite/scripts/steps/functional/fleet_cypress.sh b/.buildkite/scripts/steps/functional/fleet_cypress.sh index 3847ffda08822..7207a2adf454a 100755 --- a/.buildkite/scripts/steps/functional/fleet_cypress.sh +++ b/.buildkite/scripts/steps/functional/fleet_cypress.sh @@ -11,10 +11,8 @@ export JOB=kibana-fleet-cypress echo "--- Fleet Cypress tests" -cd "$XPACK_DIR" - checks-reporter-with-killswitch "Fleet Cypress Tests" \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/fleet_cypress/cli_config.ts + --config x-pack/test/fleet_cypress/cli_config.ts diff --git a/.buildkite/scripts/steps/functional/osquery_cypress.sh b/.buildkite/scripts/steps/functional/osquery_cypress.sh index a0d98713aa379..02766e0530bfb 100755 --- a/.buildkite/scripts/steps/functional/osquery_cypress.sh +++ b/.buildkite/scripts/steps/functional/osquery_cypress.sh @@ -12,10 +12,8 @@ export JOB=kibana-osquery-cypress echo "--- Osquery Cypress tests" -cd "$XPACK_DIR" - checks-reporter-with-killswitch "Osquery Cypress Tests" \ node scripts/functional_tests \ --debug --bail \ - --config test/osquery_cypress/cli_config.ts + --config x-pack/test/osquery_cypress/cli_config.ts diff --git a/.buildkite/scripts/steps/functional/oss_accessibility.sh b/.buildkite/scripts/steps/functional/oss_accessibility.sh deleted file mode 100755 index e8c65cfa760b2..0000000000000 --- a/.buildkite/scripts/steps/functional/oss_accessibility.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/steps/functional/common.sh - -echo --- OSS Accessibility Tests - -checks-reporter-with-killswitch "Kibana accessibility tests" \ - node scripts/functional_tests \ - --debug --bail \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/accessibility/config.ts diff --git a/.buildkite/scripts/steps/functional/oss_cigroup.sh b/.buildkite/scripts/steps/functional/oss_cigroup.sh deleted file mode 100755 index a7a5960a41afe..0000000000000 --- a/.buildkite/scripts/steps/functional/oss_cigroup.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/steps/functional/common.sh - -export CI_GROUP=${CI_GROUP:-$((BUILDKITE_PARALLEL_JOB+1))} -export JOB=kibana-oss-ciGroup${CI_GROUP} - -echo "--- OSS CI Group $CI_GROUP" - -checks-reporter-with-killswitch "Functional tests / Group ${CI_GROUP}" \ - node scripts/functional_tests \ - --bail \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --include-tag "ciGroup$CI_GROUP" diff --git a/.buildkite/scripts/steps/functional/oss_firefox.sh b/.buildkite/scripts/steps/functional/oss_firefox.sh deleted file mode 100755 index e953973da62d6..0000000000000 --- a/.buildkite/scripts/steps/functional/oss_firefox.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/steps/functional/common.sh - -echo --- OSS Firefox Smoke Tests - -checks-reporter-with-killswitch "Firefox smoke test" \ - node scripts/functional_tests \ - --bail --debug \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --include-tag "includeFirefox" \ - --config test/functional/config.firefox.js diff --git a/.buildkite/scripts/steps/functional/oss_misc.sh b/.buildkite/scripts/steps/functional/oss_misc.sh deleted file mode 100755 index 22d4eda608cc2..0000000000000 --- a/.buildkite/scripts/steps/functional/oss_misc.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/steps/functional/common.sh - -# Required, at least for plugin_functional tests -.buildkite/scripts/build_kibana_plugins.sh - -echo --- Plugin Functional Tests -checks-reporter-with-killswitch "Plugin Functional Tests" \ - node scripts/functional_tests \ - --config test/plugin_functional/config.ts \ - --bail \ - --debug - -echo --- Interpreter Functional Tests -checks-reporter-with-killswitch "Interpreter Functional Tests" \ - node scripts/functional_tests \ - --config test/interpreter_functional/config.ts \ - --bail \ - --debug \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" - -echo --- Server Integration Tests -checks-reporter-with-killswitch "Server Integration Tests" \ - node scripts/functional_tests \ - --config test/server_integration/http/ssl/config.js \ - --config test/server_integration/http/ssl_redirect/config.js \ - --config test/server_integration/http/platform/config.ts \ - --config test/server_integration/http/ssl_with_p12/config.js \ - --config test/server_integration/http/ssl_with_p12_intermediate/config.js \ - --bail \ - --debug \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" - -# Tests that must be run against source in order to build test plugins -echo --- Status Integration Tests -checks-reporter-with-killswitch "Status Integration Tests" \ - node scripts/functional_tests \ - --config test/server_integration/http/platform/config.status.ts \ - --bail \ - --debug - -# Tests that must be run against source in order to build test plugins -echo --- Analytics Integration Tests -checks-reporter-with-killswitch "Analytics Integration Tests" \ - node scripts/functional_tests \ - --config test/analytics/config.ts \ - --bail \ - --debug diff --git a/.buildkite/scripts/steps/functional/performance_playwright.sh b/.buildkite/scripts/steps/functional/performance_playwright.sh index dad75c9f66a98..a1c3f23ced51e 100644 --- a/.buildkite/scripts/steps/functional/performance_playwright.sh +++ b/.buildkite/scripts/steps/functional/performance_playwright.sh @@ -18,8 +18,6 @@ export TEST_ES_DISABLE_STARTUP=true sleep 120 -cd "$XPACK_DIR" - journeys=("login" "ecommerce_dashboard" "flight_dashboard" "web_logs_dashboard" "promotion_tracking_dashboard" "many_fields_discover") for i in "${journeys[@]}"; do @@ -31,8 +29,8 @@ for i in "${journeys[@]}"; do checks-reporter-with-killswitch "Run Performance Tests with Playwright Config (Journey:${i},Phase: WARMUP)" \ node scripts/functional_tests \ - --config test/performance/config.playwright.ts \ - --include "test/performance/tests/playwright/${i}.ts" \ + --config x-pack/test/performance/config.playwright.ts \ + --include "x-pack/test/performance/tests/playwright/${i}.ts" \ --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ --debug \ --bail @@ -42,8 +40,8 @@ for i in "${journeys[@]}"; do checks-reporter-with-killswitch "Run Performance Tests with Playwright Config (Journey:${i},Phase: TEST)" \ node scripts/functional_tests \ - --config test/performance/config.playwright.ts \ - --include "test/performance/tests/playwright/${i}.ts" \ + --config x-pack/test/performance/config.playwright.ts \ + --include "x-pack/test/performance/tests/playwright/${i}.ts" \ --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ --debug \ --bail diff --git a/.buildkite/scripts/steps/functional/response_ops.sh b/.buildkite/scripts/steps/functional/response_ops.sh index d8484854ed29e..9828884e6d6a2 100755 --- a/.buildkite/scripts/steps/functional/response_ops.sh +++ b/.buildkite/scripts/steps/functional/response_ops.sh @@ -8,10 +8,8 @@ export JOB=kibana-security-solution-chrome echo "--- Response Ops Cypress Tests on Security Solution" -cd "$XPACK_DIR" - checks-reporter-with-killswitch "Response Ops Cypress Tests on Security Solution" \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/security_solution_cypress/response_ops_cli_config.ts + --config x-pack/test/security_solution_cypress/response_ops_cli_config.ts diff --git a/.buildkite/scripts/steps/functional/response_ops_cases.sh b/.buildkite/scripts/steps/functional/response_ops_cases.sh index 13d0ef52130a3..2485e025833ed 100755 --- a/.buildkite/scripts/steps/functional/response_ops_cases.sh +++ b/.buildkite/scripts/steps/functional/response_ops_cases.sh @@ -8,10 +8,8 @@ export JOB=kibana-security-solution-chrome echo "--- Response Ops Cases Cypress Tests on Security Solution" -cd "$XPACK_DIR" - checks-reporter-with-killswitch "Response Ops Cases Cypress Tests on Security Solution" \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/security_solution_cypress/cases_cli_config.ts + --config x-pack/test/security_solution_cypress/cases_cli_config.ts diff --git a/.buildkite/scripts/steps/functional/security_solution.sh b/.buildkite/scripts/steps/functional/security_solution.sh index 9b2bfc7207a95..ae81eaa4f48e2 100755 --- a/.buildkite/scripts/steps/functional/security_solution.sh +++ b/.buildkite/scripts/steps/functional/security_solution.sh @@ -8,10 +8,8 @@ export JOB=kibana-security-solution-chrome echo "--- Security Solution tests (Chrome)" -cd "$XPACK_DIR" - checks-reporter-with-killswitch "Security Solution Cypress Tests (Chrome)" \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/security_solution_cypress/cli_config.ts + --config x-pack/test/security_solution_cypress/cli_config.ts diff --git a/.buildkite/scripts/steps/functional/xpack_accessibility.sh b/.buildkite/scripts/steps/functional/xpack_accessibility.sh deleted file mode 100755 index 5b098da858c96..0000000000000 --- a/.buildkite/scripts/steps/functional/xpack_accessibility.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/steps/functional/common.sh - -cd "$XPACK_DIR" - -echo --- Default Accessibility Tests - -checks-reporter-with-killswitch "X-Pack accessibility tests" \ - node scripts/functional_tests \ - --debug --bail \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/accessibility/config.ts diff --git a/.buildkite/scripts/steps/functional/xpack_cigroup.sh b/.buildkite/scripts/steps/functional/xpack_cigroup.sh deleted file mode 100755 index 6877e88cff8b3..0000000000000 --- a/.buildkite/scripts/steps/functional/xpack_cigroup.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/steps/functional/common.sh - -export CI_GROUP=${CI_GROUP:-$((BUILDKITE_PARALLEL_JOB+1))} -export JOB=kibana-default-ciGroup${CI_GROUP} - -echo "--- Default CI Group $CI_GROUP" - -cd "$XPACK_DIR" - -checks-reporter-with-killswitch "X-Pack Chrome Functional tests / Group ${CI_GROUP}" \ - node scripts/functional_tests \ - --bail \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --include-tag "ciGroup$CI_GROUP" - -cd "$KIBANA_DIR" diff --git a/.buildkite/scripts/steps/functional/xpack_firefox.sh b/.buildkite/scripts/steps/functional/xpack_firefox.sh deleted file mode 100755 index a9a9704ea78de..0000000000000 --- a/.buildkite/scripts/steps/functional/xpack_firefox.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/steps/functional/common.sh - -cd "$XPACK_DIR" - -echo --- Default Firefox Smoke Tests - -checks-reporter-with-killswitch "X-Pack firefox smoke test" \ - node scripts/functional_tests \ - --debug --bail \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --include-tag "includeFirefox" \ - --config test/functional/config.firefox.js \ - --config test/functional_embedded/config.firefox.ts diff --git a/.buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh b/.buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh deleted file mode 100755 index 5e00d2446bf7a..0000000000000 --- a/.buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/common/util.sh - -.buildkite/scripts/bootstrap.sh -.buildkite/scripts/download_build_artifacts.sh - -cd "$XPACK_DIR" - -echo --- Capture Kibana Saved Objects field count metrics -checks-reporter-with-killswitch "Capture Kibana Saved Objects field count metrics" \ - node scripts/functional_tests \ - --debug --bail \ - --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/saved_objects_field_count/config.ts; diff --git a/.buildkite/scripts/steps/test/api_integration.sh b/.buildkite/scripts/steps/test/api_integration.sh deleted file mode 100755 index f56e98903d226..0000000000000 --- a/.buildkite/scripts/steps/test/api_integration.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/common/util.sh - -is_test_execution_step - -.buildkite/scripts/bootstrap.sh - -echo --- API Integration Tests -checks-reporter-with-killswitch "API Integration Tests" \ - node scripts/functional_tests \ - --config test/api_integration/config.js \ - --bail \ - --debug diff --git a/.buildkite/scripts/steps/test/ftr_configs.sh b/.buildkite/scripts/steps/test/ftr_configs.sh new file mode 100755 index 0000000000000..52a4b9572f5b6 --- /dev/null +++ b/.buildkite/scripts/steps/test/ftr_configs.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/steps/functional/common.sh +source .buildkite/scripts/steps/test/test_group_env.sh + +export JOB_NUM=$BUILDKITE_PARALLEL_JOB +export JOB=ftr-configs-${JOB_NUM} + +FAILED_CONFIGS_KEY="${BUILDKITE_STEP_ID}${BUILDKITE_PARALLEL_JOB:-0}" + +# a FTR failure will result in the script returning an exit code of 10 +exitCode=0 + +configs="${FTR_CONFIG:-}" + +# The first retry should only run the configs that failed in the previous attempt +# Any subsequent retries, which would generally only happen by someone clicking the button in the UI, will run everything +if [[ ! "$configs" && "${BUILDKITE_RETRY_COUNT:-0}" == "1" ]]; then + configs=$(buildkite-agent meta-data get "$FAILED_CONFIGS_KEY" --default '') + if [[ "$configs" ]]; then + echo "--- Retrying only failed configs" + echo "$configs" + fi +fi + +if [[ "$configs" == "" ]]; then + echo "--- downloading ftr test run order" + buildkite-agent artifact download ftr_run_order.json . + configs=$(jq -r '.groups[env.JOB_NUM | tonumber].names | .[]' ftr_run_order.json) +fi + +failedConfigs="" +results=() + +while read -r config; do + if [[ ! "$config" ]]; then + continue; + fi + + echo "--- $ node scripts/functional_tests --bail --config $config" + start=$(date +%s) + + # prevent non-zero exit code from breaking the loop + set +e; + node ./scripts/functional_tests \ + --bail \ + --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ + --config="$config" + lastCode=$? + set -e; + + timeSec=$(($(date +%s)-start)) + if [[ $timeSec -gt 60 ]]; then + min=$((timeSec/60)) + sec=$((timeSec-(min*60))) + duration="${min}m ${sec}s" + else + duration="${timeSec}s" + fi + + results+=("- $config + duration: ${duration} + result: ${lastCode}") + + if [ $lastCode -ne 0 ]; then + exitCode=10 + echo "FTR exited with code $lastCode" + echo "^^^ +++" + + if [[ "$failedConfigs" ]]; then + failedConfigs="${failedConfigs}"$'\n'"$config" + else + failedConfigs="$config" + fi + fi +done <<< "$configs" + +if [[ "$failedConfigs" ]]; then + buildkite-agent meta-data set "$FAILED_CONFIGS_KEY" "$failedConfigs" +fi + +echo "--- FTR configs complete" +printf "%s\n" "${results[@]}" +echo "" + +exit $exitCode diff --git a/.buildkite/scripts/steps/test/jest_parallel.sh b/.buildkite/scripts/steps/test/jest_parallel.sh index 86c685d82c7e7..f7efc13b501bd 100755 --- a/.buildkite/scripts/steps/test/jest_parallel.sh +++ b/.buildkite/scripts/steps/test/jest_parallel.sh @@ -1,13 +1,14 @@ #!/bin/bash -set -uo pipefail +set -euo pipefail -source .buildkite/scripts/steps/test/jest_env.sh +source .buildkite/scripts/steps/test/test_group_env.sh export JOB=$BUILDKITE_PARALLEL_JOB # a jest failure will result in the script returning an exit code of 10 exitCode=0 +results=() if [[ "$1" == 'jest.config.js' ]]; then # run unit tests in parallel @@ -20,14 +21,32 @@ else fi export TEST_TYPE -echo "--- downloading integration test run order" +echo "--- downloading jest test run order" buildkite-agent artifact download jest_run_order.json . configs=$(jq -r 'getpath([env.TEST_TYPE]) | .groups[env.JOB | tonumber].names | .[]' jest_run_order.json) while read -r config; do echo "--- $ node scripts/jest --config $config" + start=$(date +%s) + + # prevent non-zero exit code from breaking the loop + set +e; NODE_OPTIONS="--max-old-space-size=14336" node ./scripts/jest --config="$config" "$parallelism" --coverage=false --passWithNoTests lastCode=$? + set -e; + + timeSec=$(($(date +%s)-start)) + if [[ $timeSec -gt 60 ]]; then + min=$((timeSec/60)) + sec=$((timeSec-(min*60))) + duration="${min}m ${sec}s" + else + duration="${timeSec}s" + fi + + results+=("- $config + duration: ${duration} + result: ${lastCode}") if [ $lastCode -ne 0 ]; then exitCode=10 @@ -36,4 +55,8 @@ while read -r config; do fi done <<< "$configs" +echo "--- Jest configs complete" +printf "%s\n" "${results[@]}" +echo "" + exit $exitCode diff --git a/.buildkite/scripts/steps/test/pick_jest_config_run_order.sh b/.buildkite/scripts/steps/test/pick_jest_config_run_order.sh deleted file mode 100644 index 37d4e629c90b0..0000000000000 --- a/.buildkite/scripts/steps/test/pick_jest_config_run_order.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/common/util.sh -source .buildkite/scripts/steps/test/jest_env.sh - -echo '--- Pick Jest Config Run Order' -node "$(dirname "${0}")/pick_jest_config_run_order.js" diff --git a/.buildkite/scripts/steps/test/pick_jest_config_run_order.js b/.buildkite/scripts/steps/test/pick_test_group_run_order.js similarity index 100% rename from .buildkite/scripts/steps/test/pick_jest_config_run_order.js rename to .buildkite/scripts/steps/test/pick_test_group_run_order.js diff --git a/.buildkite/scripts/steps/test/pick_test_group_run_order.sh b/.buildkite/scripts/steps/test/pick_test_group_run_order.sh new file mode 100644 index 0000000000000..3bb09282efb41 --- /dev/null +++ b/.buildkite/scripts/steps/test/pick_test_group_run_order.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh +source .buildkite/scripts/steps/test/test_group_env.sh + +echo '--- Pick Test Group Run Order' +node "$(dirname "${0}")/pick_test_group_run_order.js" diff --git a/.buildkite/scripts/steps/test/jest_env.sh b/.buildkite/scripts/steps/test/test_group_env.sh similarity index 80% rename from .buildkite/scripts/steps/test/jest_env.sh rename to .buildkite/scripts/steps/test/test_group_env.sh index 80e88bebba184..3a8c12fdb4a52 100644 --- a/.buildkite/scripts/steps/test/jest_env.sh +++ b/.buildkite/scripts/steps/test/test_group_env.sh @@ -5,3 +5,4 @@ set -euo pipefail # keys used to associate test group data in ci-stats with Jest execution order export TEST_GROUP_TYPE_UNIT="Jest Unit Tests" export TEST_GROUP_TYPE_INTEGRATION="Jest Integration Tests" +export TEST_GROUP_TYPE_FUNCTIONAL="Functional Tests" diff --git a/docs/developer/contributing/development-functional-tests.asciidoc b/docs/developer/contributing/development-functional-tests.asciidoc index af88754b316fa..b544add73b3b1 100644 --- a/docs/developer/contributing/development-functional-tests.asciidoc +++ b/docs/developer/contributing/development-functional-tests.asciidoc @@ -6,7 +6,7 @@ We use functional tests to make sure the {kib} UI works as expected. It replaces [discrete] === Running functional tests -The `FunctionalTestRunner` is very bare bones and gets most of its functionality from its config file, located at {blob}test/functional/config.js[test/functional/config.js] or {blob}x-pack/test/functional/config.js[x-pack/test/functional/config.js]. If you’re writing a plugin outside the {kib} repo, you will have your own config file. +The `FunctionalTestRunner` (FTR) is very bare bones and gets most of its functionality from its config file. The {kib} repo contains many FTR config files which use slightly different configurations for the {kib} server or {es}, have different test files, and potentially other config differences. You can find a manifest of all the FTR config files in `.buildkite/ftr_configs.yml`. If you’re writing a plugin outside the {kib} repo, you will have your own config file. See <> for more info. There are three ways to run the tests depending on your goals: @@ -96,7 +96,8 @@ node scripts/functional_test_runner --exclude-tag skipCloud When run without any arguments the `FunctionalTestRunner` automatically loads the configuration in the standard location, but you can override that behavior with the `--config` flag. List configs with multiple --config arguments. -* `--config test/functional/config.js` starts {es} and {kib} servers with the WebDriver tests configured to run in Chrome. +* `--config test/functional/apps/app-name/config.js` starts {es} and {kib} servers with the WebDriver tests configured to run in Chrome for a specific app. For example, +`--config test/functional/apps/home/config.js` starts {es} and {kib} servers with the WebDriver tests configured to run in Chrome for the home app. * `--config test/functional/config.firefox.js` starts {es} and {kib} servers with the WebDriver tests configured to run in Firefox. * `--config test/api_integration/config.js` starts {es} and {kib} servers with the api integration tests configuration. * `--config test/accessibility/config.ts` starts {es} and {kib} servers with the WebDriver tests configured to run an accessibility audit using https://www.deque.com/axe/[axe]. @@ -416,7 +417,7 @@ export function SomethingUsefulProvider({ getService }) { ----------- + * Re-export your provider from `services/index.js` -* Import it into `src/functional/config.js` and add it to the services config: +* Import it into `src/functional/config.base.js` and add it to the services config: + ["source","js"] ----------- diff --git a/docs/developer/plugin/external-plugin-functional-tests.asciidoc b/docs/developer/plugin/external-plugin-functional-tests.asciidoc index 55b311794f9dc..4a98ffcc5d08c 100644 --- a/docs/developer/plugin/external-plugin-functional-tests.asciidoc +++ b/docs/developer/plugin/external-plugin-functional-tests.asciidoc @@ -24,7 +24,7 @@ export default async function ({ readConfigFile }) { // read the {kib} config file so that we can utilize some of // its services and PageObjects - const kibanaConfig = await readConfigFile(resolve(REPO_ROOT, 'test/functional/config.js')); + const kibanaConfig = await readConfigFile(resolve(REPO_ROOT, 'test/functional/config.base.js')); return { // list paths to the files that contain your plugins tests diff --git a/packages/kbn-dev-utils/src/proc_runner/proc.ts b/packages/kbn-dev-utils/src/proc_runner/proc.ts index 0402feec99d47..c622c46456abf 100644 --- a/packages/kbn-dev-utils/src/proc_runner/proc.ts +++ b/packages/kbn-dev-utils/src/proc_runner/proc.ts @@ -37,19 +37,7 @@ async function withTimeout( ms: number, onTimeout: () => Promise ) { - const TIMEOUT = Symbol('timeout'); - try { - await Promise.race([ - attempt(), - new Promise((_, reject) => setTimeout(() => reject(TIMEOUT), ms)), - ]); - } catch (error) { - if (error === TIMEOUT) { - await onTimeout(); - } else { - throw error; - } - } + await Rx.lastValueFrom(Rx.race(Rx.defer(attempt), Rx.timer(ms).pipe(Rx.mergeMap(onTimeout)))); } export type Proc = ReturnType; diff --git a/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts b/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts index 3b7cf008df9a6..857a4fcfd475d 100644 --- a/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts +++ b/packages/kbn-dev-utils/src/proc_runner/proc_runner.ts @@ -7,7 +7,6 @@ */ import * as Rx from 'rxjs'; -import { filter, first, catchError, map } from 'rxjs/operators'; import exitHook from 'exit-hook'; import { ToolingLog } from '@kbn/tooling-log'; @@ -93,29 +92,30 @@ export class ProcRunner { try { if (wait instanceof RegExp) { // wait for process to log matching line - await Rx.race( - proc.lines$.pipe( - filter((line) => wait.test(line)), - first(), - catchError((err) => { - if (err.name !== 'EmptyError') { - throw createFailError(`[${name}] exited without matching pattern: ${wait}`); - } else { - throw err; - } - }) - ), - waitTimeout === false - ? Rx.NEVER - : Rx.timer(waitTimeout).pipe( - map(() => { - const sec = waitTimeout / SECOND; - throw createFailError( - `[${name}] failed to match pattern within ${sec} seconds [pattern=${wait}]` - ); - }) - ) - ).toPromise(); + await Rx.lastValueFrom( + Rx.race( + proc.lines$.pipe( + Rx.filter((line) => wait.test(line)), + Rx.take(1), + Rx.defaultIfEmpty(undefined), + Rx.map((line) => { + if (line === undefined) { + throw createFailError(`[${name}] exited without matching pattern: ${wait}`); + } + }) + ), + waitTimeout === false + ? Rx.NEVER + : Rx.timer(waitTimeout).pipe( + Rx.map(() => { + const sec = waitTimeout / SECOND; + throw createFailError( + `[${name}] failed to match pattern within ${sec} seconds [pattern=${wait}]` + ); + }) + ) + ) + ); } if (wait === true) { diff --git a/packages/kbn-es-archiver/src/cli.ts b/packages/kbn-es-archiver/src/cli.ts index fbb5784afe5ac..899a7843a68fc 100644 --- a/packages/kbn-es-archiver/src/cli.ts +++ b/packages/kbn-es-archiver/src/cli.ts @@ -24,7 +24,7 @@ import { Client, HttpConnection } from '@elastic/elasticsearch'; import { EsArchiver } from './es_archiver'; const resolveConfigPath = (v: string) => Path.resolve(process.cwd(), v); -const defaultConfigPath = resolveConfigPath('test/functional/config.js'); +const defaultConfigPath = resolveConfigPath('test/functional/config.base.js'); export function runCli() { new RunWithCommands({ diff --git a/packages/kbn-es/src/cluster.js b/packages/kbn-es/src/cluster.js index a6faffc2cfcd7..50ca9fa91e0aa 100644 --- a/packages/kbn-es/src/cluster.js +++ b/packages/kbn-es/src/cluster.js @@ -260,6 +260,24 @@ exports.Cluster = class Cluster { await this._outcome; } + /** + * Stops ES process, it it's running, without waiting for it to shutdown gracefully + */ + async kill() { + if (this._stopCalled) { + return; + } + + this._stopCalled; + + if (!this._process || !this._outcome) { + throw new Error('ES has not been started'); + } + + await treeKillAsync(this._process.pid, 'SIGKILL'); + await this._outcome; + } + /** * Common logic from this.start() and this.run() * diff --git a/packages/kbn-pm/dist/index.js b/packages/kbn-pm/dist/index.js index 6638acfef5ef4..97ff65d4f71bc 100644 --- a/packages/kbn-pm/dist/index.js +++ b/packages/kbn-pm/dist/index.js @@ -2270,8 +2270,6 @@ exports.observeLines = observeLines; var Rx = _interopRequireWildcard(__webpack_require__("../../node_modules/rxjs/dist/esm5/index.js")); -var _operators = __webpack_require__("../../node_modules/rxjs/dist/esm5/operators/index.js"); - var _observe_readable = __webpack_require__("../../node_modules/@kbn/stdio-dev-helpers/target_node/observe_readable.js"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } @@ -2297,8 +2295,8 @@ const SEP = /\r?\n/; * @return {Rx.Observable} */ function observeLines(readable) { - const done$ = (0, _observe_readable.observeReadable)(readable).pipe((0, _operators.share)()); - const scan$ = Rx.fromEvent(readable, 'data').pipe((0, _operators.scan)(({ + const done$ = (0, _observe_readable.observeReadable)(readable).pipe(Rx.share()); + const scan$ = Rx.fromEvent(readable, 'data').pipe(Rx.scan(({ buffer }, chunk) => { buffer += chunk; @@ -2322,16 +2320,15 @@ function observeLines(readable) { }, { buffer: '' }), // stop if done completes or errors - (0, _operators.takeUntil)(done$.pipe((0, _operators.materialize)())), (0, _operators.share)()); + Rx.takeUntil(done$.pipe(Rx.materialize())), Rx.share()); return Rx.merge( // use done$ to provide completion/errors done$, // merge in the "lines" from each step - scan$.pipe((0, _operators.mergeMap)(({ + scan$.pipe(Rx.mergeMap(({ lines }) => lines || [])), // inject the "unsplit" data at the end - scan$.pipe((0, _operators.last)(), (0, _operators.mergeMap)(({ + scan$.pipe(Rx.takeLast(1), Rx.mergeMap(({ buffer - }) => buffer ? [buffer] : []), // if there were no lines, last() will error, so catch and complete - (0, _operators.catchError)(() => Rx.empty()))); + }) => buffer ? [buffer] : []))); } /***/ }), @@ -2349,8 +2346,6 @@ exports.observeReadable = observeReadable; var Rx = _interopRequireWildcard(__webpack_require__("../../node_modules/rxjs/dist/esm5/index.js")); -var _operators = __webpack_require__("../../node_modules/rxjs/dist/esm5/operators/index.js"); - function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } @@ -2369,7 +2364,9 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && * - fails on the first "error" event */ function observeReadable(readable) { - return Rx.race(Rx.fromEvent(readable, 'end').pipe((0, _operators.first)(), (0, _operators.ignoreElements)()), Rx.fromEvent(readable, 'error').pipe((0, _operators.first)(), (0, _operators.mergeMap)(err => Rx.throwError(err)))); + return Rx.race(Rx.fromEvent(readable, 'end').pipe(Rx.first(), Rx.ignoreElements()), Rx.fromEvent(readable, 'error').pipe(Rx.first(), Rx.map(err => { + throw err; + }))); } /***/ }), diff --git a/packages/kbn-stdio-dev-helpers/src/observe_lines.ts b/packages/kbn-stdio-dev-helpers/src/observe_lines.ts index 9b6ba85fea897..4b3a2ac2287da 100644 --- a/packages/kbn-stdio-dev-helpers/src/observe_lines.ts +++ b/packages/kbn-stdio-dev-helpers/src/observe_lines.ts @@ -9,7 +9,6 @@ import { Readable } from 'stream'; import * as Rx from 'rxjs'; -import { scan, takeUntil, share, materialize, mergeMap, last, catchError } from 'rxjs/operators'; const SEP = /\r?\n/; @@ -25,13 +24,13 @@ import { observeReadable } from './observe_readable'; * @return {Rx.Observable} */ export function observeLines(readable: Readable): Rx.Observable { - const done$ = observeReadable(readable).pipe(share()); + const done$ = observeReadable(readable).pipe(Rx.share()); const scan$: Rx.Observable<{ buffer: string; lines?: string[] }> = Rx.fromEvent( readable, 'data' ).pipe( - scan( + Rx.scan( ({ buffer }, chunk) => { buffer += chunk; @@ -53,9 +52,9 @@ export function observeLines(readable: Readable): Rx.Observable { ), // stop if done completes or errors - takeUntil(done$.pipe(materialize())), + Rx.takeUntil(done$.pipe(Rx.materialize())), - share() + Rx.share() ); return Rx.merge( @@ -63,14 +62,12 @@ export function observeLines(readable: Readable): Rx.Observable { done$, // merge in the "lines" from each step - scan$.pipe(mergeMap(({ lines }) => lines || [])), + scan$.pipe(Rx.mergeMap(({ lines }) => lines || [])), // inject the "unsplit" data at the end scan$.pipe( - last(), - mergeMap(({ buffer }) => (buffer ? [buffer] : [])), - // if there were no lines, last() will error, so catch and complete - catchError(() => Rx.empty()) + Rx.takeLast(1), + Rx.mergeMap(({ buffer }) => (buffer ? [buffer] : [])) ) ); } diff --git a/packages/kbn-stdio-dev-helpers/src/observe_readable.ts b/packages/kbn-stdio-dev-helpers/src/observe_readable.ts index 29aa77a538601..fa087c299aa51 100644 --- a/packages/kbn-stdio-dev-helpers/src/observe_readable.ts +++ b/packages/kbn-stdio-dev-helpers/src/observe_readable.ts @@ -9,7 +9,6 @@ import { Readable } from 'stream'; import * as Rx from 'rxjs'; -import { first, ignoreElements, mergeMap } from 'rxjs/operators'; /** * Produces an Observable from a ReadableSteam that: @@ -18,11 +17,12 @@ import { first, ignoreElements, mergeMap } from 'rxjs/operators'; */ export function observeReadable(readable: Readable): Rx.Observable { return Rx.race( - Rx.fromEvent(readable, 'end').pipe(first(), ignoreElements()), - + Rx.fromEvent(readable, 'end').pipe(Rx.first(), Rx.ignoreElements()), Rx.fromEvent(readable, 'error').pipe( - first(), - mergeMap((err) => Rx.throwError(err)) + Rx.first(), + Rx.map((err) => { + throw err; + }) ) ); } diff --git a/packages/kbn-test/BUILD.bazel b/packages/kbn-test/BUILD.bazel index 8a7aabdecd61e..f7599e6d81649 100644 --- a/packages/kbn-test/BUILD.bazel +++ b/packages/kbn-test/BUILD.bazel @@ -64,6 +64,7 @@ RUNTIME_DEPS = [ "@npm//jest-snapshot", "@npm//jest-styled-components", "@npm//joi", + "@npm//js-yaml", "@npm//mustache", "@npm//normalize-path", "@npm//parse-link-header", @@ -108,6 +109,7 @@ TYPES_DEPS = [ "@npm//@types/he", "@npm//@types/history", "@npm//@types/jest", + "@npm//@types/js-yaml", "@npm//@types/joi", "@npm//@types/lodash", "@npm//@types/mustache", diff --git a/packages/kbn-test/README.md b/packages/kbn-test/README.md index 3159e5c2492b4..72fb5c3358ce7 100644 --- a/packages/kbn-test/README.md +++ b/packages/kbn-test/README.md @@ -15,14 +15,14 @@ Functional testing methods exist in the `src/functional_tests` directory. They d #### runTests(configPaths: Array) For each config file specified in configPaths, starts Elasticsearch and Kibana once, runs tests specified in that config file, and shuts down Elasticsearch and Kibana once completed. (Repeats for every config file.) -`configPaths`: array of strings, each an absolute path to a config file that looks like [this](../../test/functional/config.js), following the config schema specified [here](../../src/functional_test_runner/lib/config/schema.js). +`configPaths`: array of strings, each an absolute path to a config file that looks like [this](../../test/functional/config.base.js), following the config schema specified [here](../../src/functional_test_runner/lib/config/schema.js). Internally the method that starts Elasticsearch comes from [kbn-es](../../packages/kbn-es). #### startServers(configPath: string) Starts Elasticsearch and Kibana servers given a specified config. -`configPath`: absolute path to a config file that looks like [this](../../test/functional/config.js), following the config schema specified [here](../../src/functional_test_runner/lib/config/schema.js). +`configPath`: absolute path to a config file that looks like [this](../../test/functional/config.base.js), following the config schema specified [here](../../src/functional_test_runner/lib/config/schema.js). Allows users to start another process to run just the tests while keeping the servers running with this method. Start servers _and_ run tests using the same config file ([see how](../../scripts/README.md)). diff --git a/packages/kbn-test/src/es/test_es_cluster.ts b/packages/kbn-test/src/es/test_es_cluster.ts index a12b1d852ced9..42dc19445c293 100644 --- a/packages/kbn-test/src/es/test_es_cluster.ts +++ b/packages/kbn-test/src/es/test_es_cluster.ts @@ -41,6 +41,7 @@ interface Node { ) => Promise<{ insallPath: string }>; start: (installPath: string, opts: Record) => Promise; stop: () => Promise; + kill: () => Promise; } export interface ICluster { @@ -268,20 +269,26 @@ export function createTestEsCluster< } async stop() { - const nodeStopPromises = []; - for (let i = 0; i < this.nodes.length; i++) { - nodeStopPromises.push(async () => { + await Promise.all( + this.nodes.map(async (node, i) => { log.info(`[es] stopping node ${nodes[i].name}`); - return await this.nodes[i].stop(); - }); - } - await Promise.all(nodeStopPromises.map(async (stop) => await stop())); + await node.stop(); + }) + ); log.info('[es] stopped'); } async cleanup() { - await this.stop(); + log.info('[es] killing', this.nodes.length === 1 ? 'node' : `${this.nodes.length} nodes`); + await Promise.all( + this.nodes.map(async (node, i) => { + log.info(`[es] stopping node ${nodes[i].name}`); + // we are deleting this install, stop ES more aggressively + await node.kill(); + }) + ); + await del(config.installPath, { force: true }); log.info('[es] cleanup complete'); } diff --git a/packages/kbn-test/src/functional_test_runner/cli.ts b/packages/kbn-test/src/functional_test_runner/cli.ts index ee01b0ccfde9c..4159533e628bc 100644 --- a/packages/kbn-test/src/functional_test_runner/cli.ts +++ b/packages/kbn-test/src/functional_test_runner/cli.ts @@ -98,11 +98,7 @@ export function runFtrCli() { }); } - try { - await functionalTestRunner.close(); - } finally { - process.exit(); - } + process.exit(); }; process.on('unhandledRejection', (err) => diff --git a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts index 1ba99fc69a5d3..0ceba511f9b9b 100644 --- a/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts +++ b/packages/kbn-test/src/functional_test_runner/functional_test_runner.ts @@ -14,10 +14,9 @@ import { REPO_ROOT } from '@kbn/utils'; import { Suite, Test } from './fake_mocha_types'; import { Lifecycle, - LifecyclePhase, - TestMetadata, readConfigFile, ProviderCollection, + Providers, readProviderSpec, setupMocha, runTests, @@ -29,10 +28,6 @@ import { import { createEsClientForFtrConfig } from '../es'; export class FunctionalTestRunner { - public readonly lifecycle = new Lifecycle(); - public readonly testMetadata = new TestMetadata(this.lifecycle); - private closed = false; - private readonly esVersion: EsVersion; constructor( private readonly log: ToolingLog, @@ -40,12 +35,6 @@ export class FunctionalTestRunner { private readonly configOverrides: any, esVersion?: string | EsVersion ) { - for (const [key, value] of Object.entries(this.lifecycle)) { - if (value instanceof LifecyclePhase) { - value.before$.subscribe(() => log.verbose('starting %j lifecycle phase', key)); - value.after$.subscribe(() => log.verbose('starting %j lifecycle phase', key)); - } - } this.esVersion = esVersion === undefined ? EsVersion.getDefault() @@ -55,19 +44,28 @@ export class FunctionalTestRunner { } async run() { - return await this._run(async (config, coreProviders) => { - SuiteTracker.startTracking(this.lifecycle, this.configFile); + const testStats = await this.getTestStats(); + + return await this.runHarness(async (config, lifecycle, coreProviders) => { + SuiteTracker.startTracking(lifecycle, this.configFile); + + const realServices = + !testStats || (testStats.testCount > 0 && testStats.nonSkippedTestCount > 0); - const providers = new ProviderCollection(this.log, [ - ...coreProviders, - ...readProviderSpec('Service', config.get('services')), - ...readProviderSpec('PageObject', config.get('pageObjects')), - ]); + const providers = realServices + ? new ProviderCollection(this.log, [ + ...coreProviders, + ...readProviderSpec('Service', config.get('services')), + ...readProviderSpec('PageObject', config.get('pageObjects')), + ]) + : this.getStubProviderCollection(config, coreProviders); - if (providers.hasService('es')) { - await this.validateEsVersion(config); + if (realServices) { + if (providers.hasService('es')) { + await this.validateEsVersion(config); + } + await providers.loadAll(); } - await providers.loadAll(); const customTestRunner = config.get('testRunner'); if (customTestRunner) { @@ -90,7 +88,7 @@ export class FunctionalTestRunner { } const mocha = await setupMocha( - this.lifecycle, + lifecycle, this.log, config, providers, @@ -108,10 +106,10 @@ export class FunctionalTestRunner { return this.simulateMochaDryRun(mocha); } - await this.lifecycle.beforeTests.trigger(mocha.suite); + await lifecycle.beforeTests.trigger(mocha.suite); this.log.info('Starting tests'); - return await runTests(this.lifecycle, mocha); + return await runTests(lifecycle, mocha); }); } @@ -143,60 +141,73 @@ export class FunctionalTestRunner { } async getTestStats() { - return await this._run(async (config, coreProviders) => { + return await this.runHarness(async (config, lifecycle, coreProviders) => { if (config.get('testRunner')) { - throw new Error('Unable to get test stats for config that uses a custom test runner'); + return; } - // replace the function of custom service providers so that they return - // promise-like objects which never resolve, essentially disabling them - // allowing us to load the test files and populate the mocha suites - const readStubbedProviderSpec = (type: string, providers: any, skip: string[]) => - readProviderSpec(type, providers).map((p) => ({ - ...p, - fn: skip.includes(p.name) - ? (ctx: any) => { - const result = ProviderCollection.callProviderFn(p.fn, ctx); - - if ('then' in result) { - throw new Error( - `Provider [${p.name}] returns a promise so it can't loaded during test analysis` - ); - } - - return result; - } - : () => ({ - then: () => {}, - }), - })); - - const providers = new ProviderCollection(this.log, [ - ...coreProviders, - ...readStubbedProviderSpec( - 'Service', - config.get('services'), - config.get('servicesRequiredForTestAnalysis') - ), - ...readStubbedProviderSpec('PageObject', config.get('pageObjects'), []), - ]); - - const mocha = await setupMocha(this.lifecycle, this.log, config, providers, this.esVersion); - - const countTests = (suite: Suite): number => - suite.suites.reduce((sum, s) => sum + countTests(s), suite.tests.length); + const providers = this.getStubProviderCollection(config, coreProviders); + const mocha = await setupMocha(lifecycle, this.log, config, providers, this.esVersion); + + const queue = new Set([mocha.suite]); + const allTests: Test[] = []; + for (const suite of queue) { + for (const test of suite.tests) { + allTests.push(test); + } + for (const childSuite of suite.suites) { + queue.add(childSuite); + } + } return { - testCount: countTests(mocha.suite), + testCount: allTests.length, + nonSkippedTestCount: allTests.filter((t) => !t.pending).length, testsExcludedByTag: mocha.testsExcludedByTag.map((t: Test) => t.fullTitle()), }; }); } - async _run( - handler: (config: Config, coreProvider: ReturnType) => Promise + private getStubProviderCollection(config: Config, coreProviders: Providers) { + // when we want to load the tests but not actually run anything we can + // use stubbed providers which allow mocha to do it's thing without taking + // too much time + const readStubbedProviderSpec = (type: string, providers: any, skip: string[]) => + readProviderSpec(type, providers).map((p) => ({ + ...p, + fn: skip.includes(p.name) + ? (ctx: any) => { + const result = ProviderCollection.callProviderFn(p.fn, ctx); + + if ('then' in result) { + throw new Error( + `Provider [${p.name}] returns a promise so it can't loaded during test analysis` + ); + } + + return result; + } + : () => ({ + then: () => {}, + }), + })); + + return new ProviderCollection(this.log, [ + ...coreProviders, + ...readStubbedProviderSpec( + 'Service', + config.get('services'), + config.get('servicesRequiredForTestAnalysis') + ), + ...readStubbedProviderSpec('PageObject', config.get('pageObjects'), []), + ]); + } + + private async runHarness( + handler: (config: Config, lifecycle: Lifecycle, coreProviders: Providers) => Promise ): Promise { let runErrorOccurred = false; + const lifecycle = new Lifecycle(this.log); try { const config = await readConfigFile( @@ -205,7 +216,7 @@ export class FunctionalTestRunner { this.configFile, this.configOverrides ); - this.log.info('Config loaded'); + this.log.debug('Config loaded'); if ( (!config.get('testFiles') || config.get('testFiles').length === 0) && @@ -217,26 +228,25 @@ export class FunctionalTestRunner { const dockerServers = new DockerServersService( config.get('dockerServers'), this.log, - this.lifecycle + lifecycle ); // base level services that functional_test_runner exposes const coreProviders = readProviderSpec('Service', { - lifecycle: () => this.lifecycle, + lifecycle: () => lifecycle, log: () => this.log, - testMetadata: () => this.testMetadata, config: () => config, dockerServers: () => dockerServers, esVersion: () => this.esVersion, }); - return await handler(config, coreProviders); + return await handler(config, lifecycle, coreProviders); } catch (runError) { runErrorOccurred = true; throw runError; } finally { try { - await this.close(); + await lifecycle.cleanup.trigger(); } catch (closeError) { if (runErrorOccurred) { this.log.error('failed to close functional_test_runner'); @@ -249,13 +259,6 @@ export class FunctionalTestRunner { } } - async close() { - if (this.closed) return; - - this.closed = true; - await this.lifecycle.cleanup.trigger(); - } - simulateMochaDryRun(mocha: any) { interface TestEntry { file: string; diff --git a/packages/kbn-test/src/functional_test_runner/index.ts b/packages/kbn-test/src/functional_test_runner/index.ts index b5d55c28ee9b2..1a8efb6097048 100644 --- a/packages/kbn-test/src/functional_test_runner/index.ts +++ b/packages/kbn-test/src/functional_test_runner/index.ts @@ -15,7 +15,6 @@ export { Lifecycle, LifecyclePhase, } from './lib'; -export type { ScreenshotRecord } from './lib'; export { runFtrCli } from './cli'; export * from './lib/docker_servers'; export * from './public_types'; diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/ftr_configs_manifest.ts b/packages/kbn-test/src/functional_test_runner/lib/config/ftr_configs_manifest.ts new file mode 100644 index 0000000000000..93cab4bfaac95 --- /dev/null +++ b/packages/kbn-test/src/functional_test_runner/lib/config/ftr_configs_manifest.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import Fs from 'fs'; + +import { REPO_ROOT } from '@kbn/utils'; +import JsYaml from 'js-yaml'; + +export const FTR_CONFIGS_MANIFEST_REL = '.buildkite/ftr_configs.yml'; + +const ftrConfigsManifest = JsYaml.safeLoad( + Fs.readFileSync(Path.resolve(REPO_ROOT, FTR_CONFIGS_MANIFEST_REL), 'utf8') +); + +export const FTR_CONFIGS_MANIFEST_PATHS = (Object.values(ftrConfigsManifest) as string[][]) + .flat() + .map((rel) => Path.resolve(REPO_ROOT, rel)); diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.test.js b/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.test.ts similarity index 70% rename from packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.test.js rename to packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.test.ts index d1ce17cc95b7b..29b723dae7195 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.test.js +++ b/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.test.ts @@ -14,36 +14,35 @@ import { EsVersion } from '../es_version'; const log = new ToolingLog(); const esVersion = new EsVersion('8.0.0'); +const CONFIG_PATH_1 = require.resolve('./__fixtures__/config.1.js'); +const CONFIG_PATH_2 = require.resolve('./__fixtures__/config.2.js'); +const CONFIG_PATH_INVALID = require.resolve('./__fixtures__/config.invalid.js'); + describe('readConfigFile()', () => { it('reads config from a file, returns an instance of Config class', async () => { - const config = await readConfigFile(log, esVersion, require.resolve('./__fixtures__/config.1')); + const config = await readConfigFile(log, esVersion, CONFIG_PATH_1); expect(config instanceof Config).toBeTruthy(); expect(config.get('testFiles')).toEqual(['config.1']); }); it('merges setting overrides into log', async () => { - const config = await readConfigFile( - log, - esVersion, - require.resolve('./__fixtures__/config.1'), - { - screenshots: { - directory: 'foo.bar', - }, - } - ); + const config = await readConfigFile(log, esVersion, CONFIG_PATH_1, { + screenshots: { + directory: 'foo.bar', + }, + }); expect(config.get('screenshots.directory')).toBe('foo.bar'); }); it('supports loading config files from within config files', async () => { - const config = await readConfigFile(log, esVersion, require.resolve('./__fixtures__/config.2')); + const config = await readConfigFile(log, esVersion, CONFIG_PATH_2); expect(config.get('testFiles')).toEqual(['config.1', 'config.2']); }); it('throws if settings are invalid', async () => { try { - await readConfigFile(log, esVersion, require.resolve('./__fixtures__/config.invalid')); + await readConfigFile(log, esVersion, CONFIG_PATH_INVALID); throw new Error('expected readConfigFile() to fail'); } catch (err) { expect(err.message).toMatch(/"foo"/); diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.ts b/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.ts index d026842f3a4f1..24702d699064c 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/read_config_file.ts @@ -6,25 +6,41 @@ * Side Public License, v 1. */ +import Path from 'path'; import { ToolingLog } from '@kbn/tooling-log'; import { defaultsDeep } from 'lodash'; +import { createFlagError } from '@kbn/dev-utils'; import { Config } from './config'; import { EsVersion } from '../es_version'; +import { FTR_CONFIGS_MANIFEST_REL, FTR_CONFIGS_MANIFEST_PATHS } from './ftr_configs_manifest'; const cache = new WeakMap(); async function getSettingsFromFile( log: ToolingLog, esVersion: EsVersion, - path: string, - settingOverrides: any + options: { + path: string; + settingOverrides: any; + primary: boolean; + } ) { - const configModule = require(path); // eslint-disable-line @typescript-eslint/no-var-requires + if ( + options.primary && + !FTR_CONFIGS_MANIFEST_PATHS.includes(options.path) && + !options.path.includes(`${Path.sep}__fixtures__${Path.sep}`) + ) { + throw createFlagError( + `Refusing to load FTR Config which is not listed in [${FTR_CONFIGS_MANIFEST_REL}]. All FTR Config files must be listed there, use the "enabled" key if the FTR Config should be run on automatically on PR CI, or the "disabled" key if it is run manually or by a special job.` + ); + } + + const configModule = require(options.path); // eslint-disable-line @typescript-eslint/no-var-requires const configProvider = configModule.__esModule ? configModule.default : configModule; if (!cache.has(configProvider)) { - log.debug('Loading config file from %j', path); + log.debug('Loading config file from %j', options.path); cache.set( configProvider, configProvider({ @@ -32,7 +48,11 @@ async function getSettingsFromFile( esVersion, async readConfigFile(p: string, o: any) { return new Config({ - settings: await getSettingsFromFile(log, esVersion, p, o), + settings: await getSettingsFromFile(log, esVersion, { + path: p, + settingOverrides: o, + primary: false, + }), primary: false, path: p, }); @@ -43,7 +63,7 @@ async function getSettingsFromFile( const settingsWithDefaults: any = defaultsDeep( {}, - settingOverrides, + options.settingOverrides, await cache.get(configProvider)! ); @@ -57,7 +77,11 @@ export async function readConfigFile( settingOverrides: any = {} ) { return new Config({ - settings: await getSettingsFromFile(log, esVersion, path, settingOverrides), + settings: await getSettingsFromFile(log, esVersion, { + path, + settingOverrides, + primary: true, + }), primary: true, path, }); diff --git a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts index 17c3af046f92f..d2182064d352e 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/config/schema.ts @@ -226,6 +226,11 @@ export const schema = Joi.object() wait: Joi.object() .regex() .default(/Kibana is now available/), + + /** + * Does this test config only work when run against source? + */ + alwaysUseSource: Joi.boolean().default(false), }) .default(), env: Joi.object().unknown().default(), diff --git a/packages/kbn-test/src/functional_test_runner/lib/index.ts b/packages/kbn-test/src/functional_test_runner/lib/index.ts index 077a62e8e74e5..9f637f8bd5b4f 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/index.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/index.ts @@ -12,7 +12,6 @@ export { readConfigFile, Config } from './config'; export * from './providers'; // @internal export { runTests, setupMocha } from './mocha'; -export * from './test_metadata'; export * from './docker_servers'; export { SuiteTracker } from './suite_tracker'; diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts index e683ec23a8d84..230eacb91008e 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle.ts @@ -6,29 +6,51 @@ * Side Public License, v 1. */ +import * as Rx from 'rxjs'; +import { ToolingLog } from '@kbn/tooling-log'; + import { LifecyclePhase } from './lifecycle_phase'; import { Suite, Test } from '../fake_mocha_types'; export class Lifecycle { + /** root subscription to cleanup lifecycle phases when lifecycle completes */ + private readonly sub = new Rx.Subscription(); + /** lifecycle phase that will run handlers once before tests execute */ - public readonly beforeTests = new LifecyclePhase<[Suite]>({ + public readonly beforeTests = new LifecyclePhase<[Suite]>(this.sub, { singular: true, }); /** lifecycle phase that runs handlers before each runnable (test and hooks) */ - public readonly beforeEachRunnable = new LifecyclePhase<[Test]>(); + public readonly beforeEachRunnable = new LifecyclePhase<[Test]>(this.sub); /** lifecycle phase that runs handlers before each suite */ - public readonly beforeTestSuite = new LifecyclePhase<[Suite]>(); + public readonly beforeTestSuite = new LifecyclePhase<[Suite]>(this.sub); /** lifecycle phase that runs handlers before each test */ - public readonly beforeEachTest = new LifecyclePhase<[Test]>(); + public readonly beforeEachTest = new LifecyclePhase<[Test]>(this.sub); /** lifecycle phase that runs handlers after each suite */ - public readonly afterTestSuite = new LifecyclePhase<[Suite]>(); + public readonly afterTestSuite = new LifecyclePhase<[Suite]>(this.sub); /** lifecycle phase that runs handlers after a test fails */ - public readonly testFailure = new LifecyclePhase<[Error, Test]>(); + public readonly testFailure = new LifecyclePhase<[Error, Test]>(this.sub); /** lifecycle phase that runs handlers after a hook fails */ - public readonly testHookFailure = new LifecyclePhase<[Error, Test]>(); + public readonly testHookFailure = new LifecyclePhase<[Error, Test]>(this.sub); /** lifecycle phase that runs handlers at the very end of execution */ - public readonly cleanup = new LifecyclePhase<[]>({ + public readonly cleanup = new LifecyclePhase<[]>(this.sub, { singular: true, }); + + constructor(log: ToolingLog) { + for (const [name, phase] of Object.entries(this)) { + if (phase instanceof LifecyclePhase) { + phase.before$.subscribe(() => log.verbose('starting %j lifecycle phase', name)); + phase.after$.subscribe(() => log.verbose('starting %j lifecycle phase', name)); + } + } + + // after the singular cleanup lifecycle phase completes unsubscribe from the root subscription + this.cleanup.after$.pipe(Rx.materialize()).subscribe((n) => { + if (n.kind === 'C') { + this.sub.unsubscribe(); + } + }); + } } diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts index 503a9490f2664..47ab24169d204 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.test.ts @@ -26,7 +26,7 @@ describe('with randomness', () => { }); it('calls handlers in random order', async () => { - const phase = new LifecyclePhase(); + const phase = new LifecyclePhase(new Rx.Subscription()); const order: string[] = []; phase.add( @@ -69,7 +69,7 @@ describe('without randomness', () => { afterEach(() => jest.restoreAllMocks()); it('calls all handlers and throws first error', async () => { - const phase = new LifecyclePhase(); + const phase = new LifecyclePhase(new Rx.Subscription()); const fn1 = jest.fn(); phase.add(fn1); @@ -88,7 +88,7 @@ describe('without randomness', () => { }); it('triggers before$ just before calling handler and after$ once it resolves', async () => { - const phase = new LifecyclePhase(); + const phase = new LifecyclePhase(new Rx.Subscription()); const order: string[] = []; const beforeSub = jest.fn(() => order.push('before')); @@ -116,7 +116,7 @@ describe('without randomness', () => { }); it('completes before$ and after$ if phase is singular', async () => { - const phase = new LifecyclePhase({ singular: true }); + const phase = new LifecyclePhase(new Rx.Subscription(), { singular: true }); const beforeNotifs: Array> = []; phase.before$.pipe(materialize()).subscribe((n) => beforeNotifs.push(n)); @@ -160,7 +160,7 @@ describe('without randomness', () => { }); it('completes before$ subscribers after trigger of singular phase', async () => { - const phase = new LifecyclePhase({ singular: true }); + const phase = new LifecyclePhase(new Rx.Subscription(), { singular: true }); await phase.trigger(); await expect(phase.before$.pipe(materialize(), toArray()).toPromise()).resolves @@ -177,7 +177,7 @@ describe('without randomness', () => { }); it('replays after$ event subscribers after trigger of singular phase', async () => { - const phase = new LifecyclePhase({ singular: true }); + const phase = new LifecyclePhase(new Rx.Subscription(), { singular: true }); await phase.trigger(); await expect(phase.after$.pipe(materialize(), toArray()).toPromise()).resolves diff --git a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.ts b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.ts index 09e7c6f3b8d15..df4b26230d4da 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/lifecycle_phase.ts @@ -26,6 +26,7 @@ export class LifecyclePhase { public readonly after$: Rx.Observable; constructor( + sub: Rx.Subscription, private readonly options: { singular?: boolean; } = {} @@ -35,6 +36,12 @@ export class LifecyclePhase { this.afterSubj = this.options.singular ? new Rx.ReplaySubject(1) : new Rx.Subject(); this.after$ = this.afterSubj.asObservable(); + + sub.add(() => { + this.beforeSubj.complete(); + this.afterSubj.complete(); + this.handlers.length = 0; + }); } public add(fn: (...args: Args) => Promise | void) { diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js index b9d4ed6ef7b5e..62104cebf9cba 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/decorate_mocha_ui.js @@ -12,6 +12,32 @@ import { createAssignmentProxy } from './assignment_proxy'; import { wrapFunction } from './wrap_function'; import { wrapRunnableArgs } from './wrap_runnable_args'; +const allTestsSkippedCache = new WeakMap(); +function allTestsAreSkipped(suite) { + // cache result for each suite so we don't have to traverse over and over + const cache = allTestsSkippedCache.get(suite); + if (cache) { + return cache; + } + + // if this suite is skipped directly then all it's children are skipped + if (suite.pending) { + allTestsSkippedCache.set(suite, true); + return true; + } + + // if any of this suites own tests are not skipped, then we don't need to traverse to child suites + if (suite.tests.some((t) => !t.pending)) { + allTestsSkippedCache.set(suite, false); + return false; + } + + // otherwise traverse down through the child suites and return true only if all children are all skipped + const childrenSkipped = suite.suites.every(allTestsAreSkipped); + allTestsSkippedCache.set(suite, childrenSkipped); + return childrenSkipped; +} + export function decorateMochaUi(log, lifecycle, context, { rootTags }) { // incremented at the start of each suite, decremented after // so that in each non-suite call we can know if we are within @@ -71,6 +97,12 @@ export function decorateMochaUi(log, lifecycle, context, { rootTags }) { provider.call(this); + if (allTestsAreSkipped(this)) { + // all the children in this suite are skipped, so make sure the suite is + // marked as pending so that its hooks are not run + this.pending = true; + } + after('afterTestSuite.trigger', async () => { await lifecycle.afterTestSuite.trigger(this); }); diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.test.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.test.js index 191503af123d0..3d1867aa0eed0 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.test.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.test.js @@ -69,6 +69,9 @@ function setup({ include, exclude, esVersion }) { info(...args) { history.push(`info: ${format(...args)}`); }, + debug(...args) { + history.push(`debg: ${format(...args)}`); + }, }, mocha, include, @@ -221,7 +224,7 @@ it(`excludes tests which don't meet the esVersionRequirement`, async () => { expect(history).toMatchInlineSnapshot(` Array [ - "info: Only running suites which are compatible with ES version 9.0.0", + "debg: Only running suites which are compatible with ES version 9.0.0", "suite: ", "suite: level 1", "suite: level 1 level 1a", diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.ts b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.ts index 98db434b3b088..6bb95acd407de 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/filter_suites.ts @@ -44,7 +44,7 @@ export function filterSuites({ log, mocha, include, exclude, esVersion }: Option if (esVersion) { // traverse the test graph and exclude any tests which don't meet their esVersionRequirement - log.info('Only running suites which are compatible with ES version', esVersion.toString()); + log.debug('Only running suites which are compatible with ES version', esVersion.toString()); (function recurse(parentSuite: SuiteInternal) { const children = parentSuite.suites; parentSuite.suites = []; diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/ci_stats_ftr_reporter.ts b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/ci_stats_ftr_reporter.ts index ee993122d7d9c..96900555db745 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/ci_stats_ftr_reporter.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/ci_stats_ftr_reporter.ts @@ -17,7 +17,6 @@ import { import { Config } from '../../config'; import { Runner } from '../../../fake_mocha_types'; -import { TestMetadata, ScreenshotRecord } from '../../test_metadata'; import { Lifecycle } from '../../lifecycle'; import { getSnapshotOfRunnableLogs } from '../../../../mocha'; @@ -36,7 +35,6 @@ interface Runnable { file: string; title: string; parent: Suite; - _screenshots?: ScreenshotRecord[]; } function getHookType(hook: Runnable): CiStatsTestType { @@ -60,15 +58,18 @@ export function setupCiStatsFtrTestGroupReporter({ config, lifecycle, runner, - testMetadata, reporter, }: { config: Config; lifecycle: Lifecycle; runner: Runner; - testMetadata: TestMetadata; reporter: CiStatsReporter; }) { + const testGroupType = process.env.TEST_GROUP_TYPE_FUNCTIONAL; + if (!testGroupType) { + throw new Error('missing process.env.TEST_GROUP_TYPE_FUNCTIONAL'); + } + let startMs: number | undefined; runner.on('start', () => { startMs = Date.now(); @@ -78,7 +79,7 @@ export function setupCiStatsFtrTestGroupReporter({ const group: CiStatsReportTestsOptions['group'] = { startTime: new Date(start).toJSON(), durationMs: 0, - type: config.path.startsWith('x-pack') ? 'X-Pack Functional Tests' : 'Functional Tests', + type: testGroupType, name: Path.relative(REPO_ROOT, config.path), result: 'skip', meta: { @@ -106,10 +107,6 @@ export function setupCiStatsFtrTestGroupReporter({ type, error: error?.stack, stdout: getSnapshotOfRunnableLogs(runnable), - screenshots: testMetadata.getScreenshots(runnable).map((s) => ({ - base64Png: s.base64Png, - name: s.name, - })), }); } diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js index 973a552ebb728..66a4c9ce4fd04 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/reporter/reporter.js @@ -24,7 +24,6 @@ export function MochaReporterProvider({ getService }) { const log = getService('log'); const config = getService('config'); const lifecycle = getService('lifecycle'); - const testMetadata = getService('testMetadata'); let originalLogWriters; let reporterCaptureStartTime; @@ -61,7 +60,6 @@ export function MochaReporterProvider({ getService }) { config, lifecycle, runner, - testMetadata, }); } } diff --git a/packages/kbn-test/src/functional_test_runner/lib/mocha/validate_ci_group_tags.js b/packages/kbn-test/src/functional_test_runner/lib/mocha/validate_ci_group_tags.js index 4f798839d7231..a0298b635a135 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/mocha/validate_ci_group_tags.js +++ b/packages/kbn-test/src/functional_test_runner/lib/mocha/validate_ci_group_tags.js @@ -48,8 +48,10 @@ export function validateCiGroupTags(log, mocha) { const queue = [mocha.suite]; while (queue.length) { const suite = queue.shift(); - if (getCiGroups(suite).length > 1) { - suitesWithMultipleCiGroups.push(suite); + if (getCiGroups(suite).length) { + throw new Error( + 'ciGroups are no longer needed and should be removed. If you need to split up your FTR config because it is taking too long to complete then create one or more a new FTR config files and split your test files amoungst them' + ); } else { queue.push(...(suite.suites ?? [])); } diff --git a/packages/kbn-test/src/functional_test_runner/lib/providers/index.ts b/packages/kbn-test/src/functional_test_runner/lib/providers/index.ts index 578e41ca8e827..c0b85370d321c 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/providers/index.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/providers/index.ts @@ -7,6 +7,6 @@ */ export { ProviderCollection } from './provider_collection'; -export { readProviderSpec } from './read_provider_spec'; +export * from './read_provider_spec'; export { createAsyncInstance } from './async_instance'; export type { Provider } from './read_provider_spec'; diff --git a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts index c199dfc092789..403708b893db8 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/snapshots/decorate_snapshot_ui.test.ts @@ -6,11 +6,14 @@ * Side Public License, v 1. */ +import path from 'path'; +import fs from 'fs'; + +import { ToolingLog } from '@kbn/tooling-log'; + import { Suite, Test } from '../../fake_mocha_types'; import { Lifecycle } from '../lifecycle'; import { decorateSnapshotUi, expectSnapshot } from './decorate_snapshot_ui'; -import path from 'path'; -import fs from 'fs'; const createRootSuite = () => { const suite = { @@ -65,7 +68,7 @@ describe('decorateSnapshotUi', () => { let lifecycle: Lifecycle; let rootSuite: Suite; beforeEach(async () => { - lifecycle = new Lifecycle(); + lifecycle = new Lifecycle(new ToolingLog()); rootSuite = createRootSuite(); decorateSnapshotUi({ lifecycle, updateSnapshots: false, isCi: false }); @@ -116,7 +119,7 @@ describe('decorateSnapshotUi', () => { let lifecycle: Lifecycle; let rootSuite: Suite; beforeEach(async () => { - lifecycle = new Lifecycle(); + lifecycle = new Lifecycle(new ToolingLog()); rootSuite = createRootSuite(); decorateSnapshotUi({ lifecycle, updateSnapshots: false, isCi: false }); @@ -162,7 +165,7 @@ exports[\`Test2 1\`] = \`"bar"\`; let lifecycle: Lifecycle; let rootSuite: Suite; beforeEach(async () => { - lifecycle = new Lifecycle(); + lifecycle = new Lifecycle(new ToolingLog()); rootSuite = createRootSuite(); decorateSnapshotUi({ lifecycle, updateSnapshots: true, isCi: false }); @@ -185,7 +188,7 @@ exports[\`Test2 1\`] = \`"bar"\`; fs.writeFileSync( snapshotFile, `// Jest Snapshot v1, https://goo.gl/fbAQLP - + exports[\`Test 1\`] = \`"foo"\`; `, { encoding: 'utf-8' } @@ -219,7 +222,7 @@ exports[\`Test2 1\`] = \`"bar"\`; let lifecycle: Lifecycle; let rootSuite: Suite; beforeEach(async () => { - lifecycle = new Lifecycle(); + lifecycle = new Lifecycle(new ToolingLog()); rootSuite = createRootSuite(); decorateSnapshotUi({ lifecycle, updateSnapshots: false, isCi: true }); diff --git a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts index 53ce4c74c1388..43f1508ab7938 100644 --- a/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts +++ b/packages/kbn-test/src/functional_test_runner/lib/suite_tracker.test.ts @@ -9,6 +9,8 @@ import fs from 'fs'; import { join, resolve } from 'path'; +import { ToolingLog } from '@kbn/tooling-log'; + jest.mock('fs'); jest.mock('@kbn/utils', () => { return { REPO_ROOT: '/dev/null/root' }; @@ -60,7 +62,7 @@ describe('SuiteTracker', () => { }; const runLifecycleWithMocks = async (mocks: Suite[], fn: (objs: any) => any = () => {}) => { - const lifecycle = new Lifecycle(); + const lifecycle = new Lifecycle(new ToolingLog()); const suiteTracker = SuiteTracker.startTracking( lifecycle, resolve(REPO_ROOT, MOCK_CONFIG_PATH) diff --git a/packages/kbn-test/src/functional_test_runner/lib/test_metadata.ts b/packages/kbn-test/src/functional_test_runner/lib/test_metadata.ts deleted file mode 100644 index 5789231f87044..0000000000000 --- a/packages/kbn-test/src/functional_test_runner/lib/test_metadata.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Lifecycle } from './lifecycle'; - -export interface ScreenshotRecord { - name: string; - base64Png: string; - baselinePath?: string; - failurePath?: string; -} - -export class TestMetadata { - // mocha's global types mean we can't import Mocha or it will override the global jest types.............. - private currentRunnable?: any; - - constructor(lifecycle: Lifecycle) { - lifecycle.beforeEachRunnable.add((runnable) => { - this.currentRunnable = runnable; - }); - } - - addScreenshot(screenshot: ScreenshotRecord) { - this.currentRunnable._screenshots = (this.currentRunnable._screenshots || []).concat( - screenshot - ); - } - - getScreenshots(test: any): ScreenshotRecord[] { - if (!test || typeof test !== 'object' || !test._screenshots) { - return []; - } - - return test._screenshots.slice(); - } -} diff --git a/packages/kbn-test/src/functional_test_runner/public_types.ts b/packages/kbn-test/src/functional_test_runner/public_types.ts index 2d632b28d6e21..67adceaf22323 100644 --- a/packages/kbn-test/src/functional_test_runner/public_types.ts +++ b/packages/kbn-test/src/functional_test_runner/public_types.ts @@ -8,10 +8,10 @@ import type { ToolingLog } from '@kbn/tooling-log'; -import type { Config, Lifecycle, TestMetadata, DockerServersService, EsVersion } from './lib'; +import type { Config, Lifecycle, DockerServersService, EsVersion } from './lib'; import type { Test, Suite } from './fake_mocha_types'; -export { Lifecycle, Config, TestMetadata }; +export { Lifecycle, Config }; export interface AsyncInstance { /** @@ -56,9 +56,7 @@ export interface GenericFtrProviderContext< * Determine if a service is avaliable * @param serviceName */ - hasService( - serviceName: 'config' | 'log' | 'lifecycle' | 'testMetadata' | 'dockerServers' | 'esVersion' - ): true; + hasService(serviceName: 'config' | 'log' | 'lifecycle' | 'dockerServers' | 'esVersion'): true; hasService(serviceName: K): serviceName is K; hasService(serviceName: string): serviceName is Extract; @@ -71,7 +69,6 @@ export interface GenericFtrProviderContext< getService(serviceName: 'log'): ToolingLog; getService(serviceName: 'lifecycle'): Lifecycle; getService(serviceName: 'dockerServers'): DockerServersService; - getService(serviceName: 'testMetadata'): TestMetadata; getService(serviceName: 'esVersion'): EsVersion; getService(serviceName: T): ServiceMap[T]; diff --git a/packages/kbn-test/src/functional_tests/lib/run_ftr.ts b/packages/kbn-test/src/functional_tests/lib/run_ftr.ts index 6887a664d6657..4c4a7128a05a9 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_ftr.ts +++ b/packages/kbn-test/src/functional_tests/lib/run_ftr.ts @@ -90,6 +90,9 @@ export async function assertNoneExcluded({ configPath, options }: CreateFtrParam } const stats = await ftr.getTestStats(); + if (!stats) { + throw new Error('unable to get test stats'); + } if (stats.testsExcludedByTag.length > 0) { throw new CliError(` ${stats.testsExcludedByTag.length} tests in the ${configPath} config @@ -122,5 +125,8 @@ export async function hasTests({ configPath, options }: CreateFtrParams) { return true; } const stats = await ftr.getTestStats(); - return stats.testCount > 0; + if (!stats) { + throw new Error('unable to get test stats'); + } + return stats.nonSkippedTestCount > 0; } diff --git a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts index 6305e522b3929..47d0b1c93b620 100644 --- a/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts +++ b/packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts @@ -36,13 +36,13 @@ export async function runKibanaServer({ config: Config; options: { installDir?: string; extraKbnOpts?: string[] }; }) { - const { installDir } = options; const runOptions = config.get('kbnTestServer.runOptions'); + const installDir = runOptions.alwaysUseSource ? undefined : options.installDir; const env = config.get('kbnTestServer.env'); await procs.run('kibana', { cmd: getKibanaCmd(installDir), - args: filterCliArgs(collectCliArgs(config, options)), + args: filterCliArgs(collectCliArgs(config, installDir, options.extraKbnOpts)), env: { FORCE_COLOR: 1, ...process.env, @@ -70,10 +70,7 @@ function getKibanaCmd(installDir?: string) { * passed, we run from source code. We also allow passing in extra * Kibana server options, so we tack those on here. */ -function collectCliArgs( - config: Config, - { installDir, extraKbnOpts }: { installDir?: string; extraKbnOpts?: string[] } -) { +function collectCliArgs(config: Config, installDir?: string, extraKbnOpts: string[] = []) { const buildArgs: string[] = config.get('kbnTestServer.buildArgs') || []; const sourceArgs: string[] = config.get('kbnTestServer.sourceArgs') || []; const serverArgs: string[] = config.get('kbnTestServer.serverArgs') || []; @@ -82,7 +79,7 @@ function collectCliArgs( serverArgs, (args) => (installDir ? args.filter((a: string) => a !== '--oss') : args), (args) => (installDir ? [...buildArgs, ...args] : [KIBANA_EXEC_PATH, ...sourceArgs, ...args]), - (args) => args.concat(extraKbnOpts || []) + (args) => args.concat(extraKbnOpts) ); } diff --git a/packages/kbn-test/src/functional_tests/tasks.ts b/packages/kbn-test/src/functional_tests/tasks.ts index 8116fa25650a1..dd9fe4c93016c 100644 --- a/packages/kbn-test/src/functional_tests/tasks.ts +++ b/packages/kbn-test/src/functional_tests/tasks.ts @@ -8,6 +8,7 @@ import { relative } from 'path'; import * as Rx from 'rxjs'; +import { setTimeout } from 'timers/promises'; import { startWith, switchMap, take } from 'rxjs/operators'; import { withProcRunner } from '@kbn/dev-utils'; import { ToolingLog } from '@kbn/tooling-log'; @@ -63,7 +64,7 @@ interface RunTestsParams extends CreateFtrOptions { assertNoneExcluded: boolean; } export async function runTests(options: RunTestsParams) { - if (!process.env.KBN_NP_PLUGINS_BUILT && !options.assertNoneExcluded) { + if (!process.env.CI && !options.assertNoneExcluded) { const log = options.createLogger(); log.warning('❗️❗️❗️'); log.warning('❗️❗️❗️'); @@ -91,21 +92,18 @@ export async function runTests(options: RunTestsParams) { return; } - log.write('--- determining which ftr configs to run'); - const configPathsWithTests: string[] = []; - for (const configPath of options.configs) { - log.info('testing', relative(REPO_ROOT, configPath)); - await log.indent(4, async () => { - if (await hasTests({ configPath, options: { ...options, log } })) { - configPathsWithTests.push(configPath); + for (const [i, configPath] of options.configs.entries()) { + await log.indent(0, async () => { + if (options.configs.length > 1) { + const progress = `${i + 1}/${options.configs.length}`; + log.write(`--- [${progress}] Running ${relative(REPO_ROOT, configPath)}`); } - }); - } - for (const [i, configPath] of configPathsWithTests.entries()) { - await log.indent(0, async () => { - const progress = `${i + 1}/${configPathsWithTests.length}`; - log.write(`--- [${progress}] Running ${relative(REPO_ROOT, configPath)}`); + if (!(await hasTests({ configPath, options: { ...options, log } }))) { + // just run the FTR, no Kibana or ES, which will quickly report a skipped test group to ci-stats and continue + await runFtr({ configPath, options: { ...options, log } }); + return; + } await withProcRunner(log, async (procs) => { const config = await readConfigFile(log, options.esVersion, configPath); @@ -122,7 +120,7 @@ export async function runTests(options: RunTestsParams) { const delay = config.get('kbnTestServer.delayShutdown'); if (typeof delay === 'number') { log.info('Delaying shutdown of Kibana for', delay, 'ms'); - await new Promise((r) => setTimeout(r, delay)); + await setTimeout(delay); } await procs.stop('kibana'); diff --git a/scripts/README.md b/scripts/README.md index 960e8ab2ed0b8..a743ce5e1d53d 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -17,13 +17,13 @@ This directory is excluded from the build and tools within it should help users ## Functional Test Scripts -**`node scripts/functional_tests [--config test/functional/config.js --config test/api_integration/config.js]`** +**`node scripts/functional_tests [--config test/functional/config.base.js --config test/api_integration/config.js]`** Runs all the functional tests: selenium tests and api integration tests. List configs with multiple `--config` arguments. Uses the [@kbn/test](../packages/kbn-test) library to run Elasticsearch and Kibana servers and tests against those servers, for multiple server+test setups. In particular, calls out to [`runTests()`](../packages/kbn-test/src/functional_tests/tasks.js). Can be run on a single config. -**`node scripts/functional_tests_server [--config test/functional/config.js]`** +**`node scripts/functional_tests_server [--config test/functional/config.base.js]`** -Starts just the Elasticsearch and Kibana servers given a single config, i.e. via `--config test/functional/config.js` or `--config test/api_integration/config`. Allows the user to start just the servers with this script, and keep them running while running tests against these servers. The idea is that the same config file configures both Elasticsearch and Kibana servers. Uses the [`startServers()`](../packages/kbn-test/src/functional_tests/tasks.js#L52-L80) method from [@kbn/test](../packages/kbn-test) library. +Starts just the Elasticsearch and Kibana servers given a single config, i.e. via `--config test/functional/config.base.js` or `--config test/api_integration/config`. Allows the user to start just the servers with this script, and keep them running while running tests against these servers. The idea is that the same config file configures both Elasticsearch and Kibana servers. Uses the [`startServers()`](../packages/kbn-test/src/functional_tests/tasks.js#L52-L80) method from [@kbn/test](../packages/kbn-test) library. Example. Start servers _and_ run tests, separately, but using the same config: @@ -51,7 +51,7 @@ If you wish to load up specific es archived data for your test, you can do so vi node scripts/es_archiver.js load [--es-url=http://username:password@localhost:9200] [--kibana-url=http://username:password@localhost:5601/{basepath?}] ``` -That will load the specified archive located in the archive directory specified by the default functional config file, located in `test/functional/config.js`. To load archives from other function config files you can pass `--config path/to/config.js`. +That will load the specified archive located in the archive directory specified by the default functional config file, located in `test/functional/config.base.js`. To load archives from other function config files you can pass `--config path/to/config.js`. *Note:* The `--es-url` and `--kibana-url` options may or may not be neccessary depending on your current Kibana configuration settings, and their values may also change based on those settings (for example if you are not running with security you will not need the `username:password` portion). diff --git a/scripts/functional_tests.js b/scripts/functional_tests.js index 1e963660a1e03..eb1dea2dcab36 100644 --- a/scripts/functional_tests.js +++ b/scripts/functional_tests.js @@ -7,26 +7,4 @@ */ require('../src/setup_node_env'); -require('@kbn/test').runTestsCli([ - require.resolve('../test/functional/config.ccs.ts'), - require.resolve('../test/functional/config.js'), - require.resolve('../test/plugin_functional/config.ts'), - require.resolve('../test/ui_capabilities/newsfeed_err/config.ts'), - require.resolve('../test/new_visualize_flow/config.ts'), - require.resolve('../test/interactive_setup_api_integration/enrollment_flow.config.ts'), - require.resolve('../test/interactive_setup_api_integration/manual_configuration_flow.config.ts'), - require.resolve( - '../test/interactive_setup_api_integration/manual_configuration_flow_without_tls.config.ts' - ), - require.resolve('../test/interactive_setup_functional/enrollment_token.config.ts'), - require.resolve('../test/interactive_setup_functional/manual_configuration.config.ts'), - require.resolve( - '../test/interactive_setup_functional/manual_configuration_without_security.config.ts' - ), - require.resolve( - '../test/interactive_setup_functional/manual_configuration_without_tls.config.ts' - ), - require.resolve('../test/api_integration/config.js'), - require.resolve('../test/interpreter_functional/config.ts'), - require.resolve('../test/examples/config.js'), -]); +require('@kbn/test').runTestsCli(); diff --git a/scripts/functional_tests_server.js b/scripts/functional_tests_server.js index 4995eba4de670..836a1ede126e3 100644 --- a/scripts/functional_tests_server.js +++ b/scripts/functional_tests_server.js @@ -7,4 +7,4 @@ */ require('../src/setup_node_env'); -require('@kbn/test').startServersCli(require.resolve('../test/functional/config.js')); +require('@kbn/test').startServersCli(require.resolve('../test/functional/config.base.js')); diff --git a/test/accessibility/config.ts b/test/accessibility/config.ts index 59194fcb67826..9ed89694db5d8 100644 --- a/test/accessibility/config.ts +++ b/test/accessibility/config.ts @@ -11,7 +11,7 @@ import { services } from './services'; import { pageObjects } from './page_objects'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { ...functionalConfig.getAll(), diff --git a/test/analytics/config.ts b/test/analytics/config.ts index 1ecac5af0d01a..9dee422762e15 100644 --- a/test/analytics/config.ts +++ b/test/analytics/config.ts @@ -19,7 +19,7 @@ import { services } from './services'; */ export default async function ({ readConfigFile }: FtrConfigProviderContext) { const commonConfig = await readConfigFile(require.resolve('../common/config')); - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { testFiles: [require.resolve('./tests')], diff --git a/test/api_integration/apis/saved_objects/lib/saved_objects_test_utils.ts b/test/api_integration/apis/saved_objects/lib/saved_objects_test_utils.ts index d915fc75ed0c3..4e6fc6158e881 100644 --- a/test/api_integration/apis/saved_objects/lib/saved_objects_test_utils.ts +++ b/test/api_integration/apis/saved_objects/lib/saved_objects_test_utils.ts @@ -14,5 +14,6 @@ export async function getKibanaVersion(getService: FtrProviderContext['getServic const kibanaVersion = await kibanaServer.version.get(); expect(typeof kibanaVersion).to.eql('string'); expect(kibanaVersion.length).to.be.greaterThan(0); - return kibanaVersion; + // mimic SavedObjectsService.stripVersionQualifier() + return kibanaVersion.split('-')[0]; } diff --git a/test/api_integration/config.js b/test/api_integration/config.js index 4988094dad7a2..7f3f4b45298d1 100644 --- a/test/api_integration/config.js +++ b/test/api_integration/config.js @@ -10,7 +10,7 @@ import { services } from './services'; export default async function ({ readConfigFile }) { const commonConfig = await readConfigFile(require.resolve('../common/config')); - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { rootTags: ['runOutsideOfCiGroups'], diff --git a/test/examples/bfetch_explorer/index.ts b/test/examples/bfetch_explorer/index.ts index 247cef07a487e..b487704663c62 100644 --- a/test/examples/bfetch_explorer/index.ts +++ b/test/examples/bfetch_explorer/index.ts @@ -14,7 +14,6 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid const PageObjects = getPageObjects(['common', 'header']); describe('bfetch explorer', function () { - this.tags('ciGroup11'); before(async () => { await browser.setWindowSize(1300, 900); await PageObjects.common.navigateToApp('bfetch-explorer', { insertTimestamp: false }); diff --git a/test/examples/config.js b/test/examples/config.js index 6d1f1ec472350..25537a22e19ac 100644 --- a/test/examples/config.js +++ b/test/examples/config.js @@ -12,7 +12,7 @@ import fs from 'fs'; import { KIBANA_ROOT } from '@kbn/test'; export default async function ({ readConfigFile }) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); // Find all folders in /examples and /x-pack/examples since we treat all them as plugin folder const examplesFiles = fs.readdirSync(resolve(KIBANA_ROOT, 'examples')); diff --git a/test/examples/data_view_field_editor_example/index.ts b/test/examples/data_view_field_editor_example/index.ts index 0f8517cb3ed29..fcb8300749f0c 100644 --- a/test/examples/data_view_field_editor_example/index.ts +++ b/test/examples/data_view_field_editor_example/index.ts @@ -20,7 +20,6 @@ export default function ({ const PageObjects = getPageObjects(['common', 'header', 'settings']); describe('data view field editor example', function () { - this.tags('ciGroup11'); before(async () => { await esArchiver.emptyKibanaIndex(); await browser.setWindowSize(1300, 900); diff --git a/test/examples/embeddables/index.ts b/test/examples/embeddables/index.ts index 364c4001383a7..6cd95c699e7b8 100644 --- a/test/examples/embeddables/index.ts +++ b/test/examples/embeddables/index.ts @@ -18,7 +18,6 @@ export default function ({ const PageObjects = getPageObjects(['common', 'header']); describe('embeddable explorer', function () { - this.tags('ciGroup11'); before(async () => { await browser.setWindowSize(1300, 900); await PageObjects.common.navigateToApp('embeddableExplorer'); diff --git a/test/examples/expressions_explorer/index.ts b/test/examples/expressions_explorer/index.ts index 34f3c77cb0d3e..d7a47b63bd012 100644 --- a/test/examples/expressions_explorer/index.ts +++ b/test/examples/expressions_explorer/index.ts @@ -18,7 +18,6 @@ export default function ({ const PageObjects = getPageObjects(['common', 'header']); describe('expressions explorer', function () { - this.tags('ciGroup11'); before(async () => { await browser.setWindowSize(1300, 900); await PageObjects.common.navigateToApp('expressionsExplorer'); diff --git a/test/examples/field_formats/index.ts b/test/examples/field_formats/index.ts index f9692c910fda0..aebd92728b1af 100644 --- a/test/examples/field_formats/index.ts +++ b/test/examples/field_formats/index.ts @@ -16,7 +16,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('Field formats example', function () { before(async () => { - this.tags('ciGroup11'); await PageObjects.common.navigateToApp('fieldFormatsExample'); }); diff --git a/test/examples/hello_world/index.ts b/test/examples/hello_world/index.ts index 1ffb7ff6d69af..604d014401b8f 100644 --- a/test/examples/hello_world/index.ts +++ b/test/examples/hello_world/index.ts @@ -17,7 +17,6 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid describe('Hello world', function () { before(async () => { - this.tags('ciGroup11'); await PageObjects.common.navigateToApp('helloWorld'); }); diff --git a/test/examples/partial_results/index.ts b/test/examples/partial_results/index.ts index 84ccff4cd35b7..6dc76f6a8856c 100644 --- a/test/examples/partial_results/index.ts +++ b/test/examples/partial_results/index.ts @@ -16,7 +16,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('Partial Results Example', function () { before(async () => { - this.tags('ciGroup11'); await PageObjects.common.navigateToApp('partialResultsExample'); const element = await testSubjects.find('example-help'); diff --git a/test/examples/routing/index.ts b/test/examples/routing/index.ts index 949d8cfc7547a..0012283d8535f 100644 --- a/test/examples/routing/index.ts +++ b/test/examples/routing/index.ts @@ -17,7 +17,6 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid describe('routing examples', function () { before(async () => { - this.tags('ciGroup11'); await PageObjects.common.navigateToApp('routingExample'); }); diff --git a/test/examples/state_sync/index.ts b/test/examples/state_sync/index.ts index a33c014f4dd9d..6f70794497bef 100644 --- a/test/examples/state_sync/index.ts +++ b/test/examples/state_sync/index.ts @@ -17,7 +17,6 @@ export default function ({ const browser = getService('browser'); describe('state sync examples', function () { - this.tags('ciGroup11'); before(async () => { await browser.setWindowSize(1300, 900); }); diff --git a/test/examples/ui_actions/index.ts b/test/examples/ui_actions/index.ts index b04d361cc86ec..400af962053ba 100644 --- a/test/examples/ui_actions/index.ts +++ b/test/examples/ui_actions/index.ts @@ -18,7 +18,6 @@ export default function ({ const PageObjects = getPageObjects(['common', 'header']); describe('ui actions explorer', function () { - this.tags('ciGroup11'); before(async () => { await browser.setWindowSize(1300, 900); await PageObjects.common.navigateToApp('uiActionsExplorer'); diff --git a/test/functional/config.coverage.js b/test/functional/apps/bundles/config.ts similarity index 55% rename from test/functional/config.coverage.js rename to test/functional/apps/bundles/config.ts index 8b0a59ac88b1b..e487d31dcb657 100644 --- a/test/functional/config.coverage.js +++ b/test/functional/apps/bundles/config.ts @@ -6,18 +6,13 @@ * Side Public License, v 1. */ -export default async function ({ readConfigFile }) { - const defaultConfig = await readConfigFile(require.resolve('./config')); +import { FtrConfigProviderContext } from '@kbn/test'; - return { - ...defaultConfig.getAll(), - - suiteTags: { - exclude: ['skipCoverage'], - }, +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); - junit: { - reportName: 'Code Coverage for Functional Tests', - }, + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], }; } diff --git a/test/functional/apps/bundles/index.js b/test/functional/apps/bundles/index.js index c3ce4201a470c..105aa155a9f1f 100644 --- a/test/functional/apps/bundles/index.js +++ b/test/functional/apps/bundles/index.js @@ -14,7 +14,7 @@ export default function ({ getService }) { const supertest = getService('supertest'); describe('bundle compression', function () { - this.tags(['ciGroup11', 'skipCoverage']); + this.tags('skipCoverage'); let buildNum; before(async () => { diff --git a/test/functional/apps/console/config.ts b/test/functional/apps/console/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/console/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/console/index.js b/test/functional/apps/console/index.js index c3d0553514cb5..1944e10b5239f 100644 --- a/test/functional/apps/console/index.js +++ b/test/functional/apps/console/index.js @@ -10,8 +10,6 @@ export default function ({ getService, loadTestFile }) { const browser = getService('browser'); describe('console app', function () { - this.tags('ciGroup1'); - before(async function () { await browser.setWindowSize(1300, 1100); }); diff --git a/test/functional/apps/context/config.ts b/test/functional/apps/context/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/context/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/context/index.ts b/test/functional/apps/context/index.ts index 1320a22aad09b..20e1bcc2a3cb4 100644 --- a/test/functional/apps/context/index.ts +++ b/test/functional/apps/context/index.ts @@ -15,8 +15,6 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid const kibanaServer = getService('kibanaServer'); describe('context app', function () { - this.tags('ciGroup1'); - before(async () => { await browser.setWindowSize(1200, 800); await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); diff --git a/test/functional/apps/dashboard/README.md b/test/functional/apps/dashboard/README.md new file mode 100644 index 0000000000000..5e87a8b210bdd --- /dev/null +++ b/test/functional/apps/dashboard/README.md @@ -0,0 +1,7 @@ +# What are all these groups? + +These tests take a while so they have been broken up into groups with their own `config.ts` and `index.ts` file, causing each of these groups to be independent bundles of tests which can be run on some worker in CI without taking an incredible amount of time. + +Want to change the groups to something more logical? Have fun! Just make sure that each group executes on CI in less than 10 minutes or so. We don't currently have any mechanism for validating this right now, you just need to look at the times in the log output on CI, but we'll be working on tooling for making this information more accessible soon. + +- Kibana Operations \ No newline at end of file diff --git a/test/functional/apps/dashboard/group1/config.ts b/test/functional/apps/dashboard/group1/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/dashboard/group1/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/dashboard/create_and_add_embeddables.ts b/test/functional/apps/dashboard/group1/create_and_add_embeddables.ts similarity index 99% rename from test/functional/apps/dashboard/create_and_add_embeddables.ts rename to test/functional/apps/dashboard/group1/create_and_add_embeddables.ts index 30100f0e1aa07..c96e596a88ecf 100644 --- a/test/functional/apps/dashboard/create_and_add_embeddables.ts +++ b/test/functional/apps/dashboard/group1/create_and_add_embeddables.ts @@ -10,7 +10,7 @@ import expect from '@kbn/expect'; import { VisualizeConstants } from '@kbn/visualizations-plugin/common/constants'; import { VISUALIZE_ENABLE_LABS_SETTING } from '@kbn/visualizations-plugin/common/constants'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/dashboard_back_button.ts b/test/functional/apps/dashboard/group1/dashboard_back_button.ts similarity index 96% rename from test/functional/apps/dashboard/dashboard_back_button.ts rename to test/functional/apps/dashboard/group1/dashboard_back_button.ts index d532444befdab..1fd9614d2421a 100644 --- a/test/functional/apps/dashboard/dashboard_back_button.ts +++ b/test/functional/apps/dashboard/group1/dashboard_back_button.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/dashboard/dashboard_error_handling.ts b/test/functional/apps/dashboard/group1/dashboard_error_handling.ts similarity index 97% rename from test/functional/apps/dashboard/dashboard_error_handling.ts rename to test/functional/apps/dashboard/group1/dashboard_error_handling.ts index 58304359458c7..e950b8aef975d 100644 --- a/test/functional/apps/dashboard/dashboard_error_handling.ts +++ b/test/functional/apps/dashboard/group1/dashboard_error_handling.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header', 'common']); diff --git a/test/functional/apps/dashboard/dashboard_options.ts b/test/functional/apps/dashboard/group1/dashboard_options.ts similarity index 96% rename from test/functional/apps/dashboard/dashboard_options.ts rename to test/functional/apps/dashboard/group1/dashboard_options.ts index 282674d0cec98..096f8595072bf 100644 --- a/test/functional/apps/dashboard/dashboard_options.ts +++ b/test/functional/apps/dashboard/group1/dashboard_options.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/dashboard_query_bar.ts b/test/functional/apps/dashboard/group1/dashboard_query_bar.ts similarity index 96% rename from test/functional/apps/dashboard/dashboard_query_bar.ts rename to test/functional/apps/dashboard/group1/dashboard_query_bar.ts index 5092cadaf9d26..290cc62dca58f 100644 --- a/test/functional/apps/dashboard/dashboard_query_bar.ts +++ b/test/functional/apps/dashboard/group1/dashboard_query_bar.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/test/functional/apps/dashboard/dashboard_unsaved_listing.ts b/test/functional/apps/dashboard/group1/dashboard_unsaved_listing.ts similarity index 99% rename from test/functional/apps/dashboard/dashboard_unsaved_listing.ts rename to test/functional/apps/dashboard/group1/dashboard_unsaved_listing.ts index a1db57784b5f8..6b55a44ff9e79 100644 --- a/test/functional/apps/dashboard/dashboard_unsaved_listing.ts +++ b/test/functional/apps/dashboard/group1/dashboard_unsaved_listing.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); diff --git a/test/functional/apps/dashboard/dashboard_unsaved_state.ts b/test/functional/apps/dashboard/group1/dashboard_unsaved_state.ts similarity index 99% rename from test/functional/apps/dashboard/dashboard_unsaved_state.ts rename to test/functional/apps/dashboard/group1/dashboard_unsaved_state.ts index 5afe3b9937433..2447a122a77aa 100644 --- a/test/functional/apps/dashboard/dashboard_unsaved_state.ts +++ b/test/functional/apps/dashboard/group1/dashboard_unsaved_state.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); diff --git a/test/functional/apps/dashboard/data_shared_attributes.ts b/test/functional/apps/dashboard/group1/data_shared_attributes.ts similarity index 98% rename from test/functional/apps/dashboard/data_shared_attributes.ts rename to test/functional/apps/dashboard/group1/data_shared_attributes.ts index a94cf1b6063a9..d4070c700a925 100644 --- a/test/functional/apps/dashboard/data_shared_attributes.ts +++ b/test/functional/apps/dashboard/group1/data_shared_attributes.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/edit_embeddable_redirects.ts b/test/functional/apps/dashboard/group1/edit_embeddable_redirects.ts similarity index 98% rename from test/functional/apps/dashboard/edit_embeddable_redirects.ts rename to test/functional/apps/dashboard/group1/edit_embeddable_redirects.ts index 763488cc21ab1..aca22d84e6843 100644 --- a/test/functional/apps/dashboard/edit_embeddable_redirects.ts +++ b/test/functional/apps/dashboard/group1/edit_embeddable_redirects.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); diff --git a/test/functional/apps/dashboard/edit_visualizations.js b/test/functional/apps/dashboard/group1/edit_visualizations.js similarity index 100% rename from test/functional/apps/dashboard/edit_visualizations.js rename to test/functional/apps/dashboard/group1/edit_visualizations.js diff --git a/test/functional/apps/dashboard/embed_mode.ts b/test/functional/apps/dashboard/group1/embed_mode.ts similarity index 98% rename from test/functional/apps/dashboard/embed_mode.ts rename to test/functional/apps/dashboard/group1/embed_mode.ts index 7e53bff7387ca..25f48236ab7d5 100644 --- a/test/functional/apps/dashboard/embed_mode.ts +++ b/test/functional/apps/dashboard/group1/embed_mode.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); diff --git a/test/functional/apps/dashboard/embeddable_data_grid.ts b/test/functional/apps/dashboard/group1/embeddable_data_grid.ts similarity index 97% rename from test/functional/apps/dashboard/embeddable_data_grid.ts rename to test/functional/apps/dashboard/group1/embeddable_data_grid.ts index 060c467656662..85277e63d6f6c 100644 --- a/test/functional/apps/dashboard/embeddable_data_grid.ts +++ b/test/functional/apps/dashboard/group1/embeddable_data_grid.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardAddPanel = getService('dashboardAddPanel'); diff --git a/test/functional/apps/dashboard/embeddable_rendering.ts b/test/functional/apps/dashboard/group1/embeddable_rendering.ts similarity index 99% rename from test/functional/apps/dashboard/embeddable_rendering.ts rename to test/functional/apps/dashboard/group1/embeddable_rendering.ts index 840826be46532..5274a2c12e878 100644 --- a/test/functional/apps/dashboard/embeddable_rendering.ts +++ b/test/functional/apps/dashboard/group1/embeddable_rendering.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; /** * This tests both that one of each visualization can be added to a dashboard (as opposed to opening an existing diff --git a/test/functional/apps/dashboard/empty_dashboard.ts b/test/functional/apps/dashboard/group1/empty_dashboard.ts similarity index 97% rename from test/functional/apps/dashboard/empty_dashboard.ts rename to test/functional/apps/dashboard/group1/empty_dashboard.ts index a7524eaa94b8a..e559c0ef81f60 100644 --- a/test/functional/apps/dashboard/empty_dashboard.ts +++ b/test/functional/apps/dashboard/group1/empty_dashboard.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); diff --git a/test/functional/apps/dashboard/group1/index.ts b/test/functional/apps/dashboard/group1/index.ts new file mode 100644 index 0000000000000..597102433ef45 --- /dev/null +++ b/test/functional/apps/dashboard/group1/index.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + + async function loadCurrentData() { + await browser.setWindowSize(1300, 900); + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/dashboard/current/data'); + } + + async function unloadCurrentData() { + await esArchiver.unload('test/functional/fixtures/es_archiver/dashboard/current/data'); + } + + describe('dashboard app - group 1', function () { + before(loadCurrentData); + after(unloadCurrentData); + + // This has to be first since the other tests create some embeddables as side affects and our counting assumes + // a fresh index. + loadTestFile(require.resolve('./empty_dashboard')); + loadTestFile(require.resolve('./url_field_formatter')); + loadTestFile(require.resolve('./embeddable_rendering')); + loadTestFile(require.resolve('./embeddable_data_grid')); + loadTestFile(require.resolve('./create_and_add_embeddables')); + loadTestFile(require.resolve('./edit_embeddable_redirects')); + loadTestFile(require.resolve('./dashboard_unsaved_state')); + loadTestFile(require.resolve('./dashboard_unsaved_listing')); + loadTestFile(require.resolve('./edit_visualizations')); + loadTestFile(require.resolve('./dashboard_options')); + loadTestFile(require.resolve('./data_shared_attributes')); + loadTestFile(require.resolve('./share')); + loadTestFile(require.resolve('./embed_mode')); + loadTestFile(require.resolve('./dashboard_back_button')); + loadTestFile(require.resolve('./dashboard_error_handling')); + loadTestFile(require.resolve('./legacy_urls')); + loadTestFile(require.resolve('./saved_search_embeddable')); + + // Note: This one must be last because it unloads some data for one of its tests! + // No, this isn't ideal, but loading/unloading takes so much time and these are all bunched + // to improve efficiency... + loadTestFile(require.resolve('./dashboard_query_bar')); + }); +} diff --git a/test/functional/apps/dashboard/legacy_urls.ts b/test/functional/apps/dashboard/group1/legacy_urls.ts similarity index 98% rename from test/functional/apps/dashboard/legacy_urls.ts rename to test/functional/apps/dashboard/group1/legacy_urls.ts index 1e4138e63d393..e11da2d82fe47 100644 --- a/test/functional/apps/dashboard/legacy_urls.ts +++ b/test/functional/apps/dashboard/group1/legacy_urls.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/test/functional/apps/dashboard/saved_search_embeddable.ts b/test/functional/apps/dashboard/group1/saved_search_embeddable.ts similarity index 98% rename from test/functional/apps/dashboard/saved_search_embeddable.ts rename to test/functional/apps/dashboard/group1/saved_search_embeddable.ts index 02050eec30227..e0ecc40d2486b 100644 --- a/test/functional/apps/dashboard/saved_search_embeddable.ts +++ b/test/functional/apps/dashboard/group1/saved_search_embeddable.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardAddPanel = getService('dashboardAddPanel'); diff --git a/test/functional/apps/dashboard/share.ts b/test/functional/apps/dashboard/group1/share.ts similarity index 95% rename from test/functional/apps/dashboard/share.ts rename to test/functional/apps/dashboard/group1/share.ts index 7fe8048ab7c04..871ab5bed1488 100644 --- a/test/functional/apps/dashboard/share.ts +++ b/test/functional/apps/dashboard/group1/share.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/dashboard/url_field_formatter.ts b/test/functional/apps/dashboard/group1/url_field_formatter.ts similarity index 95% rename from test/functional/apps/dashboard/url_field_formatter.ts rename to test/functional/apps/dashboard/group1/url_field_formatter.ts index 8e9dd7b66e79f..be454549af378 100644 --- a/test/functional/apps/dashboard/url_field_formatter.ts +++ b/test/functional/apps/dashboard/group1/url_field_formatter.ts @@ -7,8 +7,8 @@ */ import expect from '@kbn/expect'; -import { WebElementWrapper } from '../../services/lib/web_element_wrapper'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { WebElementWrapper } from '../../../services/lib/web_element_wrapper'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const { common, dashboard, settings, timePicker, visChart } = getPageObjects([ diff --git a/test/functional/apps/dashboard/group2/config.ts b/test/functional/apps/dashboard/group2/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/dashboard/group2/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/dashboard/dashboard_filter_bar.ts b/test/functional/apps/dashboard/group2/dashboard_filter_bar.ts similarity index 99% rename from test/functional/apps/dashboard/dashboard_filter_bar.ts rename to test/functional/apps/dashboard/group2/dashboard_filter_bar.ts index 3f74c4bc2f0dc..966b453409433 100644 --- a/test/functional/apps/dashboard/dashboard_filter_bar.ts +++ b/test/functional/apps/dashboard/group2/dashboard_filter_bar.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dataGrid = getService('dataGrid'); diff --git a/test/functional/apps/dashboard/dashboard_filtering.ts b/test/functional/apps/dashboard/group2/dashboard_filtering.ts similarity index 99% rename from test/functional/apps/dashboard/dashboard_filtering.ts rename to test/functional/apps/dashboard/group2/dashboard_filtering.ts index 9522c47f907fc..09acbd5965020 100644 --- a/test/functional/apps/dashboard/dashboard_filtering.ts +++ b/test/functional/apps/dashboard/group2/dashboard_filtering.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; /** * Test the querying capabilities of dashboard, and make sure visualizations show the expected results, especially diff --git a/test/functional/apps/dashboard/dashboard_grid.ts b/test/functional/apps/dashboard/group2/dashboard_grid.ts similarity index 96% rename from test/functional/apps/dashboard/dashboard_grid.ts rename to test/functional/apps/dashboard/group2/dashboard_grid.ts index 25e901fd25d8b..90e2187e19eb4 100644 --- a/test/functional/apps/dashboard/dashboard_grid.ts +++ b/test/functional/apps/dashboard/group2/dashboard_grid.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); diff --git a/test/functional/apps/dashboard/dashboard_saved_query.ts b/test/functional/apps/dashboard/group2/dashboard_saved_query.ts similarity index 98% rename from test/functional/apps/dashboard/dashboard_saved_query.ts rename to test/functional/apps/dashboard/group2/dashboard_saved_query.ts index 658afb9c641b2..ac9613f4bf400 100644 --- a/test/functional/apps/dashboard/dashboard_saved_query.ts +++ b/test/functional/apps/dashboard/group2/dashboard_saved_query.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); diff --git a/test/functional/apps/dashboard/dashboard_snapshots.ts b/test/functional/apps/dashboard/group2/dashboard_snapshots.ts similarity index 98% rename from test/functional/apps/dashboard/dashboard_snapshots.ts rename to test/functional/apps/dashboard/group2/dashboard_snapshots.ts index 9cb52c5dd5511..dc1a74ea74b7d 100644 --- a/test/functional/apps/dashboard/dashboard_snapshots.ts +++ b/test/functional/apps/dashboard/group2/dashboard_snapshots.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, diff --git a/test/functional/apps/dashboard/embeddable_library.ts b/test/functional/apps/dashboard/group2/embeddable_library.ts similarity index 97% rename from test/functional/apps/dashboard/embeddable_library.ts rename to test/functional/apps/dashboard/group2/embeddable_library.ts index 2abf75f6385ac..ca52eaecaf46e 100644 --- a/test/functional/apps/dashboard/embeddable_library.ts +++ b/test/functional/apps/dashboard/group2/embeddable_library.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header', 'visualize', 'settings', 'common']); diff --git a/test/functional/apps/dashboard/full_screen_mode.ts b/test/functional/apps/dashboard/group2/full_screen_mode.ts similarity index 98% rename from test/functional/apps/dashboard/full_screen_mode.ts rename to test/functional/apps/dashboard/group2/full_screen_mode.ts index 74fa2168a1461..35d9ed8a2a15c 100644 --- a/test/functional/apps/dashboard/full_screen_mode.ts +++ b/test/functional/apps/dashboard/group2/full_screen_mode.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/group2/index.ts b/test/functional/apps/dashboard/group2/index.ts new file mode 100644 index 0000000000000..004c85f2da760 --- /dev/null +++ b/test/functional/apps/dashboard/group2/index.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + + async function loadCurrentData() { + await browser.setWindowSize(1300, 900); + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/dashboard/current/data'); + } + + async function unloadCurrentData() { + await esArchiver.unload('test/functional/fixtures/es_archiver/dashboard/current/data'); + } + + describe('dashboard app - group 2', function () { + before(loadCurrentData); + after(unloadCurrentData); + + loadTestFile(require.resolve('./full_screen_mode')); + loadTestFile(require.resolve('./dashboard_filter_bar')); + loadTestFile(require.resolve('./dashboard_filtering')); + loadTestFile(require.resolve('./panel_expand_toggle')); + loadTestFile(require.resolve('./dashboard_grid')); + loadTestFile(require.resolve('./view_edit')); + loadTestFile(require.resolve('./dashboard_saved_query')); + // Order of test suites *shouldn't* be important but there's a bug for the view_edit test above + // https://github.com/elastic/kibana/issues/46752 + // The dashboard_snapshot test below requires the timestamped URL which breaks the view_edit test. + // If we don't use the timestamp in the URL, the colors in the charts will be different. + loadTestFile(require.resolve('./dashboard_snapshots')); + loadTestFile(require.resolve('./embeddable_library')); + }); +} diff --git a/test/functional/apps/dashboard/panel_expand_toggle.ts b/test/functional/apps/dashboard/group2/panel_expand_toggle.ts similarity index 97% rename from test/functional/apps/dashboard/panel_expand_toggle.ts rename to test/functional/apps/dashboard/group2/panel_expand_toggle.ts index 272ec3824e233..f33280ba7bb79 100644 --- a/test/functional/apps/dashboard/panel_expand_toggle.ts +++ b/test/functional/apps/dashboard/group2/panel_expand_toggle.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/view_edit.ts b/test/functional/apps/dashboard/group2/view_edit.ts similarity index 99% rename from test/functional/apps/dashboard/view_edit.ts rename to test/functional/apps/dashboard/group2/view_edit.ts index a73924a8ae75f..dfd62eeaa6cb3 100644 --- a/test/functional/apps/dashboard/view_edit.ts +++ b/test/functional/apps/dashboard/group2/view_edit.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const queryBar = getService('queryBar'); diff --git a/test/functional/apps/dashboard/bwc_shared_urls.ts b/test/functional/apps/dashboard/group3/bwc_shared_urls.ts similarity index 99% rename from test/functional/apps/dashboard/bwc_shared_urls.ts rename to test/functional/apps/dashboard/group3/bwc_shared_urls.ts index 569cd8e2a67d5..01b1c8379089e 100644 --- a/test/functional/apps/dashboard/bwc_shared_urls.ts +++ b/test/functional/apps/dashboard/group3/bwc_shared_urls.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header']); diff --git a/test/functional/apps/dashboard/group3/config.ts b/test/functional/apps/dashboard/group3/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/dashboard/group3/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/dashboard/copy_panel_to.ts b/test/functional/apps/dashboard/group3/copy_panel_to.ts similarity index 98% rename from test/functional/apps/dashboard/copy_panel_to.ts rename to test/functional/apps/dashboard/group3/copy_panel_to.ts index 9a61b289ee1f3..1f40f780a5398 100644 --- a/test/functional/apps/dashboard/copy_panel_to.ts +++ b/test/functional/apps/dashboard/group3/copy_panel_to.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardVisualizations = getService('dashboardVisualizations'); diff --git a/test/functional/apps/dashboard/dashboard_state.ts b/test/functional/apps/dashboard/group3/dashboard_state.ts similarity index 98% rename from test/functional/apps/dashboard/dashboard_state.ts rename to test/functional/apps/dashboard/group3/dashboard_state.ts index d931475766776..48fb9233682ad 100644 --- a/test/functional/apps/dashboard/dashboard_state.ts +++ b/test/functional/apps/dashboard/group3/dashboard_state.ts @@ -10,8 +10,8 @@ import expect from '@kbn/expect'; import chroma from 'chroma-js'; import { DEFAULT_PANEL_WIDTH } from '@kbn/dashboard-plugin/public/application/embeddable/dashboard_constants'; -import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME } from '../../../page_objects/dashboard_page'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/test/functional/apps/dashboard/dashboard_time_picker.ts b/test/functional/apps/dashboard/group3/dashboard_time_picker.ts similarity index 97% rename from test/functional/apps/dashboard/dashboard_time_picker.ts rename to test/functional/apps/dashboard/group3/dashboard_time_picker.ts index 6f876185fd8dd..37f6e4f2ef5df 100644 --- a/test/functional/apps/dashboard/dashboard_time_picker.ts +++ b/test/functional/apps/dashboard/group3/dashboard_time_picker.ts @@ -8,8 +8,8 @@ import expect from '@kbn/expect'; -import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { PIE_CHART_VIS_NAME } from '../../../page_objects/dashboard_page'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardExpect = getService('dashboardExpect'); diff --git a/test/functional/apps/dashboard/group3/index.ts b/test/functional/apps/dashboard/group3/index.ts new file mode 100644 index 0000000000000..f3a10500fe4e6 --- /dev/null +++ b/test/functional/apps/dashboard/group3/index.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + + async function loadLogstash() { + await browser.setWindowSize(1200, 900); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + } + + async function unloadLogstash() { + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + } + + describe('dashboard app - group 3', function () { + before(loadLogstash); + after(unloadLogstash); + + loadTestFile(require.resolve('./dashboard_time_picker')); + loadTestFile(require.resolve('./bwc_shared_urls')); + loadTestFile(require.resolve('./panel_replacing')); + loadTestFile(require.resolve('./panel_cloning')); + loadTestFile(require.resolve('./copy_panel_to')); + loadTestFile(require.resolve('./panel_context_menu')); + loadTestFile(require.resolve('./dashboard_state')); + }); +} diff --git a/test/functional/apps/dashboard/panel_cloning.ts b/test/functional/apps/dashboard/group3/panel_cloning.ts similarity index 96% rename from test/functional/apps/dashboard/panel_cloning.ts rename to test/functional/apps/dashboard/group3/panel_cloning.ts index a2cadd89f486a..4de65419d2ecb 100644 --- a/test/functional/apps/dashboard/panel_cloning.ts +++ b/test/functional/apps/dashboard/group3/panel_cloning.ts @@ -7,8 +7,8 @@ */ import expect from '@kbn/expect'; -import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { PIE_CHART_VIS_NAME } from '../../../page_objects/dashboard_page'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardPanelActions = getService('dashboardPanelActions'); diff --git a/test/functional/apps/dashboard/panel_context_menu.ts b/test/functional/apps/dashboard/group3/panel_context_menu.ts similarity index 98% rename from test/functional/apps/dashboard/panel_context_menu.ts rename to test/functional/apps/dashboard/group3/panel_context_menu.ts index 8c82c162f5e86..f78cd27614b3b 100644 --- a/test/functional/apps/dashboard/panel_context_menu.ts +++ b/test/functional/apps/dashboard/group3/panel_context_menu.ts @@ -8,8 +8,8 @@ import expect from '@kbn/expect'; import { VisualizeConstants } from '@kbn/visualizations-plugin/common/constants'; -import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { PIE_CHART_VIS_NAME } from '../../../page_objects/dashboard_page'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); diff --git a/test/functional/apps/dashboard/panel_replacing.ts b/test/functional/apps/dashboard/group3/panel_replacing.ts similarity index 97% rename from test/functional/apps/dashboard/panel_replacing.ts rename to test/functional/apps/dashboard/group3/panel_replacing.ts index b9ba731beee29..e6ff8c4f940bb 100644 --- a/test/functional/apps/dashboard/panel_replacing.ts +++ b/test/functional/apps/dashboard/group3/panel_replacing.ts @@ -11,8 +11,8 @@ import { PIE_CHART_VIS_NAME, AREA_CHART_VIS_NAME, LINE_CHART_VIS_NAME, -} from '../../page_objects/dashboard_page'; -import { FtrProviderContext } from '../../ftr_provider_context'; +} from '../../../page_objects/dashboard_page'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); diff --git a/test/functional/apps/dashboard/group4/config.ts b/test/functional/apps/dashboard/group4/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/dashboard/group4/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/dashboard/dashboard_clone.ts b/test/functional/apps/dashboard/group4/dashboard_clone.ts similarity index 97% rename from test/functional/apps/dashboard/dashboard_clone.ts rename to test/functional/apps/dashboard/group4/dashboard_clone.ts index 5fc0b0c28c914..26738760b28e4 100644 --- a/test/functional/apps/dashboard/dashboard_clone.ts +++ b/test/functional/apps/dashboard/group4/dashboard_clone.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/test/functional/apps/dashboard/dashboard_listing.ts b/test/functional/apps/dashboard/group4/dashboard_listing.ts similarity index 99% rename from test/functional/apps/dashboard/dashboard_listing.ts rename to test/functional/apps/dashboard/group4/dashboard_listing.ts index 9182a0d318228..4a9827ce02f91 100644 --- a/test/functional/apps/dashboard/dashboard_listing.ts +++ b/test/functional/apps/dashboard/group4/dashboard_listing.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header', 'common']); diff --git a/test/functional/apps/dashboard/dashboard_save.ts b/test/functional/apps/dashboard/group4/dashboard_save.ts similarity index 98% rename from test/functional/apps/dashboard/dashboard_save.ts rename to test/functional/apps/dashboard/group4/dashboard_save.ts index 4ab8633a5619b..f20817c65d25d 100644 --- a/test/functional/apps/dashboard/dashboard_save.ts +++ b/test/functional/apps/dashboard/group4/dashboard_save.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['dashboard', 'header', 'visualize']); diff --git a/test/functional/apps/dashboard/dashboard_time.ts b/test/functional/apps/dashboard/group4/dashboard_time.ts similarity index 98% rename from test/functional/apps/dashboard/dashboard_time.ts rename to test/functional/apps/dashboard/group4/dashboard_time.ts index 2c0394474adab..2ff91185be60a 100644 --- a/test/functional/apps/dashboard/dashboard_time.ts +++ b/test/functional/apps/dashboard/group4/dashboard_time.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; const dashboardName = 'Dashboard Test Time'; diff --git a/test/functional/apps/dashboard/group4/index.ts b/test/functional/apps/dashboard/group4/index.ts new file mode 100644 index 0000000000000..8c9a291d2e577 --- /dev/null +++ b/test/functional/apps/dashboard/group4/index.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + + async function loadLogstash() { + await browser.setWindowSize(1200, 900); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + } + + async function unloadLogstash() { + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + } + + describe('dashboard app - group 4', function () { + before(loadLogstash); + after(unloadLogstash); + + loadTestFile(require.resolve('./dashboard_save')); + loadTestFile(require.resolve('./dashboard_time')); + loadTestFile(require.resolve('./dashboard_listing')); + loadTestFile(require.resolve('./dashboard_clone')); + }); +} diff --git a/test/functional/apps/dashboard/group5/config.ts b/test/functional/apps/dashboard/group5/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/dashboard/group5/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/dashboard/group5/index.ts b/test/functional/apps/dashboard/group5/index.ts new file mode 100644 index 0000000000000..14f4a6366477d --- /dev/null +++ b/test/functional/apps/dashboard/group5/index.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + + async function loadLogstash() { + await browser.setWindowSize(1200, 900); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + } + + async function unloadLogstash() { + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + } + + describe('dashboard app - group 5', function () { + // TODO: Remove when vislib is removed + // https://github.com/elastic/kibana/issues/56143 + describe('new charts library', function () { + before(async () => { + await loadLogstash(); + await kibanaServer.uiSettings.update({ + 'visualization:visualize:legacyPieChartsLibrary': false, + }); + await browser.refresh(); + }); + + after(async () => { + await unloadLogstash(); + await kibanaServer.uiSettings.update({ + 'visualization:visualize:legacyPieChartsLibrary': true, + }); + await browser.refresh(); + }); + + loadTestFile(require.resolve('../group3/dashboard_state')); + }); + }); +} diff --git a/test/functional/apps/dashboard/index.ts b/test/functional/apps/dashboard/index.ts deleted file mode 100644 index 4f69504ef7d5c..0000000000000 --- a/test/functional/apps/dashboard/index.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const browser = getService('browser'); - const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); - - async function loadCurrentData() { - await browser.setWindowSize(1300, 900); - await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/dashboard/current/data'); - } - - async function unloadCurrentData() { - await esArchiver.unload('test/functional/fixtures/es_archiver/dashboard/current/data'); - } - - async function loadLogstash() { - await browser.setWindowSize(1200, 900); - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); - } - - async function unloadLogstash() { - await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); - } - - describe('dashboard app', function () { - // This has to be first since the other tests create some embeddables as side affects and our counting assumes - // a fresh index. - describe('using current data', function () { - this.tags('ciGroup2'); - before(loadCurrentData); - after(unloadCurrentData); - - loadTestFile(require.resolve('./empty_dashboard')); - loadTestFile(require.resolve('./url_field_formatter')); - loadTestFile(require.resolve('./embeddable_rendering')); - loadTestFile(require.resolve('./embeddable_data_grid')); - loadTestFile(require.resolve('./create_and_add_embeddables')); - loadTestFile(require.resolve('./edit_embeddable_redirects')); - loadTestFile(require.resolve('./dashboard_unsaved_state')); - loadTestFile(require.resolve('./dashboard_unsaved_listing')); - loadTestFile(require.resolve('./edit_visualizations')); - loadTestFile(require.resolve('./dashboard_options')); - loadTestFile(require.resolve('./data_shared_attributes')); - loadTestFile(require.resolve('./share')); - loadTestFile(require.resolve('./embed_mode')); - loadTestFile(require.resolve('./dashboard_back_button')); - loadTestFile(require.resolve('./dashboard_error_handling')); - loadTestFile(require.resolve('./legacy_urls')); - loadTestFile(require.resolve('./saved_search_embeddable')); - - // Note: This one must be last because it unloads some data for one of its tests! - // No, this isn't ideal, but loading/unloading takes so much time and these are all bunched - // to improve efficiency... - loadTestFile(require.resolve('./dashboard_query_bar')); - }); - - describe('using current data', function () { - this.tags('ciGroup3'); - before(loadCurrentData); - after(unloadCurrentData); - - loadTestFile(require.resolve('./full_screen_mode')); - loadTestFile(require.resolve('./dashboard_filter_bar')); - loadTestFile(require.resolve('./dashboard_filtering')); - loadTestFile(require.resolve('./panel_expand_toggle')); - loadTestFile(require.resolve('./dashboard_grid')); - loadTestFile(require.resolve('./view_edit')); - loadTestFile(require.resolve('./dashboard_saved_query')); - // Order of test suites *shouldn't* be important but there's a bug for the view_edit test above - // https://github.com/elastic/kibana/issues/46752 - // The dashboard_snapshot test below requires the timestamped URL which breaks the view_edit test. - // If we don't use the timestamp in the URL, the colors in the charts will be different. - loadTestFile(require.resolve('./dashboard_snapshots')); - loadTestFile(require.resolve('./embeddable_library')); - }); - - // Each of these tests call initTests themselves, the way it was originally written. The above tests only load - // the data once to save on time. Eventually, all of these tests should just use current data and we can reserve - // legacy data only for specifically testing BWC situations. - describe('using legacy data', function () { - this.tags('ciGroup4'); - before(loadLogstash); - after(unloadLogstash); - - loadTestFile(require.resolve('./dashboard_time_picker')); - loadTestFile(require.resolve('./bwc_shared_urls')); - loadTestFile(require.resolve('./panel_replacing')); - loadTestFile(require.resolve('./panel_cloning')); - loadTestFile(require.resolve('./copy_panel_to')); - loadTestFile(require.resolve('./panel_context_menu')); - loadTestFile(require.resolve('./dashboard_state')); - }); - - describe('using legacy data', function () { - this.tags('ciGroup5'); - before(loadLogstash); - after(unloadLogstash); - - loadTestFile(require.resolve('./dashboard_save')); - loadTestFile(require.resolve('./dashboard_time')); - loadTestFile(require.resolve('./dashboard_listing')); - loadTestFile(require.resolve('./dashboard_clone')); - }); - - // TODO: Remove when vislib is removed - // https://github.com/elastic/kibana/issues/56143 - describe('new charts library', function () { - this.tags('ciGroup5'); - - before(async () => { - await loadLogstash(); - await kibanaServer.uiSettings.update({ - 'visualization:visualize:legacyPieChartsLibrary': false, - }); - await browser.refresh(); - }); - - after(async () => { - await unloadLogstash(); - await kibanaServer.uiSettings.update({ - 'visualization:visualize:legacyPieChartsLibrary': true, - }); - await browser.refresh(); - }); - - loadTestFile(require.resolve('./dashboard_state')); - }); - }); -} diff --git a/test/functional/apps/dashboard_elements/config.ts b/test/functional/apps/dashboard_elements/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/dashboard_elements/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/dashboard_elements/index.ts b/test/functional/apps/dashboard_elements/index.ts index 6bd3e4e04a9c9..10b0c6e5ecff5 100644 --- a/test/functional/apps/dashboard_elements/index.ts +++ b/test/functional/apps/dashboard_elements/index.ts @@ -29,9 +29,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { await esArchiver.unload('test/functional/fixtures/es_archiver/long_window_logstash'); }); - describe('dashboard elements ciGroup10', function () { - this.tags('ciGroup10'); - + describe('dashboard elements', function () { loadTestFile(require.resolve('./input_control_vis')); loadTestFile(require.resolve('./controls')); loadTestFile(require.resolve('./_markdown_vis')); diff --git a/test/functional/apps/discover/config.ts b/test/functional/apps/discover/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/discover/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/discover/index.ts b/test/functional/apps/discover/index.ts index e2895f3ca56b4..20f8f017b084f 100644 --- a/test/functional/apps/discover/index.ts +++ b/test/functional/apps/discover/index.ts @@ -13,8 +13,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const config = getService('config'); describe('discover app', function () { - this.tags('ciGroup6'); - before(async function () { await browser.setWindowSize(1300, 800); }); diff --git a/test/functional/apps/getting_started/config.ts b/test/functional/apps/getting_started/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/getting_started/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/getting_started/index.ts b/test/functional/apps/getting_started/index.ts index c88999e23be3d..a0506ce52e028 100644 --- a/test/functional/apps/getting_started/index.ts +++ b/test/functional/apps/getting_started/index.ts @@ -13,8 +13,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); describe('Getting Started ', function () { - this.tags(['ciGroup5']); - before(async function () { await browser.setWindowSize(1200, 800); }); diff --git a/test/functional/apps/home/config.ts b/test/functional/apps/home/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/home/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/home/index.js b/test/functional/apps/home/index.js index 992c5b1f2f474..ada4aa54073cf 100644 --- a/test/functional/apps/home/index.js +++ b/test/functional/apps/home/index.js @@ -9,9 +9,7 @@ export default function ({ getService, loadTestFile }) { const browser = getService('browser'); - describe('homepage app', function () { - this.tags('ciGroup5'); - + describe('home app', function () { before(function () { return browser.setWindowSize(1200, 800); }); diff --git a/test/functional/apps/management/config.ts b/test/functional/apps/management/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/management/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/management/index.ts b/test/functional/apps/management/index.ts index a4271ae73d9e2..840d04d0d1aed 100644 --- a/test/functional/apps/management/index.ts +++ b/test/functional/apps/management/index.ts @@ -21,33 +21,24 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { await esArchiver.unload('test/functional/fixtures/es_archiver/makelogs'); }); - describe('', function () { - this.tags('ciGroup9'); - - loadTestFile(require.resolve('./_create_index_pattern_wizard')); - loadTestFile(require.resolve('./_index_pattern_create_delete')); - loadTestFile(require.resolve('./_index_pattern_results_sort')); - loadTestFile(require.resolve('./_index_pattern_popularity')); - loadTestFile(require.resolve('./_kibana_settings')); - loadTestFile(require.resolve('./_scripted_fields_preview')); - loadTestFile(require.resolve('./_mgmt_import_saved_objects')); - loadTestFile(require.resolve('./_index_patterns_empty')); - loadTestFile(require.resolve('./_scripted_fields')); - loadTestFile(require.resolve('./_runtime_fields')); - loadTestFile(require.resolve('./_field_formatter')); - loadTestFile(require.resolve('./_legacy_url_redirect')); - loadTestFile(require.resolve('./_exclude_index_pattern')); - }); - - describe('', function () { - this.tags('ciGroup8'); - - loadTestFile(require.resolve('./_index_pattern_filter')); - loadTestFile(require.resolve('./_scripted_fields_filter')); - loadTestFile(require.resolve('./_import_objects')); - loadTestFile(require.resolve('./_test_huge_fields')); - loadTestFile(require.resolve('./_handle_alias')); - loadTestFile(require.resolve('./_handle_version_conflict')); - }); + loadTestFile(require.resolve('./_create_index_pattern_wizard')); + loadTestFile(require.resolve('./_index_pattern_create_delete')); + loadTestFile(require.resolve('./_index_pattern_results_sort')); + loadTestFile(require.resolve('./_index_pattern_popularity')); + loadTestFile(require.resolve('./_kibana_settings')); + loadTestFile(require.resolve('./_scripted_fields_preview')); + loadTestFile(require.resolve('./_mgmt_import_saved_objects')); + loadTestFile(require.resolve('./_index_patterns_empty')); + loadTestFile(require.resolve('./_scripted_fields')); + loadTestFile(require.resolve('./_runtime_fields')); + loadTestFile(require.resolve('./_field_formatter')); + loadTestFile(require.resolve('./_legacy_url_redirect')); + loadTestFile(require.resolve('./_exclude_index_pattern')); + loadTestFile(require.resolve('./_index_pattern_filter')); + loadTestFile(require.resolve('./_scripted_fields_filter')); + loadTestFile(require.resolve('./_import_objects')); + loadTestFile(require.resolve('./_test_huge_fields')); + loadTestFile(require.resolve('./_handle_alias')); + loadTestFile(require.resolve('./_handle_version_conflict')); }); } diff --git a/test/functional/apps/saved_objects_management/config.ts b/test/functional/apps/saved_objects_management/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/saved_objects_management/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/saved_objects_management/index.ts b/test/functional/apps/saved_objects_management/index.ts index 12e0cc8863f12..c70b2c6d25b17 100644 --- a/test/functional/apps/saved_objects_management/index.ts +++ b/test/functional/apps/saved_objects_management/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function savedObjectsManagementApp({ loadTestFile }: FtrProviderContext) { describe('saved objects management', function savedObjectsManagementAppTestSuite() { - this.tags('ciGroup7'); loadTestFile(require.resolve('./inspect_saved_objects')); loadTestFile(require.resolve('./show_relationships')); }); diff --git a/test/functional/apps/status_page/config.ts b/test/functional/apps/status_page/config.ts new file mode 100644 index 0000000000000..e487d31dcb657 --- /dev/null +++ b/test/functional/apps/status_page/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/status_page/index.ts b/test/functional/apps/status_page/index.ts index 509abeb4f0346..971f9c4984c99 100644 --- a/test/functional/apps/status_page/index.ts +++ b/test/functional/apps/status_page/index.ts @@ -14,8 +14,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common']); describe('status page', function () { - this.tags('ciGroup1'); - beforeEach(async () => { await PageObjects.common.navigateToApp('status_page'); }); diff --git a/test/functional/apps/visualize/README.md b/test/functional/apps/visualize/README.md new file mode 100644 index 0000000000000..5e87a8b210bdd --- /dev/null +++ b/test/functional/apps/visualize/README.md @@ -0,0 +1,7 @@ +# What are all these groups? + +These tests take a while so they have been broken up into groups with their own `config.ts` and `index.ts` file, causing each of these groups to be independent bundles of tests which can be run on some worker in CI without taking an incredible amount of time. + +Want to change the groups to something more logical? Have fun! Just make sure that each group executes on CI in less than 10 minutes or so. We don't currently have any mechanism for validating this right now, you just need to look at the times in the log output on CI, but we'll be working on tooling for making this information more accessible soon. + +- Kibana Operations \ No newline at end of file diff --git a/test/functional/apps/visualize/_chart_types.ts b/test/functional/apps/visualize/group1/_chart_types.ts similarity index 96% rename from test/functional/apps/visualize/_chart_types.ts rename to test/functional/apps/visualize/group1/_chart_types.ts index 1afc372f75b0e..4b5922e21a51c 100644 --- a/test/functional/apps/visualize/_chart_types.ts +++ b/test/functional/apps/visualize/group1/_chart_types.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_data_table.ts b/test/functional/apps/visualize/group1/_data_table.ts similarity index 99% rename from test/functional/apps/visualize/_data_table.ts rename to test/functional/apps/visualize/group1/_data_table.ts index e165e40e83dc1..9b95c5b69fd41 100644 --- a/test/functional/apps/visualize/_data_table.ts +++ b/test/functional/apps/visualize/group1/_data_table.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_data_table_nontimeindex.ts b/test/functional/apps/visualize/group1/_data_table_nontimeindex.ts similarity index 98% rename from test/functional/apps/visualize/_data_table_nontimeindex.ts rename to test/functional/apps/visualize/group1/_data_table_nontimeindex.ts index 1549f2aac0735..43407d3a899ea 100644 --- a/test/functional/apps/visualize/_data_table_nontimeindex.ts +++ b/test/functional/apps/visualize/group1/_data_table_nontimeindex.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_data_table_notimeindex_filters.ts b/test/functional/apps/visualize/group1/_data_table_notimeindex_filters.ts similarity index 97% rename from test/functional/apps/visualize/_data_table_notimeindex_filters.ts rename to test/functional/apps/visualize/group1/_data_table_notimeindex_filters.ts index 51ceef947bfac..d62bdd86ecf9b 100644 --- a/test/functional/apps/visualize/_data_table_notimeindex_filters.ts +++ b/test/functional/apps/visualize/group1/_data_table_notimeindex_filters.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_embedding_chart.ts b/test/functional/apps/visualize/group1/_embedding_chart.ts similarity index 98% rename from test/functional/apps/visualize/_embedding_chart.ts rename to test/functional/apps/visualize/group1/_embedding_chart.ts index 9531eafc33bed..a07e3a36e2aea 100644 --- a/test/functional/apps/visualize/_embedding_chart.ts +++ b/test/functional/apps/visualize/group1/_embedding_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const filterBar = getService('filterBar'); diff --git a/test/functional/apps/visualize/group1/config.ts b/test/functional/apps/visualize/group1/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/visualize/group1/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/visualize/group1/index.ts b/test/functional/apps/visualize/group1/index.ts new file mode 100644 index 0000000000000..fa3379b632cc1 --- /dev/null +++ b/test/functional/apps/visualize/group1/index.ts @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + + describe('visualize app - group1', () => { + before(async () => { + log.debug('Starting visualize before method'); + await browser.setWindowSize(1280, 800); + await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); + }); + + loadTestFile(require.resolve('./_embedding_chart')); + loadTestFile(require.resolve('./_data_table')); + loadTestFile(require.resolve('./_data_table_nontimeindex')); + loadTestFile(require.resolve('./_data_table_notimeindex_filters')); + loadTestFile(require.resolve('./_chart_types')); + }); +} diff --git a/test/functional/apps/visualize/_experimental_vis.ts b/test/functional/apps/visualize/group2/_experimental_vis.ts similarity index 97% rename from test/functional/apps/visualize/_experimental_vis.ts rename to test/functional/apps/visualize/group2/_experimental_vis.ts index 8e33285f909be..26460192a6b96 100644 --- a/test/functional/apps/visualize/_experimental_vis.ts +++ b/test/functional/apps/visualize/group2/_experimental_vis.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_gauge_chart.ts b/test/functional/apps/visualize/group2/_gauge_chart.ts similarity index 98% rename from test/functional/apps/visualize/_gauge_chart.ts rename to test/functional/apps/visualize/group2/_gauge_chart.ts index 6dd460d4ac32b..2c20c913b4d16 100644 --- a/test/functional/apps/visualize/_gauge_chart.ts +++ b/test/functional/apps/visualize/group2/_gauge_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_heatmap_chart.ts b/test/functional/apps/visualize/group2/_heatmap_chart.ts similarity index 98% rename from test/functional/apps/visualize/_heatmap_chart.ts rename to test/functional/apps/visualize/group2/_heatmap_chart.ts index 54cec19be97ff..1c82b66273251 100644 --- a/test/functional/apps/visualize/_heatmap_chart.ts +++ b/test/functional/apps/visualize/group2/_heatmap_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_histogram_request_start.ts b/test/functional/apps/visualize/group2/_histogram_request_start.ts similarity index 98% rename from test/functional/apps/visualize/_histogram_request_start.ts rename to test/functional/apps/visualize/group2/_histogram_request_start.ts index 28ebb25744d3f..a12474d9ebc2e 100644 --- a/test/functional/apps/visualize/_histogram_request_start.ts +++ b/test/functional/apps/visualize/group2/_histogram_request_start.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_inspector.ts b/test/functional/apps/visualize/group2/_inspector.ts similarity index 98% rename from test/functional/apps/visualize/_inspector.ts rename to test/functional/apps/visualize/group2/_inspector.ts index f83eae2fc00bc..7b306f7817f5c 100644 --- a/test/functional/apps/visualize/_inspector.ts +++ b/test/functional/apps/visualize/group2/_inspector.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_metric_chart.ts b/test/functional/apps/visualize/group2/_metric_chart.ts similarity index 99% rename from test/functional/apps/visualize/_metric_chart.ts rename to test/functional/apps/visualize/group2/_metric_chart.ts index 7853a3a845bfc..b797ccb630363 100644 --- a/test/functional/apps/visualize/_metric_chart.ts +++ b/test/functional/apps/visualize/group2/_metric_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/group2/config.ts b/test/functional/apps/visualize/group2/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/visualize/group2/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/visualize/group2/index.ts b/test/functional/apps/visualize/group2/index.ts new file mode 100644 index 0000000000000..ea5ad24e2f873 --- /dev/null +++ b/test/functional/apps/visualize/group2/index.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + + describe('visualize app', () => { + before(async () => { + log.debug('Starting visualize before method'); + await browser.setWindowSize(1280, 800); + await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); + }); + + loadTestFile(require.resolve('./_inspector')); + loadTestFile(require.resolve('./_experimental_vis')); + loadTestFile(require.resolve('./_gauge_chart')); + loadTestFile(require.resolve('./_heatmap_chart')); + loadTestFile(require.resolve('./_histogram_request_start')); + loadTestFile(require.resolve('./_metric_chart')); + }); +} diff --git a/test/functional/apps/visualize/_add_to_dashboard.ts b/test/functional/apps/visualize/group3/_add_to_dashboard.ts similarity index 99% rename from test/functional/apps/visualize/_add_to_dashboard.ts rename to test/functional/apps/visualize/group3/_add_to_dashboard.ts index 9e8984675eccd..32d329cd181da 100644 --- a/test/functional/apps/visualize/_add_to_dashboard.ts +++ b/test/functional/apps/visualize/group3/_add_to_dashboard.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const dashboardExpect = getService('dashboardExpect'); diff --git a/test/functional/apps/visualize/_lab_mode.ts b/test/functional/apps/visualize/group3/_lab_mode.ts similarity index 97% rename from test/functional/apps/visualize/_lab_mode.ts rename to test/functional/apps/visualize/group3/_lab_mode.ts index 2af593f2acc4a..ba1b8ae33e2ce 100644 --- a/test/functional/apps/visualize/_lab_mode.ts +++ b/test/functional/apps/visualize/group3/_lab_mode.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { VISUALIZE_ENABLE_LABS_SETTING } from '@kbn/visualizations-plugin/common/constants'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_linked_saved_searches.ts b/test/functional/apps/visualize/group3/_linked_saved_searches.ts similarity index 98% rename from test/functional/apps/visualize/_linked_saved_searches.ts rename to test/functional/apps/visualize/group3/_linked_saved_searches.ts index 6fa8acac8e781..e64a3f18bde95 100644 --- a/test/functional/apps/visualize/_linked_saved_searches.ts +++ b/test/functional/apps/visualize/group3/_linked_saved_searches.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); diff --git a/test/functional/apps/visualize/_pie_chart.ts b/test/functional/apps/visualize/group3/_pie_chart.ts similarity index 95% rename from test/functional/apps/visualize/_pie_chart.ts rename to test/functional/apps/visualize/group3/_pie_chart.ts index 48d49d3007b68..23b008c690cba 100644 --- a/test/functional/apps/visualize/_pie_chart.ts +++ b/test/functional/apps/visualize/group3/_pie_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); @@ -401,7 +401,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ['360,000', '47', 'US', '4'], ['360,000', '47', 'BD', '3'], ['360,000', '47', 'BR', '2'], - ]; + ].map((row) => + // the count of records is not shown for every split level in the new charting library + isNewChartsLibraryEnabled ? [row[0], ...row.slice(2)] : row + ); await inspector.open(); await inspector.setTablePageSize(50); @@ -447,6 +450,11 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); it('should still showing pie chart when a subseries have zero data', async function () { + if (isNewChartsLibraryEnabled) { + // TODO: it seems that adding a filter agg which has no results to a pie chart breaks it and instead it shows "no data" + return; + } + await PageObjects.visualize.navigateToNewAggBasedVisualization(); log.debug('clickPieChart'); await PageObjects.visualize.clickPieChart(); @@ -518,7 +526,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ['osx', '1,322', 'US', '130'], ['osx', '1,322', 'ID', '56'], ['osx', '1,322', 'BR', '30'], - ]; + ].map((row) => + // the count of records is not shown for every split level in the new charting library + isNewChartsLibraryEnabled ? [row[0], ...row.slice(2)] : row + ); await inspector.open(); await inspector.setTablePageSize(50); await inspector.expectTableData(expectedTableData); @@ -532,7 +543,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ['win xp', '526', 'CN', '526'], ['ios', '478', 'CN', '478'], ['osx', '228', 'CN', '228'], - ]; + ].map((row) => + // the count of records is not shown for every split level in the new charting library + isNewChartsLibraryEnabled ? [row[0], ...row.slice(2)] : row + ); await PageObjects.visChart.filterLegend('CN'); await PageObjects.header.waitUntilLoadingHasFinished(); await inspector.open(); diff --git a/test/functional/apps/visualize/_shared_item.ts b/test/functional/apps/visualize/group3/_shared_item.ts similarity index 95% rename from test/functional/apps/visualize/_shared_item.ts rename to test/functional/apps/visualize/group3/_shared_item.ts index 3f9016ca2ff82..0a84ae1962c63 100644 --- a/test/functional/apps/visualize/_shared_item.ts +++ b/test/functional/apps/visualize/group3/_shared_item.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_visualize_listing.ts b/test/functional/apps/visualize/group3/_visualize_listing.ts similarity index 98% rename from test/functional/apps/visualize/_visualize_listing.ts rename to test/functional/apps/visualize/group3/_visualize_listing.ts index 30b19b52af258..ad370939f2260 100644 --- a/test/functional/apps/visualize/_visualize_listing.ts +++ b/test/functional/apps/visualize/group3/_visualize_listing.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'visEditor']); diff --git a/test/functional/apps/visualize/group3/config.ts b/test/functional/apps/visualize/group3/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/visualize/group3/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/visualize/group3/index.ts b/test/functional/apps/visualize/group3/index.ts new file mode 100644 index 0000000000000..93eff60575cb3 --- /dev/null +++ b/test/functional/apps/visualize/group3/index.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + + describe('visualize app', () => { + before(async () => { + log.debug('Starting visualize before method'); + await browser.setWindowSize(1280, 800); + await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); + }); + + loadTestFile(require.resolve('./_pie_chart')); + loadTestFile(require.resolve('./_shared_item')); + loadTestFile(require.resolve('./_lab_mode')); + loadTestFile(require.resolve('./_linked_saved_searches')); + loadTestFile(require.resolve('./_visualize_listing')); + loadTestFile(require.resolve('./_add_to_dashboard.ts')); + }); +} diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/group4/_tsvb_chart.ts similarity index 99% rename from test/functional/apps/visualize/_tsvb_chart.ts rename to test/functional/apps/visualize/group4/_tsvb_chart.ts index d462a89108c09..013c0473a59b9 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/group4/_tsvb_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); diff --git a/test/functional/apps/visualize/group4/config.ts b/test/functional/apps/visualize/group4/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/visualize/group4/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/visualize/group4/index.ts b/test/functional/apps/visualize/group4/index.ts new file mode 100644 index 0000000000000..3476489706415 --- /dev/null +++ b/test/functional/apps/visualize/group4/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + + describe('visualize app', () => { + before(async () => { + log.debug('Starting visualize before method'); + await browser.setWindowSize(1280, 800); + await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); + }); + + loadTestFile(require.resolve('./_tsvb_chart')); + }); +} diff --git a/test/functional/apps/visualize/_tsvb_time_series.ts b/test/functional/apps/visualize/group5/_tsvb_time_series.ts similarity index 99% rename from test/functional/apps/visualize/_tsvb_time_series.ts rename to test/functional/apps/visualize/group5/_tsvb_time_series.ts index 3f6661aaecf00..409b2b3610f5c 100644 --- a/test/functional/apps/visualize/_tsvb_time_series.ts +++ b/test/functional/apps/visualize/group5/_tsvb_time_series.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const { visualize, visualBuilder, timeToVisualize, dashboard, common } = getPageObjects([ diff --git a/test/functional/apps/visualize/group5/config.ts b/test/functional/apps/visualize/group5/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/visualize/group5/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/visualize/group5/index.ts b/test/functional/apps/visualize/group5/index.ts new file mode 100644 index 0000000000000..eafa39962ff56 --- /dev/null +++ b/test/functional/apps/visualize/group5/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + + describe('visualize app', () => { + before(async () => { + log.debug('Starting visualize before method'); + await browser.setWindowSize(1280, 800); + await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); + }); + + loadTestFile(require.resolve('./_tsvb_time_series')); + }); +} diff --git a/test/functional/apps/visualize/_tag_cloud.ts b/test/functional/apps/visualize/group6/_tag_cloud.ts similarity index 99% rename from test/functional/apps/visualize/_tag_cloud.ts rename to test/functional/apps/visualize/group6/_tag_cloud.ts index 9380f40e0d36c..93a7fb22a2ca8 100644 --- a/test/functional/apps/visualize/_tag_cloud.ts +++ b/test/functional/apps/visualize/group6/_tag_cloud.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); diff --git a/test/functional/apps/visualize/_tsvb_markdown.ts b/test/functional/apps/visualize/group6/_tsvb_markdown.ts similarity index 99% rename from test/functional/apps/visualize/_tsvb_markdown.ts rename to test/functional/apps/visualize/group6/_tsvb_markdown.ts index 98ed05d854f0c..80756b1eacbfb 100644 --- a/test/functional/apps/visualize/_tsvb_markdown.ts +++ b/test/functional/apps/visualize/group6/_tsvb_markdown.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const { visualBuilder, timePicker, visualize, visChart } = getPageObjects([ diff --git a/test/functional/apps/visualize/_tsvb_table.ts b/test/functional/apps/visualize/group6/_tsvb_table.ts similarity index 99% rename from test/functional/apps/visualize/_tsvb_table.ts rename to test/functional/apps/visualize/group6/_tsvb_table.ts index ed668e4bca8e5..e7e24885cb406 100644 --- a/test/functional/apps/visualize/_tsvb_table.ts +++ b/test/functional/apps/visualize/group6/_tsvb_table.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const { visualBuilder, visualize, visChart, settings } = getPageObjects([ diff --git a/test/functional/apps/visualize/_vega_chart.ts b/test/functional/apps/visualize/group6/_vega_chart.ts similarity index 99% rename from test/functional/apps/visualize/_vega_chart.ts rename to test/functional/apps/visualize/group6/_vega_chart.ts index 6640b37b4a28a..78a370523071b 100644 --- a/test/functional/apps/visualize/_vega_chart.ts +++ b/test/functional/apps/visualize/group6/_vega_chart.ts @@ -9,7 +9,7 @@ import { unzip } from 'lodash'; import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; const getTestSpec = (expression: string) => ` { diff --git a/test/functional/apps/visualize/group6/config.ts b/test/functional/apps/visualize/group6/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/visualize/group6/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/visualize/group6/index.ts b/test/functional/apps/visualize/group6/index.ts new file mode 100644 index 0000000000000..05fe3b232d370 --- /dev/null +++ b/test/functional/apps/visualize/group6/index.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + + describe('visualize app', () => { + before(async () => { + log.debug('Starting visualize before method'); + await browser.setWindowSize(1280, 800); + await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); + }); + + loadTestFile(require.resolve('./_tag_cloud')); + loadTestFile(require.resolve('./_tsvb_markdown')); + loadTestFile(require.resolve('./_tsvb_table')); + loadTestFile(require.resolve('./_vega_chart')); + }); +} diff --git a/test/functional/apps/visualize/index.ts b/test/functional/apps/visualize/index.ts deleted file mode 100644 index d68fb4b253123..0000000000000 --- a/test/functional/apps/visualize/index.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, loadTestFile }: FtrProviderContext) { - const browser = getService('browser'); - const log = getService('log'); - const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); - - describe('visualize app', () => { - before(async () => { - log.debug('Starting visualize before method'); - await browser.setWindowSize(1280, 800); - await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); - - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); - await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); - }); - - // TODO: Remove when vislib is removed - describe('new charts library visualize ciGroup7', function () { - this.tags('ciGroup7'); - - before(async () => { - await kibanaServer.uiSettings.update({ - 'visualization:visualize:legacyPieChartsLibrary': false, - 'visualization:visualize:legacyHeatmapChartsLibrary': false, - }); - await browser.refresh(); - }); - - after(async () => { - await kibanaServer.uiSettings.update({ - 'visualization:visualize:legacyPieChartsLibrary': true, - 'visualization:visualize:legacyHeatmapChartsLibrary': true, - }); - await browser.refresh(); - }); - - // Test replaced vislib chart types - loadTestFile(require.resolve('./_area_chart')); - loadTestFile(require.resolve('./_line_chart_split_series')); - loadTestFile(require.resolve('./_line_chart_split_chart')); - loadTestFile(require.resolve('./_point_series_options')); - loadTestFile(require.resolve('./_vertical_bar_chart')); - loadTestFile(require.resolve('./_vertical_bar_chart_nontimeindex')); - loadTestFile(require.resolve('./_pie_chart')); - loadTestFile(require.resolve('./_timelion')); - loadTestFile(require.resolve('./_heatmap_chart')); - }); - - describe('visualize ciGroup9', function () { - this.tags('ciGroup9'); - - loadTestFile(require.resolve('./_embedding_chart')); - loadTestFile(require.resolve('./_data_table')); - loadTestFile(require.resolve('./_data_table_nontimeindex')); - loadTestFile(require.resolve('./_data_table_notimeindex_filters')); - loadTestFile(require.resolve('./_chart_types')); - }); - - describe('visualize ciGroup10', function () { - this.tags('ciGroup10'); - - loadTestFile(require.resolve('./_inspector')); - loadTestFile(require.resolve('./_experimental_vis')); - loadTestFile(require.resolve('./_gauge_chart')); - loadTestFile(require.resolve('./_heatmap_chart')); - loadTestFile(require.resolve('./_histogram_request_start')); - loadTestFile(require.resolve('./_metric_chart')); - }); - - describe('visualize ciGroup1', function () { - this.tags('ciGroup1'); - - loadTestFile(require.resolve('./_pie_chart')); - loadTestFile(require.resolve('./_shared_item')); - loadTestFile(require.resolve('./_lab_mode')); - loadTestFile(require.resolve('./_linked_saved_searches')); - loadTestFile(require.resolve('./_visualize_listing')); - loadTestFile(require.resolve('./_add_to_dashboard.ts')); - }); - - describe('visualize ciGroup8', function () { - this.tags('ciGroup8'); - - loadTestFile(require.resolve('./_tsvb_chart')); - }); - - describe('visualize ciGroup11', function () { - this.tags('ciGroup11'); - - loadTestFile(require.resolve('./_tsvb_time_series')); - }); - - describe('visualize ciGroup12', function () { - this.tags('ciGroup12'); - - loadTestFile(require.resolve('./_tag_cloud')); - loadTestFile(require.resolve('./_tsvb_markdown')); - loadTestFile(require.resolve('./_tsvb_table')); - loadTestFile(require.resolve('./_vega_chart')); - }); - }); -} diff --git a/test/functional/apps/visualize/_area_chart.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_area_chart.ts similarity index 99% rename from test/functional/apps/visualize/_area_chart.ts rename to test/functional/apps/visualize/replaced_vislib_chart_types/_area_chart.ts index 76bb1d2f58d05..5fbb264910dca 100644 --- a/test/functional/apps/visualize/_area_chart.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_area_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_line_chart_split_chart.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts similarity index 99% rename from test/functional/apps/visualize/_line_chart_split_chart.ts rename to test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts index 0e44c30499ed3..77ddc3bbac1a4 100644 --- a/test/functional/apps/visualize/_line_chart_split_chart.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_line_chart_split_series.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts similarity index 99% rename from test/functional/apps/visualize/_line_chart_split_series.ts rename to test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts index d10b4ebd9b312..a46c46fda48ad 100644 --- a/test/functional/apps/visualize/_line_chart_split_series.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_line_chart_split_series.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_point_series_options.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_point_series_options.ts similarity index 99% rename from test/functional/apps/visualize/_point_series_options.ts rename to test/functional/apps/visualize/replaced_vislib_chart_types/_point_series_options.ts index a2d2831c87933..1a11d19064ce7 100644 --- a/test/functional/apps/visualize/_point_series_options.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_point_series_options.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_timelion.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_timelion.ts similarity index 99% rename from test/functional/apps/visualize/_timelion.ts rename to test/functional/apps/visualize/replaced_vislib_chart_types/_timelion.ts index e10ba03a0e19f..dc80083a67697 100644 --- a/test/functional/apps/visualize/_timelion.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_timelion.ts @@ -7,7 +7,7 @@ */ import expect from '@kbn/expect'; -import type { FtrProviderContext } from '../../ftr_provider_context'; +import type { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const { timePicker, visChart, visEditor, visualize, timelion, common } = getPageObjects([ diff --git a/test/functional/apps/visualize/_vertical_bar_chart.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart.ts similarity index 99% rename from test/functional/apps/visualize/_vertical_bar_chart.ts rename to test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart.ts index 7c4f989724ad9..b8d5cd64bbc1f 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/_vertical_bar_chart_nontimeindex.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart_nontimeindex.ts similarity index 99% rename from test/functional/apps/visualize/_vertical_bar_chart_nontimeindex.ts rename to test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart_nontimeindex.ts index eadc7c58af5a5..4f00bac7792c4 100644 --- a/test/functional/apps/visualize/_vertical_bar_chart_nontimeindex.ts +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/_vertical_bar_chart_nontimeindex.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/config.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/config.ts new file mode 100644 index 0000000000000..a70a190ca63f8 --- /dev/null +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/visualize/replaced_vislib_chart_types/index.ts b/test/functional/apps/visualize/replaced_vislib_chart_types/index.ts new file mode 100644 index 0000000000000..5794edef68555 --- /dev/null +++ b/test/functional/apps/visualize/replaced_vislib_chart_types/index.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + + // TODO: Remove when vislib is removed + describe('visualize app - new charts library visualize', () => { + before(async () => { + log.debug('Starting visualize before method'); + await browser.setWindowSize(1280, 800); + await esArchiver.load('test/functional/fixtures/es_archiver/empty_kibana'); + + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/long_window_logstash'); + }); + + before(async () => { + await kibanaServer.uiSettings.update({ + 'visualization:visualize:legacyPieChartsLibrary': false, + 'visualization:visualize:legacyHeatmapChartsLibrary': false, + }); + await browser.refresh(); + }); + + after(async () => { + await kibanaServer.uiSettings.update({ + 'visualization:visualize:legacyPieChartsLibrary': true, + 'visualization:visualize:legacyHeatmapChartsLibrary': true, + }); + await browser.refresh(); + }); + + // Test replaced vislib chart types + loadTestFile(require.resolve('./_area_chart')); + loadTestFile(require.resolve('./_line_chart_split_series')); + loadTestFile(require.resolve('./_line_chart_split_chart')); + loadTestFile(require.resolve('./_point_series_options')); + loadTestFile(require.resolve('./_vertical_bar_chart')); + loadTestFile(require.resolve('./_vertical_bar_chart_nontimeindex')); + loadTestFile(require.resolve('./_timelion')); + loadTestFile(require.resolve('../group3/_pie_chart')); + loadTestFile(require.resolve('../group2/_heatmap_chart')); + }); +} diff --git a/test/functional/config.js b/test/functional/config.base.js similarity index 95% rename from test/functional/config.js rename to test/functional/config.base.js index 9221bef808e01..40b50da505951 100644 --- a/test/functional/config.js +++ b/test/functional/config.base.js @@ -13,20 +13,6 @@ export default async function ({ readConfigFile }) { const commonConfig = await readConfigFile(require.resolve('../common/config')); return { - testFiles: [ - require.resolve('./apps/status_page'), - require.resolve('./apps/bundles'), - require.resolve('./apps/console'), - require.resolve('./apps/context'), - require.resolve('./apps/dashboard'), - require.resolve('./apps/dashboard_elements'), - require.resolve('./apps/discover'), - require.resolve('./apps/getting_started'), - require.resolve('./apps/home'), - require.resolve('./apps/management'), - require.resolve('./apps/saved_objects_management'), - require.resolve('./apps/visualize'), - ], pageObjects, services, diff --git a/test/functional/config.ccs.ts b/test/functional/config.ccs.ts index 8137635b474da..e5a3736d6fbc3 100644 --- a/test/functional/config.ccs.ts +++ b/test/functional/config.ccs.ts @@ -12,15 +12,15 @@ import { RemoteEsProvider } from './services/remote_es/remote_es'; // eslint-disable-next-line import/no-default-export export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('./config')); + const baseConfig = await readConfigFile(require.resolve('./config.base.js')); return { - ...functionalConfig.getAll(), + ...baseConfig.getAll(), testFiles: [require.resolve('./apps/discover')], services: { - ...functionalConfig.get('services'), + ...baseConfig.get('services'), remoteEs: RemoteEsProvider, remoteEsArchiver: RemoteEsArchiverProvider, }, @@ -30,7 +30,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { }, security: { - ...functionalConfig.get('security'), + ...baseConfig.get('security'), remoteEsRoles: { ccs_remote_search: { indices: [ @@ -41,17 +41,15 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ], }, }, - defaultRoles: [...(functionalConfig.get('security.defaultRoles') ?? []), 'ccs_remote_search'], + defaultRoles: [...(baseConfig.get('security.defaultRoles') ?? []), 'ccs_remote_search'], }, esTestCluster: { - ...functionalConfig.get('esTestCluster'), + ...baseConfig.get('esTestCluster'), ccs: { remoteClusterUrl: process.env.REMOTE_CLUSTER_URL ?? - `http://elastic:changeme@localhost:${ - functionalConfig.get('servers.elasticsearch.port') + 1 - }`, + `http://elastic:changeme@localhost:${baseConfig.get('servers.elasticsearch.port') + 1}`, }, }, }; diff --git a/test/functional/config.edge.js b/test/functional/config.edge.js index 89dc4c39bca4c..86e213fd31e9f 100644 --- a/test/functional/config.edge.js +++ b/test/functional/config.edge.js @@ -7,10 +7,10 @@ */ export default async function ({ readConfigFile }) { - const defaultConfig = await readConfigFile(require.resolve('./config')); + const firefoxConfig = await readConfigFile(require.resolve('./config.firefox.js')); return { - ...defaultConfig.getAll(), + ...firefoxConfig.getAll(), browser: { type: 'msedge', diff --git a/test/functional/config.firefox.js b/test/functional/config.firefox.js index 145add328c9ca..79a757b1f1116 100644 --- a/test/functional/config.firefox.js +++ b/test/functional/config.firefox.js @@ -7,16 +7,26 @@ */ export default async function ({ readConfigFile }) { - const defaultConfig = await readConfigFile(require.resolve('./config')); + const baseConfig = await readConfigFile(require.resolve('./config.base.js')); return { - ...defaultConfig.getAll(), + ...baseConfig.getAll(), + + testFiles: [ + require.resolve('./apps/console'), + require.resolve('./apps/dashboard/group4/dashboard_save'), + require.resolve('./apps/dashboard_elements'), + require.resolve('./apps/discover'), + require.resolve('./apps/home'), + require.resolve('./apps/visualize/group5'), + ], browser: { type: 'firefox', }, suiteTags: { + include: ['includeFirefox'], exclude: ['skipFirefox'], }, diff --git a/test/functional/services/common/screenshots.ts b/test/functional/services/common/screenshots.ts index d5f901300941f..5fca603407760 100644 --- a/test/functional/services/common/screenshots.ts +++ b/test/functional/services/common/screenshots.ts @@ -22,7 +22,6 @@ const writeFileAsync = promisify(writeFile); export class ScreenshotsService extends FtrService { private readonly log = this.ctx.getService('log'); private readonly config = this.ctx.getService('config'); - private readonly testMetadata = this.ctx.getService('testMetadata'); private readonly browser = this.ctx.getService('browser'); private readonly SESSION_DIRECTORY = resolve(this.config.get('screenshots.directory'), 'session'); @@ -54,13 +53,7 @@ export class ScreenshotsService extends FtrService { const baselinePath = resolve(this.BASELINE_DIRECTORY, `${name}.png`); const failurePath = resolve(this.FAILURE_DIRECTORY, `${name}.png`); - await this.capture({ - path: sessionPath, - name, - el, - baselinePath, - failurePath, - }); + await this.capture(sessionPath, el); if (updateBaselines) { this.log.debug('Updating baseline snapshot'); @@ -82,42 +75,20 @@ export class ScreenshotsService extends FtrService { async take(name: string, el?: WebElementWrapper, subDirectories: string[] = []) { const path = resolve(this.SESSION_DIRECTORY, ...subDirectories, `${name}.png`); - await this.capture({ path, name, el }); + await this.capture(path, el); } async takeForFailure(name: string, el?: WebElementWrapper) { const path = resolve(this.FAILURE_DIRECTORY, `${name}.png`); - await this.capture({ - path, - name: `failure[${name}]`, - el, - }); + await this.capture(path, el); } - private async capture({ - path, - el, - name, - baselinePath, - failurePath, - }: { - path: string; - name: string; - el?: WebElementWrapper; - baselinePath?: string; - failurePath?: string; - }) { + private async capture(path: string, el?: WebElementWrapper) { try { this.log.info(`Taking screenshot "${path}"`); const screenshot = await (el ? el.takeScreenshot() : this.browser.takeScreenshot()); await mkdirAsync(dirname(path), { recursive: true }); await writeFileAsync(path, screenshot, 'base64'); - this.testMetadata.addScreenshot({ - name, - base64Png: Buffer.isBuffer(screenshot) ? screenshot.toString('base64') : screenshot, - baselinePath, - failurePath, - }); } catch (err) { this.log.error('SCREENSHOT FAILED'); this.log.error(err); diff --git a/test/interactive_setup_api_integration/tests/enrollment_flow.ts b/test/interactive_setup_api_integration/tests/enrollment_flow.ts index f35509f49480a..a9cec78e391c1 100644 --- a/test/interactive_setup_api_integration/tests/enrollment_flow.ts +++ b/test/interactive_setup_api_integration/tests/enrollment_flow.ts @@ -20,7 +20,7 @@ export default function (context: FtrProviderContext) { const config = context.getService('config'); describe('Interactive setup APIs - Enrollment flow', function () { - this.tags(['skipCloud', 'ciGroup11']); + this.tags('skipCloud'); let kibanaVerificationCode: string; let elasticsearchCaFingerprint: string; diff --git a/test/interactive_setup_api_integration/tests/manual_configuration_flow.ts b/test/interactive_setup_api_integration/tests/manual_configuration_flow.ts index 94a06363367ad..156834d503e8f 100644 --- a/test/interactive_setup_api_integration/tests/manual_configuration_flow.ts +++ b/test/interactive_setup_api_integration/tests/manual_configuration_flow.ts @@ -19,7 +19,7 @@ export default function (context: FtrProviderContext) { const config = context.getService('config'); describe('Interactive setup APIs - Manual configuration flow', function () { - this.tags(['skipCloud', 'ciGroup11']); + this.tags('skipCloud'); let kibanaVerificationCode: string; let elasticsearchCaCertificate: string; diff --git a/test/interactive_setup_api_integration/tests/manual_configuration_flow_without_tls.ts b/test/interactive_setup_api_integration/tests/manual_configuration_flow_without_tls.ts index a3964c5fd5aa6..6035b6571a1fc 100644 --- a/test/interactive_setup_api_integration/tests/manual_configuration_flow_without_tls.ts +++ b/test/interactive_setup_api_integration/tests/manual_configuration_flow_without_tls.ts @@ -18,7 +18,7 @@ export default function (context: FtrProviderContext) { const config = context.getService('config'); describe('Interactive setup APIs - Manual configuration flow without TLS', function () { - this.tags(['skipCloud', 'ciGroup11']); + this.tags('skipCloud'); let kibanaVerificationCode: string; before(async () => { diff --git a/test/interactive_setup_functional/manual_configuration_without_security.config.ts b/test/interactive_setup_functional/manual_configuration_without_security.config.ts index 953b33d4e2077..48c917e853b5a 100644 --- a/test/interactive_setup_functional/manual_configuration_without_security.config.ts +++ b/test/interactive_setup_functional/manual_configuration_without_security.config.ts @@ -13,7 +13,7 @@ import type { FtrConfigProviderContext } from '@kbn/test'; import { getDataPath } from '@kbn/utils'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); const testEndpointsPlugin = resolve( __dirname, diff --git a/test/interactive_setup_functional/tests/enrollment_token.ts b/test/interactive_setup_functional/tests/enrollment_token.ts index 20d9da6539692..5af4ed0fc3f2e 100644 --- a/test/interactive_setup_functional/tests/enrollment_token.ts +++ b/test/interactive_setup_functional/tests/enrollment_token.ts @@ -22,7 +22,7 @@ export default function ({ getService }: FtrProviderContext) { const log = getService('log'); describe('Interactive Setup Functional Tests (Enrollment token)', function () { - this.tags(['skipCloud', 'ciGroup11']); + this.tags('skipCloud'); const elasticsearchConfig = config.get('servers.elasticsearch'); let verificationCode: string; diff --git a/test/interactive_setup_functional/tests/manual_configuration.ts b/test/interactive_setup_functional/tests/manual_configuration.ts index 68c5068acd267..3f41cf0659567 100644 --- a/test/interactive_setup_functional/tests/manual_configuration.ts +++ b/test/interactive_setup_functional/tests/manual_configuration.ts @@ -19,7 +19,7 @@ export default function ({ getService }: FtrProviderContext) { const log = getService('log'); describe('Interactive Setup Functional Tests (Manual configuration)', function () { - this.tags(['skipCloud', 'ciGroup11']); + this.tags('skipCloud'); let verificationCode: string; before(async function () { diff --git a/test/interactive_setup_functional/tests/manual_configuration_without_security.ts b/test/interactive_setup_functional/tests/manual_configuration_without_security.ts index 20f7bac890da4..f8925e4add106 100644 --- a/test/interactive_setup_functional/tests/manual_configuration_without_security.ts +++ b/test/interactive_setup_functional/tests/manual_configuration_without_security.ts @@ -19,7 +19,7 @@ export default function ({ getService, getPageObject }: FtrProviderContext) { const log = getService('log'); describe('Interactive Setup Functional Tests (Manual configuration without Security)', function () { - this.tags(['skipCloud', 'ciGroup11']); + this.tags('skipCloud'); let verificationCode: string; before(async function () { diff --git a/test/interactive_setup_functional/tests/manual_configuration_without_tls.ts b/test/interactive_setup_functional/tests/manual_configuration_without_tls.ts index 04e31b4ae8454..23595150d55a1 100644 --- a/test/interactive_setup_functional/tests/manual_configuration_without_tls.ts +++ b/test/interactive_setup_functional/tests/manual_configuration_without_tls.ts @@ -19,7 +19,7 @@ export default function ({ getService }: FtrProviderContext) { const log = getService('log'); describe('Interactive Setup Functional Tests (Manual configuration without TLS)', function () { - this.tags(['skipCloud', 'ciGroup11']); + this.tags('skipCloud'); let verificationCode: string; before(async function () { diff --git a/test/interpreter_functional/config.ts b/test/interpreter_functional/config.ts index 3f9c846a51429..0f81089433b33 100644 --- a/test/interpreter_functional/config.ts +++ b/test/interpreter_functional/config.ts @@ -11,7 +11,7 @@ import fs from 'fs'; import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); // Find all folders in ./plugins since we treat all them as plugin folder const allFiles = fs.readdirSync(path.resolve(__dirname, 'plugins')); diff --git a/test/new_visualize_flow/config.ts b/test/new_visualize_flow/config.ts index a6bd97464e2d0..381d316fa1ad0 100644 --- a/test/new_visualize_flow/config.ts +++ b/test/new_visualize_flow/config.ts @@ -9,7 +9,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const commonConfig = await readConfigFile(require.resolve('../functional/config.js')); + const commonConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { testFiles: [require.resolve('./index.ts')], diff --git a/test/new_visualize_flow/index.ts b/test/new_visualize_flow/index.ts index 7cb55069d7d9b..35c90edf9447d 100644 --- a/test/new_visualize_flow/index.ts +++ b/test/new_visualize_flow/index.ts @@ -11,7 +11,6 @@ import { FtrProviderContext } from '../functional/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile, getService }: FtrProviderContext) { describe('New Visualize Flow', function () { - this.tags('ciGroup11'); const esArchiver = getService('esArchiver'); before(async () => { await esArchiver.loadIfNeeded( diff --git a/test/plugin_functional/config.ts b/test/plugin_functional/config.ts index 4a96b2b402898..b2dbc762ab657 100644 --- a/test/plugin_functional/config.ts +++ b/test/plugin_functional/config.ts @@ -11,7 +11,7 @@ import path from 'path'; import fs from 'fs'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); // Find all folders in ./plugins since we treat all them as plugin folder const allFiles = fs.readdirSync(path.resolve(__dirname, 'plugins')); diff --git a/test/plugin_functional/test_suites/core_plugins/rendering.ts b/test/plugin_functional/test_suites/core_plugins/rendering.ts index 56264eec24477..2d87c0575845f 100644 --- a/test/plugin_functional/test_suites/core_plugins/rendering.ts +++ b/test/plugin_functional/test_suites/core_plugins/rendering.ts @@ -190,7 +190,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) { 'xpack.osquery.savedQueries (boolean)', 'xpack.remote_clusters.ui.enabled (boolean)', /** - * NOTE: The Reporting plugin is currently disabled in functional tests (see test/functional/config.js). + * NOTE: The Reporting plugin is currently disabled in functional tests (see test/functional/config.base.js). * It will be re-enabled once #102552 is completed. */ // 'xpack.reporting.roles.allow (array)', diff --git a/test/server_integration/config.js b/test/server_integration/config.base.js similarity index 97% rename from test/server_integration/config.js rename to test/server_integration/config.base.js index 0ebb5c48033b8..71006c258c423 100644 --- a/test/server_integration/config.js +++ b/test/server_integration/config.base.js @@ -14,7 +14,7 @@ import { export default async function ({ readConfigFile }) { const commonConfig = await readConfigFile(require.resolve('../common/config')); - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { services: { diff --git a/test/server_integration/http/platform/config.status.ts b/test/server_integration/http/platform/config.status.ts index 20ffc917f8244..8be9b24a56817 100644 --- a/test/server_integration/http/platform/config.status.ts +++ b/test/server_integration/http/platform/config.status.ts @@ -20,7 +20,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; */ // eslint-disable-next-line import/no-default-export export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const httpConfig = await readConfigFile(require.resolve('../../config')); + const httpConfig = await readConfigFile(require.resolve('../../config.base.js')); // Find all folders in __fixtures__/plugins since we treat all them as plugin folder const allFiles = fs.readdirSync(path.resolve(__dirname, '../../__fixtures__/plugins')); @@ -52,6 +52,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...httpConfig.get('kbnTestServer.runOptions'), // Don't wait for Kibana to be completely ready so that we can test the status timeouts wait: /Kibana is now unavailable/, + alwaysUseSource: true, }, }, }; diff --git a/test/server_integration/http/platform/config.ts b/test/server_integration/http/platform/config.ts index f3cdf426e9cbb..028ff67b43022 100644 --- a/test/server_integration/http/platform/config.ts +++ b/test/server_integration/http/platform/config.ts @@ -10,7 +10,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; // eslint-disable-next-line import/no-default-export export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const httpConfig = await readConfigFile(require.resolve('../../config')); + const httpConfig = await readConfigFile(require.resolve('../../config.base.js')); return { testFiles: [require.resolve('./cache'), require.resolve('./headers')], diff --git a/test/server_integration/http/ssl/config.js b/test/server_integration/http/ssl/config.js index 260ba7424d676..14d9a27a00f44 100644 --- a/test/server_integration/http/ssl/config.js +++ b/test/server_integration/http/ssl/config.js @@ -11,7 +11,7 @@ import { CA_CERT_PATH, KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils'; import { createKibanaSupertestProvider } from '../../services'; export default async function ({ readConfigFile }) { - const httpConfig = await readConfigFile(require.resolve('../../config')); + const httpConfig = await readConfigFile(require.resolve('../../config.base.js')); const certificateAuthorities = [readFileSync(CA_CERT_PATH)]; return { diff --git a/test/server_integration/http/ssl_redirect/config.js b/test/server_integration/http/ssl_redirect/config.js index aed7f23593820..47568b16bf6ba 100644 --- a/test/server_integration/http/ssl_redirect/config.js +++ b/test/server_integration/http/ssl_redirect/config.js @@ -13,7 +13,7 @@ import { CA_CERT_PATH, KBN_CERT_PATH, KBN_KEY_PATH } from '@kbn/dev-utils'; import { createKibanaSupertestProvider } from '../../services'; export default async function ({ readConfigFile }) { - const httpConfig = await readConfigFile(require.resolve('../../config')); + const httpConfig = await readConfigFile(require.resolve('../../config.base.js')); const certificateAuthorities = [readFileSync(CA_CERT_PATH)]; const redirectPort = httpConfig.get('servers.kibana.port') + 1234; diff --git a/test/server_integration/http/ssl_with_p12/config.js b/test/server_integration/http/ssl_with_p12/config.js index 5d2de9e9a9b54..51beb51b20ba4 100644 --- a/test/server_integration/http/ssl_with_p12/config.js +++ b/test/server_integration/http/ssl_with_p12/config.js @@ -11,7 +11,7 @@ import { CA_CERT_PATH, KBN_P12_PATH, KBN_P12_PASSWORD } from '@kbn/dev-utils'; import { createKibanaSupertestProvider } from '../../services'; export default async function ({ readConfigFile }) { - const httpConfig = await readConfigFile(require.resolve('../../config')); + const httpConfig = await readConfigFile(require.resolve('../../config.base.js')); const certificateAuthorities = [readFileSync(CA_CERT_PATH)]; return { diff --git a/test/server_integration/http/ssl_with_p12_intermediate/config.js b/test/server_integration/http/ssl_with_p12_intermediate/config.js index ffcb9da0fa047..a6eb6c82485d9 100644 --- a/test/server_integration/http/ssl_with_p12_intermediate/config.js +++ b/test/server_integration/http/ssl_with_p12_intermediate/config.js @@ -11,7 +11,7 @@ import { CA1_CERT_PATH, CA2_CERT_PATH, EE_P12_PATH, EE_P12_PASSWORD } from '../. import { createKibanaSupertestProvider } from '../../services'; export default async function ({ readConfigFile }) { - const httpConfig = await readConfigFile(require.resolve('../../config')); + const httpConfig = await readConfigFile(require.resolve('../../config.base.js')); const certificateAuthorities = [readFileSync(CA1_CERT_PATH), readFileSync(CA2_CERT_PATH)]; return { diff --git a/test/ui_capabilities/newsfeed_err/config.ts b/test/ui_capabilities/newsfeed_err/config.ts index e9548b41b67a0..4b6eb99a5627c 100644 --- a/test/ui_capabilities/newsfeed_err/config.ts +++ b/test/ui_capabilities/newsfeed_err/config.ts @@ -7,22 +7,20 @@ */ import { FtrConfigProviderContext } from '@kbn/test'; -// @ts-ignore untyped module -import getFunctionalConfig from '../../functional/config'; // eslint-disable-next-line import/no-default-export export default async ({ readConfigFile }: FtrConfigProviderContext) => { - const functionalConfig = await getFunctionalConfig({ readConfigFile }); + const baseConfig = await readConfigFile(require.resolve('../../functional/config.base.js')); return { - ...functionalConfig, + ...baseConfig.getAll(), testFiles: [require.resolve('./test')], kbnTestServer: { - ...functionalConfig.kbnTestServer, + ...baseConfig.get('kbnTestServer'), serverArgs: [ - ...functionalConfig.kbnTestServer.serverArgs, + ...baseConfig.get('kbnTestServer.serverArgs'), `--newsfeed.service.pathTemplate=/api/_newsfeed-FTS-external-service-simulators/kibana/crash.json`, ], }, diff --git a/test/ui_capabilities/newsfeed_err/test.ts b/test/ui_capabilities/newsfeed_err/test.ts index 52c1c0644299a..538d790ac5724 100644 --- a/test/ui_capabilities/newsfeed_err/test.ts +++ b/test/ui_capabilities/newsfeed_err/test.ts @@ -15,8 +15,6 @@ export default function uiCapabilitiesTests({ getService, getPageObjects }: FtrP const PageObjects = getPageObjects(['common', 'newsfeed']); describe('Newsfeed icon button handle errors', function () { - this.tags('ciGroup5'); - before(async () => { await PageObjects.newsfeed.resetPage(); }); diff --git a/test/visual_regression/config.ts b/test/visual_regression/config.ts index 3c11a4c2689ba..294848246e7c8 100644 --- a/test/visual_regression/config.ts +++ b/test/visual_regression/config.ts @@ -10,7 +10,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { services } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { ...functionalConfig.getAll(), diff --git a/test/visual_regression/tests/discover/index.ts b/test/visual_regression/tests/discover/index.ts index fe634c02400a4..9142a430f963b 100644 --- a/test/visual_regression/tests/discover/index.ts +++ b/test/visual_regression/tests/discover/index.ts @@ -16,8 +16,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const browser = getService('browser'); describe('discover app', function () { - this.tags('ciGroup5'); - before(function () { return browser.setWindowSize(SCREEN_WIDTH, 1000); }); diff --git a/test/visual_regression/tests/vega/index.ts b/test/visual_regression/tests/vega/index.ts index 71f22a3058d91..9ab4e199439a4 100644 --- a/test/visual_regression/tests/vega/index.ts +++ b/test/visual_regression/tests/vega/index.ts @@ -16,8 +16,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const browser = getService('browser'); describe('vega app', function () { - this.tags('ciGroup5'); - before(function () { return browser.setWindowSize(SCREEN_WIDTH, 1000); }); diff --git a/x-pack/README.md b/x-pack/README.md index d104dffff3d28..dad469295ca0f 100644 --- a/x-pack/README.md +++ b/x-pack/README.md @@ -20,7 +20,7 @@ For information on testing, see [the Elastic functional test development guide]( #### Running functional tests -The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.js)), *API integration tests* ([specified by this config](test/api_integration/config.ts)), and *SAML API integration tests* ([specified by this config](test/security_api_integration/saml.config.ts)). +The functional UI tests, the API integration tests, and the SAML API integration tests are all run against a live browser, Kibana, and Elasticsearch install. Each set of tests is specified with a unique config that describes how to start the Elasticsearch server, the Kibana server, and what tests to run against them. The sets of tests that exist today are *functional UI tests* ([specified by this config](test/functional/config.base.js)), *API integration tests* ([specified by this config](test/api_integration/config.ts)), and *SAML API integration tests* ([specified by this config](test/security_api_integration/saml.config.ts)). The script runs all sets of tests sequentially like so: * builds Elasticsearch and X-Pack diff --git a/x-pack/plugins/apm/dev_docs/testing.md b/x-pack/plugins/apm/dev_docs/testing.md index 6c35979add784..e1819875f58d8 100644 --- a/x-pack/plugins/apm/dev_docs/testing.md +++ b/x-pack/plugins/apm/dev_docs/testing.md @@ -96,13 +96,13 @@ TODO: We could try moving this tests to the new e2e tests located at `x-pack/plu **Start server** ``` -node scripts/functional_tests_server --config x-pack/test/functional/config.js +node scripts/functional_tests_server --config x-pack/test/functional/config.base.js ``` **Run tests** ``` -node scripts/functional_test_runner --config x-pack/test/functional/config.js --grep='APM specs' +node scripts/functional_test_runner --config x-pack/test/functional/config.base.js --grep='APM specs' ``` APM tests are located in `x-pack/test/functional/apps/apm`. diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts b/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts index 383a6fa68cf8a..2d9b530ed76a9 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/tasks/es_archiver.ts @@ -19,7 +19,7 @@ const NODE_TLS_REJECT_UNAUTHORIZED = '1'; export const esArchiverLoad = (archiveName: string) => { const archivePath = path.join(ES_ARCHIVE_DIR, archiveName); execSync( - `node ../../../../scripts/es_archiver load "${archivePath}" --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver load "${archivePath}" --config ../../../test/functional/config.base.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; @@ -27,14 +27,14 @@ export const esArchiverLoad = (archiveName: string) => { export const esArchiverUnload = (archiveName: string) => { const archivePath = path.join(ES_ARCHIVE_DIR, archiveName); execSync( - `node ../../../../scripts/es_archiver unload "${archivePath}" --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver unload "${archivePath}" --config ../../../test/functional/config.base.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; export const esArchiverResetKibana = () => { execSync( - `node ../../../../scripts/es_archiver empty-kibana-index --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver empty-kibana-index --config ../../../test/functional/config.base.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; diff --git a/x-pack/plugins/apm/ftr_e2e/ftr_config.ts b/x-pack/plugins/apm/ftr_e2e/ftr_config.ts index ec2e8d05a97dd..dd2166508d134 100644 --- a/x-pack/plugins/apm/ftr_e2e/ftr_config.ts +++ b/x-pack/plugins/apm/ftr_e2e/ftr_config.ts @@ -13,7 +13,7 @@ async function config({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../../test/common/config.js') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); return { diff --git a/x-pack/plugins/fleet/cypress/README.md b/x-pack/plugins/fleet/cypress/README.md index e9bb299ca905e..94de6b38c47ec 100644 --- a/x-pack/plugins/fleet/cypress/README.md +++ b/x-pack/plugins/fleet/cypress/README.md @@ -113,13 +113,13 @@ We use es_archiver to manage the data that our Cypress tests need. 3. When you are sure that you have all the data you need run the following command from: `x-pack/plugins/fleet` ```sh -node ../../../scripts/es_archiver save --dir ../../test/fleet_cypress/es_archives --config ../../../test/functional/config.js --es-url http://:@: +node ../../../scripts/es_archiver save --dir ../../test/fleet_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http://:@: ``` Example: ```sh -node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/fleet_cypress/es_archives --config ../../../test/functional/config.js --es-url http://elastic:changeme@localhost:9220 +node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/fleet_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http://elastic:changeme@localhost:9220 ``` Note that the command will create the folder if it does not exist. diff --git a/x-pack/plugins/graph/README.md b/x-pack/plugins/graph/README.md index a0d7eb25ff987..b17f114a8f01f 100644 --- a/x-pack/plugins/graph/README.md +++ b/x-pack/plugins/graph/README.md @@ -10,8 +10,8 @@ Graph shows only up in the side bar if your server is running on a platinum or t * Run type check `node scripts/type_check.js --project=x-pack/tsconfig.json` * Run linter `node scripts/eslint.js x-pack/plugins/graph` * Run functional tests (make sure to stop dev server) - * Server `cd x-pack && node ./scripts/functional_tests_server.js` - * Tests `cd x-pack && node ../scripts/functional_test_runner.js --config ./test/functional/config.js --grep=graph` + * Server `node ./scripts/functional_tests_server.js --config x-pack/test/functional/apps/graph/config.ts` + * Tests `node scripts/functional_test_runner.js --config x-pack/test/functional/apps/graph/config.ts` ## Folder structure diff --git a/x-pack/plugins/lens/readme.md b/x-pack/plugins/lens/readme.md index c85005c09754e..84cea6feead06 100644 --- a/x-pack/plugins/lens/readme.md +++ b/x-pack/plugins/lens/readme.md @@ -14,8 +14,9 @@ Run all tests from the `x-pack` root directory - Unit tests: `yarn test:jest x-pack/plugins/lens` - Functional tests: - Run `node scripts/functional_tests_server` - - Run `node ../scripts/functional_test_runner.js --config ./test/functional/config.js --grep="lens app"` - - You may want to comment out all imports except for Lens in the config file. + - Run `node ../scripts/functional_test_runner.js --config ./test/functional/apps/lens/group1/config.ts` + - Run `node ../scripts/functional_test_runner.js --config ./test/functional/apps/lens/group2/config.ts` + - Run `node ../scripts/functional_test_runner.js --config ./test/functional/apps/lens/group3/config.ts` - API Functional tests: - Run `node scripts/functional_tests_server` - Run `node ../scripts/functional_test_runner.js --config ./test/api_integration/config.ts --grep=Lens` diff --git a/x-pack/plugins/maps/README.md b/x-pack/plugins/maps/README.md index 729cba26f72ab..de683af8ac627 100644 --- a/x-pack/plugins/maps/README.md +++ b/x-pack/plugins/maps/README.md @@ -10,4 +10,7 @@ Run all tests from the `x-pack` root directory - Unit tests: `yarn test:jest x-pack/plugins/maps --watch` - Functional tests: - Run `node scripts/functional_tests_server` - - Run `node ../scripts/functional_test_runner.js --config ./test/functional/config.js --grep="maps app"` \ No newline at end of file + - Run `node ../scripts/functional_test_runner.js --config ./test/functional/apps/maps/group1/config.ts` + - Run `node ../scripts/functional_test_runner.js --config ./test/functional/apps/maps/group2/config.ts` + - Run `node ../scripts/functional_test_runner.js --config ./test/functional/apps/maps/group3/config.ts` + - Run `node ../scripts/functional_test_runner.js --config ./test/functional/apps/maps/group4/config.ts` \ No newline at end of file diff --git a/x-pack/plugins/osquery/cypress/README.md b/x-pack/plugins/osquery/cypress/README.md index 72d558b6e5980..6d72c6aa82b9d 100644 --- a/x-pack/plugins/osquery/cypress/README.md +++ b/x-pack/plugins/osquery/cypress/README.md @@ -101,13 +101,13 @@ We use es_archiver to manage the data that our Cypress tests need. 3. When you are sure that you have all the data you need run the following command from: `x-pack/plugins/osquery` ```sh -node ../../../scripts/es_archiver save --dir ../../test/osquery_cypress/es_archives --config ../../../test/functional/config.js --es-url http://:@: +node ../../../scripts/es_archiver save --dir ../../test/osquery_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http://:@: ``` Example: ```sh -node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/osquery_cypress/es_archives --config ../../../test/functional/config.js --es-url http://elastic:changeme@localhost:9220 +node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/osquery_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http://elastic:changeme@localhost:9220 ``` Note that the command will create the folder if it does not exist. diff --git a/x-pack/plugins/security_solution/cypress/README.md b/x-pack/plugins/security_solution/cypress/README.md index 69a8019146ae6..e0430ea332e99 100644 --- a/x-pack/plugins/security_solution/cypress/README.md +++ b/x-pack/plugins/security_solution/cypress/README.md @@ -203,7 +203,7 @@ yarn kbn bootstrap # load auditbeat data needed for test execution (which FTR normally does for us) cd x-pack/plugins/security_solution -node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http(s)://:@ --kibana-url http(s)://:@ +node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http(s)://:@ --kibana-url http(s)://:@ # launch the cypress test runner with overridden environment variables cd x-pack/plugins/security_solution @@ -221,7 +221,7 @@ yarn kbn bootstrap # load auditbeat data needed for test execution (which FTR normally does for us) cd x-pack/plugins/security_solution -node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http(s)://:@ --kibana-url http(s)://:@ +node ../../../scripts/es_archiver load auditbeat --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http(s)://:@ --kibana-url http(s)://:@ # launch the cypress test runner with overridden environment variables cd x-pack/plugins/security_solution @@ -344,13 +344,13 @@ We use es_archiver to manage the data that our Cypress tests need. 3. When you are sure that you have all the data you need run the following command from: `x-pack/plugins/security_solution` ```sh -node ../../../scripts/es_archiver save --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http://:@: +node ../../../scripts/es_archiver save --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http://:@: ``` Example: ```sh -node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.js --es-url http://elastic:changeme@localhost:9220 +node ../../../scripts/es_archiver save custom_rules ".kibana",".siem-signal*" --dir ../../test/security_solution_cypress/es_archives --config ../../../test/functional/config.base.js --es-url http://elastic:changeme@localhost:9220 ``` Note that the command will create the folder if it does not exist. diff --git a/x-pack/plugins/security_solution/cypress/tasks/es_archiver.ts b/x-pack/plugins/security_solution/cypress/tasks/es_archiver.ts index 83ec1536baf0f..588a1e94cf407 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/es_archiver.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/es_archiver.ts @@ -8,7 +8,7 @@ import Path from 'path'; const ES_ARCHIVE_DIR = '../../test/security_solution_cypress/es_archives'; -const CONFIG_PATH = '../../test/functional/config.js'; +const CONFIG_PATH = '../../test/functional/config.base.js'; const ES_URL = Cypress.env('ELASTICSEARCH_URL'); const KIBANA_URL = Cypress.config().baseUrl; const CCS_ES_URL = Cypress.env('CCS_ELASTICSEARCH_URL'); diff --git a/x-pack/plugins/synthetics/e2e/config.ts b/x-pack/plugins/synthetics/e2e/config.ts index e8af8510fe5dc..42e97eb21e90a 100644 --- a/x-pack/plugins/synthetics/e2e/config.ts +++ b/x-pack/plugins/synthetics/e2e/config.ts @@ -19,7 +19,7 @@ async function config({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../../test/common/config.js') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); const kibanaConfig = readKibanaConfig(); diff --git a/x-pack/plugins/synthetics/e2e/tasks/es_archiver.ts b/x-pack/plugins/synthetics/e2e/tasks/es_archiver.ts index dac5672bdf649..bbb66b19f5a5e 100644 --- a/x-pack/plugins/synthetics/e2e/tasks/es_archiver.ts +++ b/x-pack/plugins/synthetics/e2e/tasks/es_archiver.ts @@ -16,7 +16,7 @@ const NODE_TLS_REJECT_UNAUTHORIZED = '1'; export const esArchiverLoad = (folder: string) => { const path = Path.join(ES_ARCHIVE_DIR, folder); execSync( - `node ../../../../scripts/es_archiver load "${path}" --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver load "${path}" --config ../../../test/functional/config.base.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; @@ -24,14 +24,14 @@ export const esArchiverLoad = (folder: string) => { export const esArchiverUnload = (folder: string) => { const path = Path.join(ES_ARCHIVE_DIR, folder); execSync( - `node ../../../../scripts/es_archiver unload "${path}" --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver unload "${path}" --config ../../../test/functional/config.base.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; export const esArchiverResetKibana = () => { execSync( - `node ../../../../scripts/es_archiver empty-kibana-index --config ../../../test/functional/config.js`, + `node ../../../../scripts/es_archiver empty-kibana-index --config ../../../test/functional/config.base.js`, { env: { ...process.env, NODE_TLS_REJECT_UNAUTHORIZED }, stdio: 'inherit' } ); }; diff --git a/x-pack/scripts/functional_tests.js b/x-pack/scripts/functional_tests.js deleted file mode 100644 index ee99785aa8fad..0000000000000 --- a/x-pack/scripts/functional_tests.js +++ /dev/null @@ -1,96 +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. - */ - -require('../../src/setup_node_env'); -require('@kbn/test').runTestsCli([ - require.resolve('../test/functional/config.ccs.ts'), - require.resolve('../test/functional/config.js'), - require.resolve('../test/functional_basic/config.ts'), - require.resolve('../test/security_solution_endpoint/config.ts'), - require.resolve('../test/plugin_functional/config.ts'), - require.resolve('../test/functional_with_es_ssl/config.ts'), - require.resolve('../test/functional/config_security_basic.ts'), - require.resolve('../test/reporting_functional/reporting_and_security.config.ts'), - require.resolve('../test/reporting_functional/reporting_without_security.config.ts'), - require.resolve('../test/reporting_functional/reporting_and_deprecated_security.config.ts'), - require.resolve('../test/security_functional/login_selector.config.ts'), - require.resolve('../test/security_functional/oidc.config.ts'), - require.resolve('../test/security_functional/saml.config.ts'), - require.resolve('../test/functional_embedded/config.ts'), - require.resolve('../test/functional_cors/config.ts'), - require.resolve('../test/functional_enterprise_search/without_host_configured.config.ts'), - require.resolve('../test/saved_object_tagging/functional/config.ts'), - require.resolve('../test/usage_collection/config.ts'), - require.resolve('../test/fleet_functional/config.ts'), - require.resolve('../test/functional_synthetics/config.js'), - require.resolve('../test/api_integration/config_security_basic.ts'), - require.resolve('../test/api_integration/config_security_trial.ts'), - require.resolve('../test/api_integration/config.ts'), - require.resolve('../test/api_integration_basic/config.ts'), - require.resolve('../test/alerting_api_integration/basic/config.ts'), - require.resolve('../test/alerting_api_integration/spaces_only/config.ts'), - require.resolve('../test/alerting_api_integration/security_and_spaces/config.ts'), - require.resolve('../test/cases_api_integration/security_and_spaces/config_basic.ts'), - require.resolve('../test/cases_api_integration/security_and_spaces/config_trial.ts'), - require.resolve('../test/cases_api_integration/spaces_only/config.ts'), - require.resolve('../test/apm_api_integration/basic/config.ts'), - require.resolve('../test/apm_api_integration/trial/config.ts'), - require.resolve('../test/apm_api_integration/rules/config.ts'), - require.resolve('../test/detection_engine_api_integration/security_and_spaces/config.ts'), - require.resolve('../test/detection_engine_api_integration/basic/config.ts'), - require.resolve('../test/lists_api_integration/security_and_spaces/config.ts'), - require.resolve('../test/plugin_api_integration/config.ts'), - require.resolve('../test/rule_registry/security_and_spaces/config_basic.ts'), - require.resolve('../test/rule_registry/security_and_spaces/config_trial.ts'), - require.resolve('../test/rule_registry/spaces_only/config_basic.ts'), - require.resolve('../test/rule_registry/spaces_only/config_trial.ts'), - require.resolve('../test/security_api_integration/saml.config.ts'), - require.resolve('../test/security_api_integration/session_idle.config.ts'), - require.resolve('../test/security_api_integration/session_invalidate.config.ts'), - require.resolve('../test/security_api_integration/session_lifespan.config.ts'), - require.resolve('../test/security_api_integration/login_selector.config.ts'), - require.resolve('../test/security_api_integration/audit.config.ts'), - require.resolve('../test/security_api_integration/http_bearer.config.ts'), - require.resolve('../test/security_api_integration/http_no_auth_providers.config.ts'), - require.resolve('../test/security_api_integration/kerberos.config.ts'), - require.resolve('../test/security_api_integration/kerberos_anonymous_access.config.ts'), - require.resolve('../test/security_api_integration/pki.config.ts'), - require.resolve('../test/security_api_integration/oidc.config.ts'), - require.resolve('../test/security_api_integration/oidc_implicit_flow.config.ts'), - require.resolve('../test/security_api_integration/token.config.ts'), - require.resolve('../test/security_api_integration/anonymous.config.ts'), - require.resolve('../test/security_api_integration/anonymous_es_anonymous.config.ts'), - require.resolve('../test/observability_api_integration/basic/config.ts'), - require.resolve('../test/observability_api_integration/trial/config.ts'), - require.resolve('../test/observability_functional/with_rac_write.config.ts'), - require.resolve('../test/encrypted_saved_objects_api_integration/config.ts'), - require.resolve('../test/spaces_api_integration/spaces_only/config.ts'), - require.resolve('../test/spaces_api_integration/security_and_spaces/config_trial.ts'), - require.resolve('../test/spaces_api_integration/security_and_spaces/config_basic.ts'), - require.resolve('../test/saved_object_api_integration/security_and_spaces/config_trial.ts'), - require.resolve('../test/saved_object_api_integration/security_and_spaces/config_basic.ts'), - require.resolve('../test/saved_object_api_integration/spaces_only/config.ts'), - // TODO: Enable once RBAC timeline search strategy - // tests updated - // require.resolve('../test/timeline/security_and_spaces/config_basic.ts'), - require.resolve('../test/timeline/security_and_spaces/config_trial.ts'), - require.resolve('../test/ui_capabilities/security_and_spaces/config.ts'), - require.resolve('../test/ui_capabilities/spaces_only/config.ts'), - require.resolve('../test/upgrade_assistant_integration/config.js'), - require.resolve('../test/licensing_plugin/config.ts'), - require.resolve('../test/licensing_plugin/config.public.ts'), - require.resolve('../test/endpoint_api_integration_no_ingest/config.ts'), - require.resolve('../test/reporting_api_integration/reporting_and_security.config.ts'), - require.resolve('../test/reporting_api_integration/reporting_without_security.config.ts'), - require.resolve('../test/security_solution_endpoint_api_int/config.ts'), - require.resolve('../test/fleet_api_integration/config.ts'), - require.resolve('../test/search_sessions_integration/config.ts'), - require.resolve('../test/saved_object_tagging/api_integration/security_and_spaces/config.ts'), - require.resolve('../test/saved_object_tagging/api_integration/tagging_api/config.ts'), - require.resolve('../test/examples/config.ts'), - require.resolve('../test/functional_execution_context/config.ts'), -]); diff --git a/x-pack/scripts/functional_tests_server.js b/x-pack/scripts/functional_tests_server.js index 946f7ea3836a6..329fea019221b 100755 --- a/x-pack/scripts/functional_tests_server.js +++ b/x-pack/scripts/functional_tests_server.js @@ -8,4 +8,4 @@ process.env.ALLOW_PERFORMANCE_HOOKS_IN_TASK_MANAGER = true; require('../../src/setup_node_env'); -require('@kbn/test').startServersCli(require.resolve('../test/functional/config.js')); +require('@kbn/test').startServersCli(require.resolve('../test/functional/config.base.js')); diff --git a/x-pack/test/accessibility/apps/advanced_settings.ts b/x-pack/test/accessibility/apps/advanced_settings.ts index 6f2dc78a7b35b..6c931f0a0e5a1 100644 --- a/x-pack/test/accessibility/apps/advanced_settings.ts +++ b/x-pack/test/accessibility/apps/advanced_settings.ts @@ -13,7 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const toasts = getService('toasts'); - describe('Stack Management -Advanced Settings', () => { + describe('Stack Management -Advanced Settings Accessibility', () => { // click on Management > Advanced settings it('click on advanced settings ', async () => { await PageObjects.common.navigateToUrl('management', 'kibana/settings', { diff --git a/x-pack/test/accessibility/apps/canvas.ts b/x-pack/test/accessibility/apps/canvas.ts index 609c8bf5bb1ae..d9508e75bdf27 100644 --- a/x-pack/test/accessibility/apps/canvas.ts +++ b/x-pack/test/accessibility/apps/canvas.ts @@ -14,7 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const { common } = getPageObjects(['common']); - describe('Canvas', () => { + describe('Canvas Accessibility', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/canvas/default'); await common.navigateToApp('canvas'); diff --git a/x-pack/test/accessibility/apps/dashboard_edit_panel.ts b/x-pack/test/accessibility/apps/dashboard_edit_panel.ts index 5624a5f25db2f..20b72e142f5c7 100644 --- a/x-pack/test/accessibility/apps/dashboard_edit_panel.ts +++ b/x-pack/test/accessibility/apps/dashboard_edit_panel.ts @@ -20,7 +20,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PANEL_TITLE = 'Visualization PieChart'; - describe('Dashboard Edit Panel', () => { + describe('Dashboard Edit Panel Accessibility', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/dashboard/drilldowns'); await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); diff --git a/x-pack/test/accessibility/apps/enterprise_search.ts b/x-pack/test/accessibility/apps/enterprise_search.ts index aa6910842b5eb..0a1a5d68d9621 100644 --- a/x-pack/test/accessibility/apps/enterprise_search.ts +++ b/x-pack/test/accessibility/apps/enterprise_search.ts @@ -14,7 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const { common } = getPageObjects(['common']); - describe('Enterprise Search', () => { + describe('Enterprise Search Accessibility', () => { // NOTE: These accessibility tests currently only run against Enterprise Search in Kibana // without a sidecar Enterprise Search service/host configured, and as such only test // the basic setup guides and not the full application(s) diff --git a/x-pack/test/accessibility/apps/grok_debugger.ts b/x-pack/test/accessibility/apps/grok_debugger.ts index ecb62ffd53177..4f40696bb0eb6 100644 --- a/x-pack/test/accessibility/apps/grok_debugger.ts +++ b/x-pack/test/accessibility/apps/grok_debugger.ts @@ -13,7 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const grokDebugger = getService('grokDebugger'); // this test is failing as there is a violation https://github.com/elastic/kibana/issues/62102 - describe.skip('Dev tools grok debugger', () => { + describe.skip('Dev tools grok debugger Accessibility', () => { before(async () => { await PageObjects.common.navigateToApp('grokDebugger'); await grokDebugger.assertExists(); diff --git a/x-pack/test/accessibility/apps/home.ts b/x-pack/test/accessibility/apps/home.ts index 61297859c29f8..544a32843f7f3 100644 --- a/x-pack/test/accessibility/apps/home.ts +++ b/x-pack/test/accessibility/apps/home.ts @@ -13,7 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const find = getService('find'); - describe('Kibana Home', () => { + describe('Kibana Home Accessibility', () => { before(async () => { await common.navigateToApp('home'); }); diff --git a/x-pack/test/accessibility/apps/index_lifecycle_management.ts b/x-pack/test/accessibility/apps/index_lifecycle_management.ts index 6cec8d1cb891a..fc3ec1ff5cf81 100644 --- a/x-pack/test/accessibility/apps/index_lifecycle_management.ts +++ b/x-pack/test/accessibility/apps/index_lifecycle_management.ts @@ -63,14 +63,14 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { throw new Error(`Could not find ${policyName} in policy table`); }; - describe('Index Lifecycle Management', async () => { + describe('Index Lifecycle Management Accessibility', async () => { before(async () => { await esClient.snapshot.createRepository({ name: REPO_NAME, body: { type: 'fs', settings: { - // use one of the values defined in path.repo in test/functional/config.js + // use one of the values defined in path.repo in test/functional/config.base.js location: '/tmp/', }, }, diff --git a/x-pack/test/accessibility/apps/ingest_node_pipelines.ts b/x-pack/test/accessibility/apps/ingest_node_pipelines.ts index a09a07bb01267..4bbd9cde06d2d 100644 --- a/x-pack/test/accessibility/apps/ingest_node_pipelines.ts +++ b/x-pack/test/accessibility/apps/ingest_node_pipelines.ts @@ -14,7 +14,7 @@ export default function ({ getService, getPageObjects }: any) { const log = getService('log'); const a11y = getService('a11y'); /* this is the wrapping service around axe */ - describe('Ingest Pipelines', async () => { + describe('Ingest Pipelines Accessibility', async () => { before(async () => { await putSamplePipeline(esClient); await common.navigateToApp('ingestPipelines'); diff --git a/x-pack/test/accessibility/apps/kibana_overview.ts b/x-pack/test/accessibility/apps/kibana_overview.ts index 9d21f08a900cc..19af9c2828d35 100644 --- a/x-pack/test/accessibility/apps/kibana_overview.ts +++ b/x-pack/test/accessibility/apps/kibana_overview.ts @@ -11,7 +11,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'home']); const a11y = getService('a11y'); - describe('Kibana overview', () => { + describe('Kibana overview Accessibility', () => { const esArchiver = getService('esArchiver'); before(async () => { diff --git a/x-pack/test/accessibility/apps/lens.ts b/x-pack/test/accessibility/apps/lens.ts index 8a46d662a61cf..18459b56c0542 100644 --- a/x-pack/test/accessibility/apps/lens.ts +++ b/x-pack/test/accessibility/apps/lens.ts @@ -15,7 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const listingTable = getService('listingTable'); const kibanaServer = getService('kibanaServer'); - describe('Lens', () => { + describe('Lens Accessibility', () => { const lensChartName = 'MyLensChart'; before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/logstash_functional'); diff --git a/x-pack/test/accessibility/apps/license_management.ts b/x-pack/test/accessibility/apps/license_management.ts index 891a682e653ba..7693ebb197ff1 100644 --- a/x-pack/test/accessibility/apps/license_management.ts +++ b/x-pack/test/accessibility/apps/license_management.ts @@ -12,7 +12,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); const testSubjects = getService('testSubjects'); - describe('License Management page a11y tests', () => { + describe('License Management page Accessibility', () => { before(async () => { await PageObjects.common.navigateToApp('licenseManagement'); }); diff --git a/x-pack/test/accessibility/apps/login_page.ts b/x-pack/test/accessibility/apps/login_page.ts index 154517d09502e..6463e63fb2e49 100644 --- a/x-pack/test/accessibility/apps/login_page.ts +++ b/x-pack/test/accessibility/apps/login_page.ts @@ -14,8 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'security']); - // Failing: See https://github.com/elastic/kibana/issues/96372 - describe('Security', () => { + describe('Security Accessibility', () => { describe('Login Page', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); diff --git a/x-pack/test/accessibility/apps/maps.ts b/x-pack/test/accessibility/apps/maps.ts index c5b824c330829..0e4142e6ade60 100644 --- a/x-pack/test/accessibility/apps/maps.ts +++ b/x-pack/test/accessibility/apps/maps.ts @@ -13,7 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const PageObjects = getPageObjects(['common', 'settings', 'header', 'home', 'maps']); - describe('Maps app meets ally validations', () => { + describe('Maps app Accessibility', () => { before(async () => { await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, diff --git a/x-pack/test/accessibility/apps/ml.ts b/x-pack/test/accessibility/apps/ml.ts index fd05d2af07747..a783310d01706 100644 --- a/x-pack/test/accessibility/apps/ml.ts +++ b/x-pack/test/accessibility/apps/ml.ts @@ -5,15 +5,13 @@ * 2.0. */ -import path from 'path'; - import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const a11y = getService('a11y'); const ml = getService('ml'); - describe('ml', () => { + describe('ml Accessibility', () => { const esArchiver = getService('esArchiver'); before(async () => { @@ -79,16 +77,8 @@ export default function ({ getService }: FtrProviderContext) { const dfaJobType = 'outlier_detection'; const dfaJobId = `ihp_ally_${Date.now()}`; - const uploadFilePath = path.join( - __dirname, - '..', - '..', - 'functional', - 'apps', - 'ml', - 'data_visualizer', - 'files_to_import', - 'artificial_server_log' + const uploadFilePath = require.resolve( + '../../functional/apps/ml/data_visualizer/files_to_import/artificial_server_log' ); before(async () => { diff --git a/x-pack/test/accessibility/apps/ml_embeddables_in_dashboard.ts b/x-pack/test/accessibility/apps/ml_embeddables_in_dashboard.ts index 9532e8e365655..8f8bc67304c0d 100644 --- a/x-pack/test/accessibility/apps/ml_embeddables_in_dashboard.ts +++ b/x-pack/test/accessibility/apps/ml_embeddables_in_dashboard.ts @@ -60,7 +60,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'timePicker', 'dashboard']); const a11y = getService('a11y'); /* this is the wrapping service around axe */ - describe('machine learning embeddables anomaly charts', function () { + describe('machine learning embeddables anomaly charts Accessibility', function () { before(async () => { await ml.securityCommon.createMlRoles(); await ml.securityCommon.createMlUsers(); diff --git a/x-pack/test/accessibility/apps/painless_lab.ts b/x-pack/test/accessibility/apps/painless_lab.ts index c25930941b5eb..a0a4712dbe4e3 100644 --- a/x-pack/test/accessibility/apps/painless_lab.ts +++ b/x-pack/test/accessibility/apps/painless_lab.ts @@ -14,7 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); const retry = getService('retry'); - describe('Accessibility Painless Lab Editor', () => { + describe('Accessibility Painless Lab Editor Accessibility', () => { before(async () => { await PageObjects.common.navigateToApp('painlessLab'); }); diff --git a/x-pack/test/accessibility/apps/remote_clusters.ts b/x-pack/test/accessibility/apps/remote_clusters.ts index 67c85eda60a4a..deb0e4a090b8c 100644 --- a/x-pack/test/accessibility/apps/remote_clusters.ts +++ b/x-pack/test/accessibility/apps/remote_clusters.ts @@ -79,7 +79,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); const retry = getService('retry'); - describe('Remote Clusters', () => { + describe('Remote Clusters Accessibility', () => { beforeEach(async () => { await PageObjects.common.navigateToApp('remoteClusters'); }); diff --git a/x-pack/test/accessibility/apps/reporting.ts b/x-pack/test/accessibility/apps/reporting.ts index c6a6571cc0ff6..f1ac0770c9587 100644 --- a/x-pack/test/accessibility/apps/reporting.ts +++ b/x-pack/test/accessibility/apps/reporting.ts @@ -16,7 +16,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const security = getService('security'); const log = getService('log'); - describe('Reporting', () => { + describe('Reporting Accessibility', () => { const createReportingUser = async () => { await security.user.create(reporting.REPORTING_USER_USERNAME, { password: reporting.REPORTING_USER_PASSWORD, diff --git a/x-pack/test/accessibility/apps/roles.ts b/x-pack/test/accessibility/apps/roles.ts index 3c40e664d7da2..5369dced427fa 100644 --- a/x-pack/test/accessibility/apps/roles.ts +++ b/x-pack/test/accessibility/apps/roles.ts @@ -17,7 +17,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const kibanaServer = getService('kibanaServer'); - describe('Kibana roles page a11y tests', () => { + describe('Kibana roles page Accessibility', () => { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await kibanaServer.uiSettings.update({ diff --git a/x-pack/test/accessibility/apps/search_profiler.ts b/x-pack/test/accessibility/apps/search_profiler.ts index 47909662fb132..30043f8f4157f 100644 --- a/x-pack/test/accessibility/apps/search_profiler.ts +++ b/x-pack/test/accessibility/apps/search_profiler.ts @@ -15,7 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); const esArchiver = getService('esArchiver'); - describe('Accessibility Search Profiler Editor', () => { + describe('Search Profiler Editor Accessibility', () => { before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await PageObjects.common.navigateToApp('searchProfiler'); diff --git a/x-pack/test/accessibility/apps/search_sessions.ts b/x-pack/test/accessibility/apps/search_sessions.ts index 30bef9086a4b6..42a2f387612ac 100644 --- a/x-pack/test/accessibility/apps/search_sessions.ts +++ b/x-pack/test/accessibility/apps/search_sessions.ts @@ -15,7 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const find = getService('find'); const esArchiver = getService('esArchiver'); - describe('Search sessions a11y tests', () => { + describe('Search sessions Accessibility', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/data/search_sessions'); await PageObjects.searchSessionsManagement.goTo(); diff --git a/x-pack/test/accessibility/apps/security_solution.ts b/x-pack/test/accessibility/apps/security_solution.ts index 8014e03152b17..ef930f093eb4a 100644 --- a/x-pack/test/accessibility/apps/security_solution.ts +++ b/x-pack/test/accessibility/apps/security_solution.ts @@ -15,7 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); // FLAKY: https://github.com/elastic/kibana/issues/95707 - describe.skip('Security Solution', () => { + describe.skip('Security Solution Accessibility', () => { before(async () => { await security.testUser.setRoles(['superuser'], { skipBrowserRefresh: true }); await common.navigateToApp('security'); diff --git a/x-pack/test/accessibility/apps/spaces.ts b/x-pack/test/accessibility/apps/spaces.ts index 567f958f5f8a4..38b34054911f6 100644 --- a/x-pack/test/accessibility/apps/spaces.ts +++ b/x-pack/test/accessibility/apps/spaces.ts @@ -18,7 +18,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const toasts = getService('toasts'); - describe('Kibana spaces page meets a11y validations', () => { + describe('Kibana Spaces Accessibility', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); await PageObjects.common.navigateToApp('home'); diff --git a/x-pack/test/accessibility/apps/tags.ts b/x-pack/test/accessibility/apps/tags.ts index 8174c8fa8c06b..da51f2f0535e2 100644 --- a/x-pack/test/accessibility/apps/tags.ts +++ b/x-pack/test/accessibility/apps/tags.ts @@ -16,7 +16,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); const toasts = getService('toasts'); - describe('Kibana tags page meets a11y validations', () => { + describe('Kibana Tags Page Accessibility', () => { before(async () => { await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', { useActualUrl: true, diff --git a/x-pack/test/accessibility/apps/transform.ts b/x-pack/test/accessibility/apps/transform.ts index 59f19471490b8..fa54ea4ad6766 100644 --- a/x-pack/test/accessibility/apps/transform.ts +++ b/x-pack/test/accessibility/apps/transform.ts @@ -11,7 +11,7 @@ export default function ({ getService }: FtrProviderContext) { const a11y = getService('a11y'); const transform = getService('transform'); - describe('transform', () => { + describe('transform Accessibility', () => { const esArchiver = getService('esArchiver'); before(async () => { diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 1f7fd2a654bca..fffb6e684ba4a 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -53,7 +53,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const es = getService('es'); const log = getService('log'); - describe.skip('Upgrade Assistant', () => { + describe.skip('Upgrade Assistant Accessibility', () => { before(async () => { await PageObjects.upgradeAssistant.navigateToPage(); diff --git a/x-pack/test/accessibility/apps/uptime.ts b/x-pack/test/accessibility/apps/uptime.ts index 41664c5920b82..49243c37fe730 100644 --- a/x-pack/test/accessibility/apps/uptime.ts +++ b/x-pack/test/accessibility/apps/uptime.ts @@ -19,7 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const es = getService('es'); const toasts = getService('toasts'); - describe('uptime', () => { + describe('uptime Accessibility', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/uptime/blank'); await makeChecks(es, A11Y_TEST_MONITOR_ID, 150, 1, 1000, { diff --git a/x-pack/test/accessibility/apps/users.ts b/x-pack/test/accessibility/apps/users.ts index 8682cc8f0a884..5833a19580c24 100644 --- a/x-pack/test/accessibility/apps/users.ts +++ b/x-pack/test/accessibility/apps/users.ts @@ -17,7 +17,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const find = getService('find'); const retry = getService('retry'); - describe('Kibana users page a11y tests', () => { + describe('Kibana users Accessibility', () => { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); await PageObjects.security.clickElasticsearchUsers(); diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index e85b8a9ef17d8..30c130df23a15 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -10,7 +10,7 @@ import { services } from './services'; import { pageObjects } from './page_objects'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { ...functionalConfig.getAll(), diff --git a/x-pack/test/alerting_api_integration/basic/tests/index.ts b/x-pack/test/alerting_api_integration/basic/tests/index.ts index 6ddb09b1c666e..ba6ebbe6a944e 100644 --- a/x-pack/test/alerting_api_integration/basic/tests/index.ts +++ b/x-pack/test/alerting_api_integration/basic/tests/index.ts @@ -13,8 +13,6 @@ export default function alertingApiIntegrationTests({ getService, }: FtrProviderContext) { describe('alerting api integration basic license', function () { - this.tags('ciGroup13'); - loadTestFile(require.resolve('./actions')); loadTestFile(require.resolve('./alerts')); }); diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index 14039ad3360a0..ffdf0c09ad216 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -25,6 +25,7 @@ interface CreateTestConfigOptions { customizeLocalHostSsl?: boolean; rejectUnauthorized?: boolean; // legacy emailDomainsAllowed?: string[]; + testFiles?: string[]; } // test.not-enabled is specifically not enabled @@ -64,6 +65,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) customizeLocalHostSsl = false, rejectUnauthorized = true, // legacy emailDomainsAllowed = undefined, + testFiles = undefined, } = options; return async ({ readConfigFile }: FtrConfigProviderContext) => { @@ -139,7 +141,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) : []; return { - testFiles: [require.resolve(`../${name}/tests/`)], + testFiles: testFiles ? testFiles : [require.resolve(`../${name}/tests/`)], servers, services, junit: { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/config.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/config.ts similarity index 82% rename from x-pack/test/alerting_api_integration/security_and_spaces/config.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/config.ts index 314f65c167048..9b90a4c18fdf0 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/config.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/config.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { createTestConfig } from '../common/config'; +import { createTestConfig } from '../../common/config'; // eslint-disable-next-line import/no-default-export export default createTestConfig('security_and_spaces', { @@ -14,4 +14,5 @@ export default createTestConfig('security_and_spaces', { ssl: true, enableActionsProxy: true, publicBaseUrl: true, + testFiles: [require.resolve('./tests')], }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts index 57ba6e3863576..e601c6ee15ec7 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; +import { UserAtSpaceScenarios } from '../../../scenarios'; import { checkAAD, getTestRuleData, @@ -15,8 +15,8 @@ import { ObjectRemover, getProducerUnauthorizedErrorMessage, TaskManagerDoc, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/delete.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/delete.ts index 56c50f035b10e..2b6086cf38d92 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/delete.ts @@ -6,15 +6,15 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; +import { UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, ObjectRemover, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDeleteTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts index 8a4266eb8dc8a..864de743ea343 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/disable.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createDisableAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts index 6d667eff24072..0aba468174cff 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/enable.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -17,7 +17,7 @@ import { getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, TaskManagerDoc, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createEnableAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/execution_status.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/execution_status.ts similarity index 95% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/execution_status.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/execution_status.ts index 4e61fd6593113..122353f444536 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/execution_status.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/execution_status.ts @@ -7,9 +7,9 @@ import expect from '@kbn/expect'; import { RuleExecutionStatusErrorReasons } from '@kbn/alerting-plugin/common'; -import { Spaces } from '../../scenarios'; -import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { Spaces } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function executionStatusAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/find.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts index 84f0d7709d01a..20a5e82d303fe 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts @@ -9,9 +9,9 @@ import expect from '@kbn/expect'; import { SuperTest, Test } from 'supertest'; import { chunk, omit } from 'lodash'; import uuid from 'uuid'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; const findTestUtils = ( describeType: 'internal' | 'public', diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts index 180a3cf36e27f..48559aa35ac3c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts @@ -7,15 +7,15 @@ import expect from '@kbn/expect'; import { SuperTest, Test } from 'supertest'; -import { UserAtSpaceScenarios } from '../../scenarios'; +import { UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; const getTestUtils = ( describeType: 'internal' | 'public', diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_state.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get_alert_state.ts similarity index 97% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_state.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get_alert_state.ts index 3bdfe49464fcf..e3da329c1cbaf 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_state.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get_alert_state.ts @@ -12,9 +12,9 @@ import { getTestRuleData, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { UserAtSpaceScenarios } from '../../scenarios'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; // eslint-disable-next-line import/no-default-export export default function createGetAlertStateTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_summary.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get_alert_summary.ts similarity index 97% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_summary.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get_alert_summary.ts index eb4e592a91d8a..f0ba9dc451937 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_summary.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get_alert_summary.ts @@ -13,9 +13,9 @@ import { getTestRuleData, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { UserAtSpaceScenarios } from '../../scenarios'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; // eslint-disable-next-line import/no-default-export export default function createGetAlertSummaryTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts new file mode 100644 index 0000000000000..6753b6383872d --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/index.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { setupSpacesAndUsers, tearDown } from '../../../setup'; + +// eslint-disable-next-line import/no-default-export +export default function alertingTests({ loadTestFile, getService }: FtrProviderContext) { + describe('Alerts - Group 1', () => { + describe('alerts', () => { + before(async () => { + await setupSpacesAndUsers(getService); + }); + + after(async () => { + await tearDown(getService); + }); + + loadTestFile(require.resolve('./find')); + loadTestFile(require.resolve('./create')); + loadTestFile(require.resolve('./delete')); + loadTestFile(require.resolve('./disable')); + loadTestFile(require.resolve('./enable')); + loadTestFile(require.resolve('./execution_status')); + loadTestFile(require.resolve('./get')); + loadTestFile(require.resolve('./get_alert_state')); + loadTestFile(require.resolve('./get_alert_summary')); + loadTestFile(require.resolve('./rule_types')); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rule_types.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/rule_types.ts similarity index 96% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rule_types.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/rule_types.ts index 0c527ac1449f8..e9d8175f9066e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rule_types.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/rule_types.ts @@ -7,9 +7,9 @@ import expect from '@kbn/expect'; import { omit } from 'lodash'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { getUrlPrefix } from '../../../common/lib/space_test_utils'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix } from '../../../../common/lib/space_test_utils'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function listAlertTypes({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/index.ts new file mode 100644 index 0000000000000..795af26627dfb --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function alertingApiIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('alerting api integration security and spaces enabled', function () { + describe('', function () { + loadTestFile(require.resolve('./alerting')); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/config.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/config.ts new file mode 100644 index 0000000000000..9b90a4c18fdf0 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig('security_and_spaces', { + disabledPlugins: [], + license: 'trial', + ssl: true, + enableActionsProxy: true, + publicBaseUrl: true, + testFiles: [require.resolve('./tests')], +}); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/email.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/email.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/email.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/email.ts index 6fb2315956b69..4d9282d4fdeea 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/email.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/email.ts @@ -7,11 +7,11 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { ExternalServiceSimulator, getExternalServiceSimulatorPath, -} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +} from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function emailTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/es_index.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/es_index.ts index edf352936e979..fed3acba1147e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/es_index.ts @@ -7,7 +7,7 @@ import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/es_index_preconfigured.ts similarity index 96% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/es_index_preconfigured.ts index caa7d57688037..a447921ac5041 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/es_index_preconfigured.ts @@ -7,7 +7,7 @@ import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; // from: x-pack/test/alerting_api_integration/common/config.ts const ACTION_ID = 'preconfigured-es-index-action'; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/jira.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/jira.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/jira.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/jira.ts index 33185a20c9249..5a6e0967736a2 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/jira.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/jira.ts @@ -8,13 +8,13 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getExternalServiceSimulatorPath, ExternalServiceSimulator, -} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +} from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function jiraTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/pagerduty.ts similarity index 96% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/pagerduty.ts index 05dba49236197..731eab7dad0f3 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/pagerduty.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/pagerduty.ts @@ -8,13 +8,13 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getExternalServiceSimulatorPath, ExternalServiceSimulator, -} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +} from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function pagerdutyTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/resilient.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/resilient.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/resilient.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/resilient.ts index e2a92701b62cb..fec22ab72e1ef 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/resilient.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/resilient.ts @@ -8,13 +8,13 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getExternalServiceSimulatorPath, ExternalServiceSimulator, -} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +} from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function resilientTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/server_log.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/server_log.ts similarity index 96% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/server_log.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/server_log.ts index fb7bac7d81e9c..b8b12d6aac764 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/server_log.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/server_log.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function serverLogTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_itom.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_itom.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_itom.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_itom.ts index c685fff8abfc6..0771e4e293726 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_itom.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_itom.ts @@ -11,9 +11,9 @@ import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import { getServiceNowServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getServiceNowServer } from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function serviceNowITOMTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_itsm.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_itsm.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_itsm.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_itsm.ts index 0f81753bbc731..368e1b104a87e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_itsm.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_itsm.ts @@ -11,9 +11,9 @@ import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import { getServiceNowServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getServiceNowServer } from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function serviceNowITSMTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_sir.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_sir.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_sir.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_sir.ts index 0f5640f7edd3e..f08ca542e4617 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/servicenow_sir.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/servicenow_sir.ts @@ -11,9 +11,9 @@ import { asyncForEach } from '@kbn/std'; import getPort from 'get-port'; import http from 'http'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import { getServiceNowServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getServiceNowServer } from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function serviceNowSIRTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/slack.ts similarity index 96% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/slack.ts index 66b988fb9b4eb..a05c622d8a1cf 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/slack.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/slack.ts @@ -9,10 +9,10 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; import http from 'http'; import getPort from 'get-port'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; -import { getSlackServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +import { getSlackServer } from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function slackTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/swimlane.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/swimlane.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/swimlane.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/swimlane.ts index a55e8e30d419a..4119a409d7a4b 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/swimlane.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/swimlane.ts @@ -10,9 +10,9 @@ import expect from '@kbn/expect'; import getPort from 'get-port'; import http from 'http'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import { getSwimlaneServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; +import { getSwimlaneServer } from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function swimlaneTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/webhook.ts similarity index 97% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/webhook.ts index 44a74a7a31571..c484dfad69539 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/webhook.ts @@ -10,13 +10,13 @@ import http from 'http'; import expect from '@kbn/expect'; import { URL, format as formatUrl } from 'url'; import getPort from 'get-port'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getExternalServiceSimulatorPath, ExternalServiceSimulator, getWebhookServer, -} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +} from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; const defaultValues: Record = { headers: null, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/xmatters.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/xmatters.ts similarity index 96% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/xmatters.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/xmatters.ts index 7ce357bc62e36..e33597057cfe1 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/xmatters.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/builtin_action_types/xmatters.ts @@ -8,13 +8,13 @@ import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; -import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getHttpProxyServer } from '../../../../../common/lib/get_proxy_server'; +import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; import { getExternalServiceSimulatorPath, ExternalServiceSimulator, -} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +} from '../../../../../common/fixtures/plugins/actions_simulators/server/plugin'; // eslint-disable-next-line import/no-default-export export default function xmattersTest({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/config.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/config.ts new file mode 100644 index 0000000000000..506d0016af4f6 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../../../../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig('security_and_spaces', { + disabledPlugins: [], + license: 'trial', + ssl: true, + enableActionsProxy: true, + publicBaseUrl: true, + testFiles: [require.resolve('.')], +}); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/connector_types.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types.ts similarity index 91% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/connector_types.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types.ts index ec23719880926..feacbaa48be42 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/connector_types.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types.ts @@ -6,9 +6,9 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { getUrlPrefix } from '../../../common/lib/space_test_utils'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix } from '../../../../common/lib/space_test_utils'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function listActionTypesTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/create.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/create.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/create.ts index 06e8017177138..15d43f9782d94 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/create.ts @@ -6,9 +6,9 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { checkAAD, getUrlPrefix, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { checkAAD, getUrlPrefix, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createActionTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/delete.ts similarity index 97% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/delete.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/delete.ts index a0aae0a1bd64d..b0cfffdd2f464 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/delete.ts @@ -7,9 +7,9 @@ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function deleteActionTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts index c8433ac60575f..35361920cc729 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/execute.ts @@ -7,15 +7,15 @@ import expect from '@kbn/expect'; import { IValidatedEvent, nanosToMillis } from '@kbn/event-log-plugin/server'; -import { UserAtSpaceScenarios } from '../../scenarios'; +import { UserAtSpaceScenarios } from '../../../scenarios'; import { ESTestIndexTool, ES_TEST_INDEX_NAME, getUrlPrefix, ObjectRemover, getEventLog, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get.ts similarity index 96% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get.ts index 9842b13a9745d..f58481bb94412 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get.ts @@ -6,9 +6,9 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { getUrlPrefix, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function getActionTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all.ts index ab6181369755f..103ae5abd3071 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/get_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all.ts @@ -6,9 +6,9 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function getAllActionTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/index.ts similarity index 93% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/index.ts index 93d4bbb4065ed..6d1ecdbee566c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/index.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { setupSpacesAndUsers, tearDown } from '..'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { setupSpacesAndUsers, tearDown } from '../../../setup'; // eslint-disable-next-line import/no-default-export export default function actionsTests({ loadTestFile, getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/manual/pr_40694.js b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/manual/pr_40694.js similarity index 100% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/manual/pr_40694.js rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/manual/pr_40694.js diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/update.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/update.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/update.ts index 92bb7084ec534..6a9181d5ba5dd 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/update.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/update.ts @@ -6,9 +6,9 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { checkAAD, getUrlPrefix, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { checkAAD, getUrlPrefix, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function updateActionTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts index 407d6467296e4..5dfbdfa9707c2 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/alerts.ts @@ -11,8 +11,8 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IValidatedEvent, nanosToMillis } from '@kbn/event-log-plugin/server'; import { TaskRunning, TaskRunningStage } from '@kbn/task-manager-plugin/server/task_running'; import { ConcreteTaskInstance } from '@kbn/task-manager-plugin/server'; -import { UserAtSpaceScenarios, Superuser } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios, Superuser } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { ESTestIndexTool, ES_TEST_INDEX_NAME, @@ -23,7 +23,7 @@ import { getConsumerUnauthorizedErrorMessage, TaskManagerUtils, getEventLog, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/event_log.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/event_log.ts similarity index 92% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/event_log.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/event_log.ts index 4a572002a4366..424c734b5c6a2 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/event_log.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/event_log.ts @@ -6,10 +6,10 @@ */ import expect from '@kbn/expect'; -import { Spaces } from '../../scenarios'; -import { getUrlPrefix, getTestRuleData, ObjectRemover, getEventLog } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { validateEvent } from '../../../spaces_only/tests/alerting/event_log'; +import { Spaces } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover, getEventLog } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { validateEvent } from '../../../../spaces_only/tests/alerting/event_log'; // eslint-disable-next-line import/no-default-export export default function eventLogTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/excluded.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/excluded.ts similarity index 94% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/excluded.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/excluded.ts index eae80da85dc59..d09edae045e6f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/excluded.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/excluded.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; +import { UserAtSpaceScenarios } from '../../../scenarios'; import { getTestRuleData, getUrlPrefix, @@ -14,8 +14,8 @@ import { getEventLog, AlertUtils, ES_TEST_INDEX_NAME, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/health.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/health.ts similarity index 97% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/health.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/health.ts index d51cf8cc96af9..0663696dbee14 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/health.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/health.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { getUrlPrefix, getTestRuleData, @@ -15,7 +15,7 @@ import { AlertUtils, ESTestIndexTool, ES_TEST_INDEX_NAME, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createFindTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts new file mode 100644 index 0000000000000..72890c2bbd90a --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/index.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { setupSpacesAndUsers, tearDown } from '../../../setup'; + +// eslint-disable-next-line import/no-default-export +export default function alertingTests({ loadTestFile, getService }: FtrProviderContext) { + describe('Alerts', () => { + describe('legacy alerts', function () { + before(async () => { + await setupSpacesAndUsers(getService); + }); + + after(async () => { + await tearDown(getService); + }); + + loadTestFile(require.resolve('./rbac_legacy')); + }); + + describe('alerts', () => { + before(async () => { + await setupSpacesAndUsers(getService); + }); + + after(async () => { + await tearDown(getService); + }); + + loadTestFile(require.resolve('./mute_all')); + loadTestFile(require.resolve('./mute_instance')); + loadTestFile(require.resolve('./unmute_all')); + loadTestFile(require.resolve('./unmute_instance')); + loadTestFile(require.resolve('./update')); + loadTestFile(require.resolve('./update_api_key')); + loadTestFile(require.resolve('./alerts')); + loadTestFile(require.resolve('./event_log')); + loadTestFile(require.resolve('./mustache_templates')); + loadTestFile(require.resolve('./health')); + loadTestFile(require.resolve('./excluded')); + loadTestFile(require.resolve('./snooze')); + }); + }); +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mustache_templates.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mustache_templates.ts similarity index 92% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mustache_templates.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mustache_templates.ts index 7e3a7599a73e0..2426c154aa443 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mustache_templates.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mustache_templates.ts @@ -18,11 +18,11 @@ import axios from 'axios'; import httpProxy from 'http-proxy'; import expect from '@kbn/expect'; -import { Spaces } from '../../scenarios'; -import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { getSlackServer } from '../../../common/fixtures/plugins/actions_simulators/server/plugin'; -import { getHttpProxyServer } from '../../../common/lib/get_proxy_server'; +import { Spaces } from '../../../scenarios'; +import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { getSlackServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin'; +import { getHttpProxyServer } from '../../../../common/lib/get_proxy_server'; // eslint-disable-next-line import/no-default-export export default function executionStatusAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mute_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mute_all.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts index 1cac93cb52b78..5a4c792463b62 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mute_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_all.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createMuteAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mute_instance.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_instance.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mute_instance.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_instance.ts index 3948f910423a9..63a285e0f4cb8 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/mute_instance.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/mute_instance.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createMuteAlertInstanceTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/rbac_legacy.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/rbac_legacy.ts index 4f324cae689cd..4f0f53383e206 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/rbac_legacy.ts @@ -7,10 +7,10 @@ import expect from '@kbn/expect'; import { SavedObjectsUtils } from '@kbn/core/server/saved_objects'; -import { UserAtSpaceScenarios, Superuser } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { ESTestIndexTool, getUrlPrefix, ObjectRemover, AlertUtils } from '../../../common/lib'; -import { setupSpacesAndUsers } from '..'; +import { UserAtSpaceScenarios, Superuser } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { ESTestIndexTool, getUrlPrefix, ObjectRemover, AlertUtils } from '../../../../common/lib'; +import { setupSpacesAndUsers } from '../../../setup'; // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/snooze.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/snooze.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/snooze.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/snooze.ts index 929b95535e195..553e090498f00 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/snooze.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/snooze.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; const FUTURE_SNOOZE_TIME = '9999-12-31T06:00:00.000Z'; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unmute_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unmute_all.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts index e97e7e73abe44..dde198f54f771 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unmute_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_all.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createUnmuteAlertTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unmute_instance.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_instance.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unmute_instance.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_instance.ts index 17ee25e822a6d..1aa84f64a7e79 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unmute_instance.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unmute_instance.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createMuteAlertInstanceTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unsnooze.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unsnooze.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unsnooze.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unsnooze.ts index ed37a19d80707..c868654235c21 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/unsnooze.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/unsnooze.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createUnsnoozeRuleTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts index b2a1ae223f62c..c49fa62c606b6 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { Response as SupertestResponse } from 'supertest'; -import { UserAtSpaceScenarios } from '../../scenarios'; +import { UserAtSpaceScenarios } from '../../../scenarios'; import { checkAAD, getUrlPrefix, @@ -16,8 +16,8 @@ import { ensureDatetimeIsWithinRange, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createUpdateTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update_api_key.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update_api_key.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update_api_key.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update_api_key.ts index 1c25ec550c41e..a0d1eb4dd0756 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/update_api_key.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update_api_key.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; -import { UserAtSpaceScenarios } from '../../scenarios'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +import { UserAtSpaceScenarios } from '../../../scenarios'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { AlertUtils, checkAAD, @@ -16,7 +16,7 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, -} from '../../../common/lib'; +} from '../../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createUpdateApiKeyTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/index.ts new file mode 100644 index 0000000000000..c4b5ab80c3416 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default function alertingApiIntegrationTests({ loadTestFile }: FtrProviderContext) { + describe('alerting api integration security and spaces enabled - Group 2', function () { + loadTestFile(require.resolve('./telemetry')); + loadTestFile(require.resolve('./actions')); + loadTestFile(require.resolve('./alerting')); + }); +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/actions_telemetry.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/actions_telemetry.ts similarity index 98% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/actions_telemetry.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/actions_telemetry.ts index 1d8d0091b67de..b187b9e9f9759 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/actions_telemetry.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/actions_telemetry.ts @@ -6,15 +6,15 @@ */ import expect from '@kbn/expect'; -import { Spaces, Superuser } from '../../scenarios'; +import { Spaces, Superuser } from '../../../scenarios'; import { getUrlPrefix, getEventLog, getTestRuleData, ObjectRemover, TaskManagerDoc, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createActionsTelemetryTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/alerting_telemetry.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/alerting_telemetry.ts similarity index 99% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/alerting_telemetry.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/alerting_telemetry.ts index afc39bf1c6b74..811eeecfc0375 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/alerting_telemetry.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/alerting_telemetry.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { Spaces, Superuser } from '../../scenarios'; +import { Spaces, Superuser } from '../../../scenarios'; import { getUrlPrefix, getEventLog, @@ -14,8 +14,8 @@ import { ObjectRemover, TaskManagerDoc, ESTestIndexTool, -} from '../../../common/lib'; -import { FtrProviderContext } from '../../../common/ftr_provider_context'; +} from '../../../../common/lib'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertingTelemetryTests({ getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/config.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/config.ts new file mode 100644 index 0000000000000..506d0016af4f6 --- /dev/null +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createTestConfig } from '../../../../common/config'; + +// eslint-disable-next-line import/no-default-export +export default createTestConfig('security_and_spaces', { + disabledPlugins: [], + license: 'trial', + ssl: true, + enableActionsProxy: true, + publicBaseUrl: true, + testFiles: [require.resolve('.')], +}); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/index.ts similarity index 84% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/index.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/index.ts index 9e73fafc9f7bd..6077997b661ae 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/telemetry/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/telemetry/index.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { setupSpacesAndUsers, tearDown } from '..'; +import { FtrProviderContext } from '../../../../common/ftr_provider_context'; +import { setupSpacesAndUsers, tearDown } from '../../../setup'; // eslint-disable-next-line import/no-default-export export default function actionsTests({ loadTestFile, getService }: FtrProviderContext) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/setup.ts similarity index 73% rename from x-pack/test/alerting_api_integration/security_and_spaces/tests/index.ts rename to x-pack/test/alerting_api_integration/security_and_spaces/setup.ts index 1196e3716347d..69ca58e1edc12 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/setup.ts @@ -6,8 +6,8 @@ */ import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { isCustomRoleSpecification } from '../../common/types'; -import { Spaces, Users } from '../scenarios'; +import { isCustomRoleSpecification } from '../common/types'; +import { Spaces, Users } from './scenarios'; export async function setupSpacesAndUsers(getService: FtrProviderContext['getService']) { const securityService = getService('security'); @@ -54,18 +54,3 @@ export async function tearDown(getService: FtrProviderContext['getService']) { await esArchiver.unload('x-pack/test/functional/es_archives/empty_kibana'); } - -// eslint-disable-next-line import/no-default-export -export default function alertingApiIntegrationTests({ loadTestFile }: FtrProviderContext) { - describe('alerting api integration security and spaces enabled', function () { - describe('', function () { - this.tags('ciGroup17'); - loadTestFile(require.resolve('./telemetry')); - loadTestFile(require.resolve('./actions')); - }); - - describe('', function () { - loadTestFile(require.resolve('./alerting')); - }); - }); -} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/index.ts deleted file mode 100644 index 9dd7326aa4663..0000000000000 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { setupSpacesAndUsers, tearDown } from '..'; - -// eslint-disable-next-line import/no-default-export -export default function alertingTests({ loadTestFile, getService }: FtrProviderContext) { - describe('Alerts', () => { - describe('legacy alerts', function () { - this.tags('ciGroup17'); - - before(async () => { - await setupSpacesAndUsers(getService); - }); - - after(async () => { - await tearDown(getService); - }); - - loadTestFile(require.resolve('./rbac_legacy')); - }); - - describe('alerts', () => { - before(async () => { - await setupSpacesAndUsers(getService); - }); - - after(async () => { - await tearDown(getService); - }); - - describe('', function () { - this.tags('ciGroup17'); - loadTestFile(require.resolve('./find')); - loadTestFile(require.resolve('./create')); - loadTestFile(require.resolve('./delete')); - loadTestFile(require.resolve('./disable')); - loadTestFile(require.resolve('./enable')); - loadTestFile(require.resolve('./execution_status')); - loadTestFile(require.resolve('./get')); - loadTestFile(require.resolve('./get_alert_state')); - loadTestFile(require.resolve('./get_alert_summary')); - loadTestFile(require.resolve('./rule_types')); - }); - - describe('', function () { - this.tags('ciGroup30'); - loadTestFile(require.resolve('./mute_all')); - loadTestFile(require.resolve('./mute_instance')); - loadTestFile(require.resolve('./unmute_all')); - loadTestFile(require.resolve('./unmute_instance')); - loadTestFile(require.resolve('./update')); - loadTestFile(require.resolve('./update_api_key')); - loadTestFile(require.resolve('./alerts')); - loadTestFile(require.resolve('./event_log')); - loadTestFile(require.resolve('./mustache_templates')); - loadTestFile(require.resolve('./health')); - loadTestFile(require.resolve('./excluded')); - loadTestFile(require.resolve('./snooze')); - }); - }); - }); -} diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/index.ts index 88e5e0740789f..424deaaf83815 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/index.ts @@ -11,8 +11,6 @@ import { Spaces } from '../scenarios'; // eslint-disable-next-line import/no-default-export export default function alertingApiIntegrationTests({ loadTestFile }: FtrProviderContext) { describe('alerting api integration spaces only', function () { - this.tags('ciGroup12'); - loadTestFile(require.resolve('./actions')); loadTestFile(require.resolve('./alerting')); loadTestFile(require.resolve('./action_task_params')); diff --git a/x-pack/test/alerting_api_integration/spaces_only_legacy/tests/index.ts b/x-pack/test/alerting_api_integration/spaces_only_legacy/tests/index.ts index bb581a7f61cdb..757f2793b239f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only_legacy/tests/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only_legacy/tests/index.ts @@ -11,8 +11,6 @@ import { Spaces } from '../scenarios'; // eslint-disable-next-line import/no-default-export export default function alertingApiIntegrationTests({ loadTestFile }: FtrProviderContext) { describe('alerting api integration spaces only legacy configuration', function () { - this.tags('ciGroup12'); - loadTestFile(require.resolve('./actions/builtin_action_types/webhook')); }); } diff --git a/x-pack/test/api_integration/apis/index.ts b/x-pack/test/api_integration/apis/index.ts index ec964f97922ad..645cc81560682 100644 --- a/x-pack/test/api_integration/apis/index.ts +++ b/x-pack/test/api_integration/apis/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('apis', function () { - this.tags('ciGroup18'); - loadTestFile(require.resolve('./search')); loadTestFile(require.resolve('./es')); loadTestFile(require.resolve('./security')); diff --git a/x-pack/test/api_integration/apis/security/index.ts b/x-pack/test/api_integration/apis/security/index.ts index eb81d8245dbff..b595894f157fc 100644 --- a/x-pack/test/api_integration/apis/security/index.ts +++ b/x-pack/test/api_integration/apis/security/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security', function () { - this.tags('ciGroup18'); - // Updates here should be mirrored in `./security_basic.ts` if tests // should also run under a basic license. diff --git a/x-pack/test/api_integration/apis/security/security_basic.ts b/x-pack/test/api_integration/apis/security/security_basic.ts index 3dcb347126a97..1e7d8ed1ad4b2 100644 --- a/x-pack/test/api_integration/apis/security/security_basic.ts +++ b/x-pack/test/api_integration/apis/security/security_basic.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security (basic license)', function () { - this.tags('ciGroup6'); - // Updates here should be mirrored in `./index.js` if tests // should also run under a trial/platinum license. diff --git a/x-pack/test/api_integration/apis/security/security_trial.ts b/x-pack/test/api_integration/apis/security/security_trial.ts index be4ad252d408f..3786240b4e433 100644 --- a/x-pack/test/api_integration/apis/security/security_trial.ts +++ b/x-pack/test/api_integration/apis/security/security_trial.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security (trial license)', function () { - this.tags('ciGroup6'); - // THIS TEST NEEDS TO BE LAST. IT IS DESTRUCTIVE! IT REMOVES TRIAL LICENSE!!! loadTestFile(require.resolve('./license_downgrade')); }); diff --git a/x-pack/test/api_integration/apis/spaces/index.ts b/x-pack/test/api_integration/apis/spaces/index.ts index 3ca0040e39ec9..1ec1faac535ce 100644 --- a/x-pack/test/api_integration/apis/spaces/index.ts +++ b/x-pack/test/api_integration/apis/spaces/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('spaces', function () { - this.tags('ciGroup18'); - loadTestFile(require.resolve('./get_active_space')); loadTestFile(require.resolve('./saved_objects')); loadTestFile(require.resolve('./space_attributes')); diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index 4e47947aa29dc..8cc5fb6f57d42 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -10,7 +10,7 @@ import { services } from './services'; export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProviderContext) { const xPackFunctionalTestsConfig = await readConfigFile( - require.resolve('../functional/config.js') + require.resolve('../functional/config.base.js') ); return { diff --git a/x-pack/test/api_integration_basic/apis/index.ts b/x-pack/test/api_integration_basic/apis/index.ts index 9490d4c277675..31176c55ac3ca 100644 --- a/x-pack/test/api_integration_basic/apis/index.ts +++ b/x-pack/test/api_integration_basic/apis/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('apis', function () { - this.tags('ciGroup11'); - loadTestFile(require.resolve('./transform')); loadTestFile(require.resolve('./security_solution')); }); diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts index 59764cf021c4a..e1312f589862c 100644 --- a/x-pack/test/apm_api_integration/tests/index.ts +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -14,8 +14,6 @@ export default function apmApiIntegrationTests({ getService, loadTestFile }: Ftr const registry = getService('registry'); describe('APM API tests', function () { - this.tags('ciGroup1'); - const tests = glob.sync('**/*.spec.ts', { cwd }); tests.forEach((test) => { describe(test, function () { diff --git a/x-pack/test/banners_functional/config.ts b/x-pack/test/banners_functional/config.ts index 03f91dfbc34e2..83d0c4656572c 100644 --- a/x-pack/test/banners_functional/config.ts +++ b/x-pack/test/banners_functional/config.ts @@ -9,7 +9,9 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { services, pageObjects } from './ftr_provider_context'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const kibanaFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const kibanaFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); return { testFiles: [require.resolve('./tests')], diff --git a/x-pack/test/banners_functional/tests/index.ts b/x-pack/test/banners_functional/tests/index.ts index 301c872c746e1..8a26cb66ad569 100644 --- a/x-pack/test/banners_functional/tests/index.ts +++ b/x-pack/test/banners_functional/tests/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('banners - functional tests', function () { - this.tags('ciGroup2'); - loadTestFile(require.resolve('./global')); loadTestFile(require.resolve('./spaces')); }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/basic/index.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/basic/index.ts index b618cf5b4df68..714d7e0c6b219 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/basic/index.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/basic/index.ts @@ -11,9 +11,6 @@ import { createSpacesAndUsers, deleteSpacesAndUsers } from '../../../common/lib/ // eslint-disable-next-line import/no-default-export export default ({ loadTestFile, getService }: FtrProviderContext): void => { describe('cases security and spaces enabled: basic', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup27'); - before(async () => { await createSpacesAndUsers(getService); }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts index 3c1ee84296270..e768c92d8c8af 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts @@ -19,23 +19,15 @@ export default ({ loadTestFile, getService }: FtrProviderContext): void => { await deleteSpacesAndUsers(getService); }); - describe('', function () { - this.tags('ciGroup13'); + // Trial + loadTestFile(require.resolve('./cases/push_case')); + loadTestFile(require.resolve('./cases/user_actions/get_all_user_actions')); + loadTestFile(require.resolve('./configure')); - // Trial - loadTestFile(require.resolve('./cases/push_case')); - loadTestFile(require.resolve('./cases/user_actions/get_all_user_actions')); - loadTestFile(require.resolve('./configure')); - }); - - describe('', function () { - this.tags('ciGroup25'); + // Common + loadTestFile(require.resolve('../common')); - // Common - loadTestFile(require.resolve('../common')); - - // NOTE: These need to be at the end because they could delete the .kibana index and inadvertently remove the users and spaces - loadTestFile(require.resolve('../common/migrations')); - }); + // NOTE: These need to be at the end because they could delete the .kibana index and inadvertently remove the users and spaces + loadTestFile(require.resolve('../common/migrations')); }); }; diff --git a/x-pack/test/cases_api_integration/spaces_only/tests/trial/index.ts b/x-pack/test/cases_api_integration/spaces_only/tests/trial/index.ts index 346640aa6b9de..cbf0f010048ef 100644 --- a/x-pack/test/cases_api_integration/spaces_only/tests/trial/index.ts +++ b/x-pack/test/cases_api_integration/spaces_only/tests/trial/index.ts @@ -11,9 +11,6 @@ import { createSpaces, deleteSpaces } from '../../../common/lib/authentication'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile, getService }: FtrProviderContext): void => { describe('cases spaces only enabled: trial', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup5'); - before(async () => { await createSpaces(getService); }); diff --git a/x-pack/test/cloud_integration/config.ts b/x-pack/test/cloud_integration/config.ts index 102d276b34584..0074565875845 100644 --- a/x-pack/test/cloud_integration/config.ts +++ b/x-pack/test/cloud_integration/config.ts @@ -25,7 +25,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); const kibanaPort = kibanaFunctionalConfig.get('servers.kibana.port'); diff --git a/x-pack/test/detection_engine_api_integration/basic/config.ts b/x-pack/test/detection_engine_api_integration/basic/config.ts index 0c5c7d1649f84..26fdc62e0ec52 100644 --- a/x-pack/test/detection_engine_api_integration/basic/config.ts +++ b/x-pack/test/detection_engine_api_integration/basic/config.ts @@ -8,7 +8,10 @@ import { createTestConfig } from '../common/config'; // eslint-disable-next-line import/no-default-export -export default createTestConfig('basic', { - license: 'basic', - ssl: true, -}); +export default createTestConfig( + { + license: 'basic', + ssl: true, + }, + [require.resolve('./tests')] +); diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/index.ts b/x-pack/test/detection_engine_api_integration/basic/tests/index.ts index 1a5ea8de935b4..349d33c89fdf3 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/index.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/index.ts @@ -10,8 +10,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { describe('detection engine api basic license', function () { - this.tags('ciGroup1'); - loadTestFile(require.resolve('./add_prepackaged_rules')); loadTestFile(require.resolve('./create_rules')); loadTestFile(require.resolve('./create_rules_bulk')); diff --git a/x-pack/test/detection_engine_api_integration/common/config.ts b/x-pack/test/detection_engine_api_integration/common/config.ts index 96a83d2c3a427..a95cb937d4cd9 100644 --- a/x-pack/test/detection_engine_api_integration/common/config.ts +++ b/x-pack/test/detection_engine_api_integration/common/config.ts @@ -31,7 +31,7 @@ const enabledActionTypes = [ 'test.rate-limit', ]; -export function createTestConfig(name: string, options: CreateTestConfigOptions) { +export function createTestConfig(options: CreateTestConfigOptions, testFiles?: string[]) { const { license = 'trial', ssl = false } = options; return async ({ readConfigFile }: FtrConfigProviderContext) => { @@ -47,7 +47,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) }; return { - testFiles: [require.resolve(`../${name}/tests/`)], + testFiles, servers, services, junit: { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/README.md b/x-pack/test/detection_engine_api_integration/security_and_spaces/README.md new file mode 100644 index 0000000000000..ca10827803c65 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/README.md @@ -0,0 +1,33 @@ +# What are all these groups? + +These tests take a while so they have been broken up into groups with their own `config.ts` and `index.ts` file, causing each of these groups to be independent bundles of tests which can be run on some worker in CI without taking an incredible amount of time. + +Want to change the groups to something more logical? Have fun! Just make sure that each group executes on CI in less than 10 minutes or so. We don't currently have any mechanism for validating this right now, you just need to look at the times in the log output on CI, but we'll be working on tooling for making this information more accessible soon. + +- Kibana Operations + +# Rule Exception List Tests + +These tests are currently in group7-9. + +These are tests for rule exception lists where we test each data type + +- date +- double +- float +- integer +- ip +- keyword +- long +- text + +Against the operator types of: + +- "is" +- "is not" +- "is one of" +- "is not one of" +- "exists" +- "does not exist" +- "is in list" +- "is not in list" diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/config.base.ts similarity index 87% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/config.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/config.base.ts index 78203525b887a..ed72e1faa682c 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/config.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/config.base.ts @@ -8,7 +8,7 @@ import { createTestConfig } from '../common/config'; // eslint-disable-next-line import/no-default-export -export default createTestConfig('security_and_spaces', { +export default createTestConfig({ license: 'trial', ssl: true, }); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/add_actions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_actions.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/add_actions.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_actions.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/add_prepackaged_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_prepackaged_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/add_prepackaged_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/add_prepackaged_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/aliases.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/aliases.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/aliases.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/aliases.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/check_privileges.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/check_privileges.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts diff --git a/x-pack/test/functional_embedded/config.firefox.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/config.ts similarity index 54% rename from x-pack/test/functional_embedded/config.firefox.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/config.ts index 49359d37673de..2430b8f2148d9 100644 --- a/x-pack/test/functional_embedded/config.firefox.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/config.ts @@ -7,23 +7,12 @@ import { FtrConfigProviderContext } from '@kbn/test'; +// eslint-disable-next-line import/no-default-export export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const chromeConfig = await readConfigFile(require.resolve('./config')); + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); return { - ...chromeConfig.getAll(), - - browser: { - type: 'firefox', - acceptInsecureCerts: true, - }, - - suiteTags: { - exclude: ['skipFirefox'], - }, - - junit: { - reportName: 'Firefox Kibana Embedded in iframe with X-Pack Security', - }, + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], }; } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_index.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_index.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_index.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_ml.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_ml.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_ml.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_rules_bulk.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_rules_bulk.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_rules_bulk.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_signals_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_signals_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_threat_matching.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_threat_matching.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/create_threat_matching.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_rules_bulk.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_rules_bulk.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_rules_bulk.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_signals_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/delete_signals_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/export_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/export_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/export_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/export_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/finalize_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/finalize_signals_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/finalize_signals_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/finalize_signals_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/find_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/find_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/find_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/generating_signals.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/generating_signals.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/generating_signals.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_prepackaged_rules_status.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_prepackaged_rules_status.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_prepackaged_rules_status.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_prepackaged_rules_status.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_rule_execution_events.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_rule_execution_events.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_rule_execution_events.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_rule_execution_events.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_signals_migration_status.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_signals_migration_status.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/get_signals_migration_status.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/get_signals_migration_status.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/ignore_fields.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/ignore_fields.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/ignore_fields.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/ignore_fields.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_export_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_export_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_export_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_export_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/import_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/import_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts new file mode 100644 index 0000000000000..f7a96c2f496d8 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 1', function () { + // !!NOTE: For new routes that do any updates on a rule, please ensure that you are including the legacy + // action migration code. We are monitoring legacy action telemetry to clean up once we see their + // existence being near 0. + + loadTestFile(require.resolve('./aliases')); + loadTestFile(require.resolve('./add_actions')); + loadTestFile(require.resolve('./update_actions')); + loadTestFile(require.resolve('./add_prepackaged_rules')); + loadTestFile(require.resolve('./check_privileges')); + loadTestFile(require.resolve('./create_index')); + loadTestFile(require.resolve('./create_rules')); + loadTestFile(require.resolve('./preview_rules')); + loadTestFile(require.resolve('./create_rules_bulk')); + loadTestFile(require.resolve('./create_ml')); + loadTestFile(require.resolve('./create_threat_matching')); + loadTestFile(require.resolve('./delete_rules')); + loadTestFile(require.resolve('./delete_rules_bulk')); + loadTestFile(require.resolve('./export_rules')); + loadTestFile(require.resolve('./find_rules')); + loadTestFile(require.resolve('./generating_signals')); + loadTestFile(require.resolve('./get_prepackaged_rules_status')); + loadTestFile(require.resolve('./get_rule_execution_events')); + loadTestFile(require.resolve('./import_rules')); + loadTestFile(require.resolve('./import_export_rules')); + loadTestFile(require.resolve('./legacy_actions_migrations')); + loadTestFile(require.resolve('./read_rules')); + loadTestFile(require.resolve('./resolve_read_rules')); + loadTestFile(require.resolve('./update_rules')); + loadTestFile(require.resolve('./update_rules_bulk')); + loadTestFile(require.resolve('./patch_rules_bulk')); + loadTestFile(require.resolve('./perform_bulk_action')); + loadTestFile(require.resolve('./patch_rules')); + loadTestFile(require.resolve('./read_privileges')); + loadTestFile(require.resolve('./open_close_signals')); + loadTestFile(require.resolve('./get_signals_migration_status')); + loadTestFile(require.resolve('./create_signals_migrations')); + loadTestFile(require.resolve('./finalize_signals_migrations')); + loadTestFile(require.resolve('./delete_signals_migrations')); + loadTestFile(require.resolve('./timestamps')); + loadTestFile(require.resolve('./runtime')); + loadTestFile(require.resolve('./throttle')); + loadTestFile(require.resolve('./ignore_fields')); + loadTestFile(require.resolve('./migrations')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/legacy_actions_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/legacy_actions_migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/legacy_actions_migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/legacy_actions_migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/migrations.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/migrations.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/migrations.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/open_close_signals.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/open_close_signals.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules_bulk.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/patch_rules_bulk.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/patch_rules_bulk.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/perform_bulk_action.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/perform_bulk_action.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/perform_bulk_action.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/perform_bulk_action.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/preview_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/preview_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/preview_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/preview_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_privileges.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_privileges.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_privileges.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_privileges.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/read_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/read_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/resolve_read_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/resolve_read_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/resolve_read_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/resolve_read_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/runtime.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/runtime.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/runtime.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/template_data/execution_events.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/template_data/execution_events.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/template_data/execution_events.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/template_data/execution_events.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/throttle.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/throttle.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/throttle.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/throttle.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/timestamps.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/timestamps.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/timestamps.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/timestamps.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_actions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_actions.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_actions.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_actions.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules_bulk.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/update_rules_bulk.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group1/update_rules_bulk.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group2/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group2/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group2/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_endpoint_exceptions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group2/create_endpoint_exceptions.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_endpoint_exceptions.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group2/create_endpoint_exceptions.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group2/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group2/index.ts new file mode 100644 index 0000000000000..f477b23e801f3 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group2/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 2', function () { + loadTestFile(require.resolve('./create_endpoint_exceptions')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_exceptions.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/create_exceptions.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_exceptions.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group3/create_exceptions.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/index.ts new file mode 100644 index 0000000000000..10d4e9c2d6635 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group3/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 3', function () { + loadTestFile(require.resolve('./create_exceptions')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/index.ts new file mode 100644 index 0000000000000..9394e81017aba --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 4', function () { + loadTestFile(require.resolve('./telemetry')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/README.md b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/README.md similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/README.md rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/README.md diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/index.ts similarity index 51% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/index.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/index.ts index d2050179abd0e..4e180f73dc742 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/index.ts @@ -10,15 +10,12 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { describe('Detection rule type telemetry', function () { - describe('', function () { - this.tags('ciGroup28'); - loadTestFile(require.resolve('./usage_collector/all_types')); - loadTestFile(require.resolve('./usage_collector/detection_rules')); - loadTestFile(require.resolve('./usage_collector/detection_rule_status')); + loadTestFile(require.resolve('./usage_collector/all_types')); + loadTestFile(require.resolve('./usage_collector/detection_rules')); + loadTestFile(require.resolve('./usage_collector/detection_rule_status')); - loadTestFile(require.resolve('./task_based/all_types')); - loadTestFile(require.resolve('./task_based/detection_rules')); - loadTestFile(require.resolve('./task_based/security_lists')); - }); + loadTestFile(require.resolve('./task_based/all_types')); + loadTestFile(require.resolve('./task_based/detection_rules')); + loadTestFile(require.resolve('./task_based/security_lists')); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/task_based/all_types.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/all_types.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/task_based/all_types.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/all_types.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/task_based/detection_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/detection_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/task_based/detection_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/detection_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/task_based/security_lists.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/security_lists.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/task_based/security_lists.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/task_based/security_lists.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/usage_collector/all_types.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/all_types.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/usage_collector/all_types.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/all_types.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/usage_collector/detection_rule_status.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/usage_collector/detection_rule_status.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rule_status.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/usage_collector/detection_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/telemetry/usage_collector/detection_rules.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/index.ts new file mode 100644 index 0000000000000..ac107392d4b5c --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 5', function () { + loadTestFile(require.resolve('./keyword_family')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/README.md b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/README.md similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/README.md rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/README.md diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/const_keyword.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/const_keyword.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/const_keyword.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/const_keyword.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/index.ts similarity index 68% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/index.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/index.ts index 4855524d650ef..1ecb06fbed4e5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/index.ts @@ -10,12 +10,8 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { describe('Detection keyword family data types', function () { - describe('', function () { - this.tags('ciGroup11'); - - loadTestFile(require.resolve('./keyword')); - loadTestFile(require.resolve('./const_keyword')); - loadTestFile(require.resolve('./keyword_mixed_with_const')); - }); + loadTestFile(require.resolve('./keyword')); + loadTestFile(require.resolve('./const_keyword')); + loadTestFile(require.resolve('./keyword_mixed_with_const')); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/keyword.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/keyword.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/keyword_mixed_with_const.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword_mixed_with_const.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/keyword_family/keyword_mixed_with_const.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group5/keyword_family/keyword_mixed_with_const.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/alerts/alerts_compatibility.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group6/alerts/alerts_compatibility.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/alerts/index.ts similarity index 79% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/index.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group6/alerts/index.ts index b06d6cb26e33b..320650a4c79e3 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/alerts/index.ts @@ -10,10 +10,6 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { describe('Detection engine signals/alerts compatibility', function () { - describe('', function () { - this.tags('ciGroup11'); - - loadTestFile(require.resolve('./alerts_compatibility')); - }); + loadTestFile(require.resolve('./alerts_compatibility')); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/index.ts new file mode 100644 index 0000000000000..92c235e95c0e4 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group6/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 6', function () { + loadTestFile(require.resolve('./alerts')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/date.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/date.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/date.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/date.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/double.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/double.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/double.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/double.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/float.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/float.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/float.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/float.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/index.ts new file mode 100644 index 0000000000000..6b2cf915cc51b --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('Detection exceptions data types and operators', function () { + loadTestFile(require.resolve('./date')); + loadTestFile(require.resolve('./double')); + loadTestFile(require.resolve('./float')); + loadTestFile(require.resolve('./integer')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/integer.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/integer.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/integer.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group7/exception_operators_data_types/integer.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/index.ts new file mode 100644 index 0000000000000..96f53c47441ed --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group7/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 7', function () { + loadTestFile(require.resolve('./exception_operators_data_types')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/index.ts new file mode 100644 index 0000000000000..cf87276aac3ae --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('Detection exceptions data types and operators', function () { + loadTestFile(require.resolve('./keyword')); + loadTestFile(require.resolve('./keyword_array')); + loadTestFile(require.resolve('./long')); + loadTestFile(require.resolve('./text')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/keyword.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/keyword.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/keyword.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/keyword.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/keyword_array.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/keyword_array.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/keyword_array.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/keyword_array.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/long.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/long.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/long.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/long.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/text.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/text.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/text.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group8/exception_operators_data_types/text.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/index.ts new file mode 100644 index 0000000000000..7182e411a1332 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group8/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 8', function () { + loadTestFile(require.resolve('./exception_operators_data_types')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/config.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/config.ts new file mode 100644 index 0000000000000..2430b8f2148d9 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/config.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +// eslint-disable-next-line import/no-default-export +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../config.base.ts')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/index.ts new file mode 100644 index 0000000000000..22864980e2653 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('Detection exceptions data types and operators', function () { + loadTestFile(require.resolve('./text_array')); + loadTestFile(require.resolve('./ip')); + loadTestFile(require.resolve('./ip_array')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/ip.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/ip.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/ip.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/ip.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/ip_array.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/ip_array.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/ip_array.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/ip_array.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/text_array.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/text_array.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/text_array.ts rename to x-pack/test/detection_engine_api_integration/security_and_spaces/group9/exception_operators_data_types/text_array.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/index.ts new file mode 100644 index 0000000000000..ad5e427c69df8 --- /dev/null +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group9/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../common/ftr_provider_context'; + +// eslint-disable-next-line import/no-default-export +export default ({ loadTestFile }: FtrProviderContext): void => { + describe('detection engine api security and spaces enabled - Group 9', function () { + loadTestFile(require.resolve('./exception_operators_data_types')); + }); +}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/README.md b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/README.md deleted file mode 100644 index d6beb912d7007..0000000000000 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/README.md +++ /dev/null @@ -1,21 +0,0 @@ -These are tests for rule exception lists where we test each data type -* date -* double -* float -* integer -* ip -* keyword -* long -* text - -Against the operator types of: -* "is" -* "is not" -* "is one of" -* "is not one of" -* "exists" -* "does not exist" -* "is in list" -* "is not in list" - -If you add a test here, ensure you add it to the ./index.ts" file as well \ No newline at end of file diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/index.ts deleted file mode 100644 index ded3df8b6716c..0000000000000 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/exception_operators_data_types/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../../common/ftr_provider_context'; - -// eslint-disable-next-line import/no-default-export -export default ({ loadTestFile }: FtrProviderContext): void => { - describe('Detection exceptions data types and operators', function () { - describe('', function () { - this.tags('ciGroup23'); - - loadTestFile(require.resolve('./date')); - loadTestFile(require.resolve('./double')); - loadTestFile(require.resolve('./float')); - loadTestFile(require.resolve('./integer')); - }); - - describe('', function () { - this.tags('ciGroup24'); - - loadTestFile(require.resolve('./keyword')); - loadTestFile(require.resolve('./keyword_array')); - loadTestFile(require.resolve('./long')); - loadTestFile(require.resolve('./text')); - loadTestFile(require.resolve('./text_array')); - }); - - describe('', function () { - this.tags('ciGroup16'); - - loadTestFile(require.resolve('./ip')); - }); - - describe('', function () { - this.tags('ciGroup21'); - - loadTestFile(require.resolve('./ip_array')); - }); - }); -}; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts deleted file mode 100644 index 9a61569ada3b0..0000000000000 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/index.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../common/ftr_provider_context'; - -// eslint-disable-next-line import/no-default-export -export default ({ loadTestFile }: FtrProviderContext): void => { - describe('detection engine api security and spaces enabled', function () { - describe('', function () { - this.tags('ciGroup11'); - - // !!NOTE: For new routes that do any updates on a rule, please ensure that you are including the legacy - // action migration code. We are monitoring legacy action telemetry to clean up once we see their - // existence being near 0. - loadTestFile(require.resolve('./aliases')); - loadTestFile(require.resolve('./add_actions')); - loadTestFile(require.resolve('./update_actions')); - loadTestFile(require.resolve('./add_prepackaged_rules')); - loadTestFile(require.resolve('./check_privileges')); - loadTestFile(require.resolve('./create_index')); - loadTestFile(require.resolve('./create_rules')); - loadTestFile(require.resolve('./preview_rules')); - loadTestFile(require.resolve('./create_rules_bulk')); - loadTestFile(require.resolve('./create_ml')); - loadTestFile(require.resolve('./create_threat_matching')); - loadTestFile(require.resolve('./delete_rules')); - loadTestFile(require.resolve('./delete_rules_bulk')); - loadTestFile(require.resolve('./export_rules')); - loadTestFile(require.resolve('./find_rules')); - loadTestFile(require.resolve('./generating_signals')); - loadTestFile(require.resolve('./get_prepackaged_rules_status')); - loadTestFile(require.resolve('./get_rule_execution_events')); - loadTestFile(require.resolve('./import_rules')); - loadTestFile(require.resolve('./import_export_rules')); - loadTestFile(require.resolve('./legacy_actions_migrations')); - loadTestFile(require.resolve('./read_rules')); - loadTestFile(require.resolve('./resolve_read_rules')); - loadTestFile(require.resolve('./update_rules')); - loadTestFile(require.resolve('./update_rules_bulk')); - loadTestFile(require.resolve('./patch_rules_bulk')); - loadTestFile(require.resolve('./perform_bulk_action')); - loadTestFile(require.resolve('./patch_rules')); - loadTestFile(require.resolve('./read_privileges')); - loadTestFile(require.resolve('./open_close_signals')); - loadTestFile(require.resolve('./get_signals_migration_status')); - loadTestFile(require.resolve('./create_signals_migrations')); - loadTestFile(require.resolve('./finalize_signals_migrations')); - loadTestFile(require.resolve('./delete_signals_migrations')); - loadTestFile(require.resolve('./timestamps')); - loadTestFile(require.resolve('./runtime')); - loadTestFile(require.resolve('./throttle')); - loadTestFile(require.resolve('./ignore_fields')); - loadTestFile(require.resolve('./migrations')); - }); - - describe('', function () { - this.tags('ciGroup26'); - - loadTestFile(require.resolve('./create_endpoint_exceptions')); - }); - - describe('', function () { - this.tags('ciGroup14'); - - loadTestFile(require.resolve('./create_exceptions')); - }); - - // That split here enable us on using a different ciGroup to run the tests - // listed on ./exception_operators_data_types/index - describe('', function () { - loadTestFile(require.resolve('./exception_operators_data_types')); - }); - - // That split here enable us on using a different ciGroup to run the tests - // listed on ./keyword_family/index - describe('', function () { - loadTestFile(require.resolve('./keyword_family')); - }); - - describe('', function () { - loadTestFile(require.resolve('./alerts')); - }); - - describe('', function () { - loadTestFile(require.resolve('./telemetry')); - }); - }); -}; diff --git a/x-pack/test/encrypted_saved_objects_api_integration/tests/index.ts b/x-pack/test/encrypted_saved_objects_api_integration/tests/index.ts index de87d627ac486..0313187ac09a7 100644 --- a/x-pack/test/encrypted_saved_objects_api_integration/tests/index.ts +++ b/x-pack/test/encrypted_saved_objects_api_integration/tests/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('encryptedSavedObjects', function encryptedSavedObjectsSuite() { - this.tags('ciGroup13'); loadTestFile(require.resolve('./encrypted_saved_objects_api')); loadTestFile(require.resolve('./encrypted_saved_objects_decryption')); }); diff --git a/x-pack/test/endpoint_api_integration_no_ingest/apis/index.ts b/x-pack/test/endpoint_api_integration_no_ingest/apis/index.ts index 1ca035df18fd5..10a4e18f8c133 100644 --- a/x-pack/test/endpoint_api_integration_no_ingest/apis/index.ts +++ b/x-pack/test/endpoint_api_integration_no_ingest/apis/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function endpointAPIIntegrationTests({ loadTestFile }: FtrProviderContext) { // Failing ES snapshot promotion: https://github.com/elastic/kibana/issues/70535 describe.skip('Endpoint plugin', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./metadata')); }); } diff --git a/x-pack/test/examples/config.ts b/x-pack/test/examples/config.ts index 6eb1e86dd0826..16db620e76598 100644 --- a/x-pack/test/examples/config.ts +++ b/x-pack/test/examples/config.ts @@ -12,7 +12,9 @@ import fs from 'fs'; import { KIBANA_ROOT } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); // Find all folders in /examples and /x-pack/examples since we treat all them as plugin folder const examplesFiles = fs.readdirSync(resolve(KIBANA_ROOT, 'examples')); diff --git a/x-pack/test/examples/embedded_lens/index.ts b/x-pack/test/examples/embedded_lens/index.ts index debab4773f9eb..b418e69584a9a 100644 --- a/x-pack/test/examples/embedded_lens/index.ts +++ b/x-pack/test/examples/embedded_lens/index.ts @@ -13,6 +13,8 @@ export default function ({ getService, loadTestFile }: PluginFunctionalProviderC const kibanaServer = getService('kibanaServer'); describe('embedded Lens examples', function () { + this.tags('skipFirefox'); + before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/logstash_functional'); await kibanaServer.importExport.load( @@ -30,10 +32,6 @@ export default function ({ getService, loadTestFile }: PluginFunctionalProviderC ); }); - describe('', function () { - this.tags(['ciGroup4', 'skipFirefox']); - - loadTestFile(require.resolve('./embedded_example')); - }); + loadTestFile(require.resolve('./embedded_example')); }); } diff --git a/x-pack/test/examples/reporting_examples/index.ts b/x-pack/test/examples/reporting_examples/index.ts index e4e5c93e5eee2..2f1b00597a9d8 100644 --- a/x-pack/test/examples/reporting_examples/index.ts +++ b/x-pack/test/examples/reporting_examples/index.ts @@ -10,8 +10,6 @@ import { PluginFunctionalProviderContext } from '../../../../test/plugin_functio // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile }: PluginFunctionalProviderContext) { describe('reporting examples', function () { - this.tags('ciGroup13'); - loadTestFile(require.resolve('./capture_test')); }); } diff --git a/x-pack/test/examples/screenshotting/index.ts b/x-pack/test/examples/screenshotting/index.ts index e9ecd2ecde346..c64d84c7fcf3d 100644 --- a/x-pack/test/examples/screenshotting/index.ts +++ b/x-pack/test/examples/screenshotting/index.ts @@ -22,8 +22,6 @@ export default function ({ // FAILING: https://github.com/elastic/kibana/issues/131190 describe.skip('Screenshotting Example', function () { - this.tags('ciGroup13'); - before(async () => { await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional'); await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/visualize.json'); diff --git a/x-pack/test/examples/search_examples/index.ts b/x-pack/test/examples/search_examples/index.ts index c0f8ab22c8f8f..cee873dfed53a 100644 --- a/x-pack/test/examples/search_examples/index.ts +++ b/x-pack/test/examples/search_examples/index.ts @@ -13,7 +13,6 @@ export default function ({ getService, loadTestFile }: PluginFunctionalProviderC const kibanaServer = getService('kibanaServer'); describe('search examples', function () { - this.tags('ciGroup13'); before(async () => { await esArchiver.emptyKibanaIndex(); await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); diff --git a/x-pack/test/fleet_api_integration/apis/index.js b/x-pack/test/fleet_api_integration/apis/index.js index 9f68eb1c7f81f..1c528e719e2e8 100644 --- a/x-pack/test/fleet_api_integration/apis/index.js +++ b/x-pack/test/fleet_api_integration/apis/index.js @@ -9,8 +9,6 @@ import { setupTestUsers } from './test_users'; export default function ({ loadTestFile, getService }) { describe('Fleet Endpoints', function () { - this.tags('ciGroup29'); - before(async () => { await setupTestUsers(getService('security')); }); diff --git a/x-pack/test/fleet_cypress/config.ts b/x-pack/test/fleet_cypress/config.ts index d2076fa940412..52198f4f035e0 100644 --- a/x-pack/test/fleet_cypress/config.ts +++ b/x-pack/test/fleet_cypress/config.ts @@ -14,7 +14,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('../functional/config.js') + require.resolve('../functional/config.base.js') ); return { diff --git a/x-pack/test/fleet_functional/apps/fleet/agents_page.ts b/x-pack/test/fleet_functional/apps/fleet/agents_page.ts index 515eaa65f5310..cff1273e0b901 100644 --- a/x-pack/test/fleet_functional/apps/fleet/agents_page.ts +++ b/x-pack/test/fleet_functional/apps/fleet/agents_page.ts @@ -11,8 +11,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const { agentsPage } = getPageObjects(['agentsPage']); describe('When in the Fleet application', function () { - this.tags(['ciGroup7']); - describe('and on the agents page', () => { before(async () => { await agentsPage.navigateToAgentsPage(); diff --git a/x-pack/test/fleet_functional/apps/fleet/index.ts b/x-pack/test/fleet_functional/apps/fleet/index.ts index ec16e2d857183..965d4c7776197 100644 --- a/x-pack/test/fleet_functional/apps/fleet/index.ts +++ b/x-pack/test/fleet_functional/apps/fleet/index.ts @@ -11,7 +11,6 @@ export default function (providerContext: FtrProviderContext) { const { loadTestFile } = providerContext; describe('endpoint', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./agents_page')); }); } diff --git a/x-pack/test/fleet_functional/apps/home/index.ts b/x-pack/test/fleet_functional/apps/home/index.ts index cd14bfdff557d..727213b96349e 100644 --- a/x-pack/test/fleet_functional/apps/home/index.ts +++ b/x-pack/test/fleet_functional/apps/home/index.ts @@ -11,7 +11,6 @@ export default function (providerContext: FtrProviderContext) { const { loadTestFile } = providerContext; describe('home onboarding', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./welcome')); }); } diff --git a/x-pack/test/fleet_functional/config.ts b/x-pack/test/fleet_functional/config.ts index 60db783280aec..5efc39b02acd6 100644 --- a/x-pack/test/fleet_functional/config.ts +++ b/x-pack/test/fleet_functional/config.ts @@ -11,7 +11,9 @@ import { pageObjects } from './page_objects'; import { services } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); return { ...xpackFunctionalConfig.getAll(), diff --git a/x-pack/test/functional/apps/advanced_settings/config.ts b/x-pack/test/functional/apps/advanced_settings/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/advanced_settings/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/advanced_settings/index.ts b/x-pack/test/functional/apps/advanced_settings/index.ts index d962f648db395..f121b031466ea 100644 --- a/x-pack/test/functional/apps/advanced_settings/index.ts +++ b/x-pack/test/functional/apps/advanced_settings/index.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function advancedSettingsApp({ loadTestFile }: FtrProviderContext) { describe('Advanced Settings', function canvasAppTestSuite() { - this.tags(['ciGroup2', 'skipFirefox']); // CI requires tags ヽ(゜Q。)ノ? + this.tags(['skipFirefox']); // CI requires tags ヽ(゜Q。)ノ? loadTestFile(require.resolve('./feature_controls/advanced_settings_security')); loadTestFile(require.resolve('./feature_controls/advanced_settings_spaces')); }); diff --git a/x-pack/test/functional/apps/api_keys/config.ts b/x-pack/test/functional/apps/api_keys/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/api_keys/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/api_keys/index.ts b/x-pack/test/functional/apps/api_keys/index.ts index 7b9afd201e3d9..2f9d7206d374a 100644 --- a/x-pack/test/functional/apps/api_keys/index.ts +++ b/x-pack/test/functional/apps/api_keys/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('API Keys app', function () { - this.tags(['ciGroup7']); loadTestFile(require.resolve('./home_page')); loadTestFile(require.resolve('./feature_controls')); }); diff --git a/x-pack/test/functional/apps/apm/config.ts b/x-pack/test/functional/apps/apm/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/apm/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/apm/index.ts b/x-pack/test/functional/apps/apm/index.ts index 20c2bc264a74f..61aca7ca3f9de 100644 --- a/x-pack/test/functional/apps/apm/index.ts +++ b/x-pack/test/functional/apps/apm/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('APM specs', function () { - this.tags('ciGroup10'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./correlations')); }); diff --git a/x-pack/test/functional/apps/canvas/config.ts b/x-pack/test/functional/apps/canvas/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/canvas/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/canvas/index.js b/x-pack/test/functional/apps/canvas/index.js index 784aeb6655768..2c6a46b75e510 100644 --- a/x-pack/test/functional/apps/canvas/index.js +++ b/x-pack/test/functional/apps/canvas/index.js @@ -27,7 +27,6 @@ export default function canvasApp({ loadTestFile, getService }) { await security.testUser.restoreDefaults(); }); - this.tags('ciGroup2'); loadTestFile(require.resolve('./smoke_test')); loadTestFile(require.resolve('./expression')); loadTestFile(require.resolve('./filters')); diff --git a/x-pack/test/functional/apps/cross_cluster_replication/config.ts b/x-pack/test/functional/apps/cross_cluster_replication/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/cross_cluster_replication/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/cross_cluster_replication/index.ts b/x-pack/test/functional/apps/cross_cluster_replication/index.ts index 1ab1ab7183394..5c6539b5e73f7 100644 --- a/x-pack/test/functional/apps/cross_cluster_replication/index.ts +++ b/x-pack/test/functional/apps/cross_cluster_replication/index.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Cross Cluster Replication app', function () { - this.tags(['ciGroup4', 'skipCloud']); + this.tags('skipCloud'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./home_page')); }); diff --git a/x-pack/test/functional/apps/dashboard/README.md b/x-pack/test/functional/apps/dashboard/README.md new file mode 100644 index 0000000000000..5e87a8b210bdd --- /dev/null +++ b/x-pack/test/functional/apps/dashboard/README.md @@ -0,0 +1,7 @@ +# What are all these groups? + +These tests take a while so they have been broken up into groups with their own `config.ts` and `index.ts` file, causing each of these groups to be independent bundles of tests which can be run on some worker in CI without taking an incredible amount of time. + +Want to change the groups to something more logical? Have fun! Just make sure that each group executes on CI in less than 10 minutes or so. We don't currently have any mechanism for validating this right now, you just need to look at the times in the log output on CI, but we'll be working on tooling for making this information more accessible soon. + +- Kibana Operations \ No newline at end of file diff --git a/x-pack/test/functional/apps/dashboard/group1/config.ts b/x-pack/test/functional/apps/dashboard/group1/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/dashboard/group1/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/dashboard/drilldowns/dashboard_to_dashboard_drilldown.ts b/x-pack/test/functional/apps/dashboard/group1/drilldowns/dashboard_to_dashboard_drilldown.ts similarity index 99% rename from x-pack/test/functional/apps/dashboard/drilldowns/dashboard_to_dashboard_drilldown.ts rename to x-pack/test/functional/apps/dashboard/group1/drilldowns/dashboard_to_dashboard_drilldown.ts index 9fd6beeb8ff22..c540d5673d89e 100644 --- a/x-pack/test/functional/apps/dashboard/drilldowns/dashboard_to_dashboard_drilldown.ts +++ b/x-pack/test/functional/apps/dashboard/group1/drilldowns/dashboard_to_dashboard_drilldown.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; const DRILLDOWN_TO_PIE_CHART_NAME = 'Go to pie chart dashboard'; const DRILLDOWN_TO_AREA_CHART_NAME = 'Go to area chart dashboard'; diff --git a/x-pack/test/functional/apps/dashboard/drilldowns/dashboard_to_url_drilldown.ts b/x-pack/test/functional/apps/dashboard/group1/drilldowns/dashboard_to_url_drilldown.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/drilldowns/dashboard_to_url_drilldown.ts rename to x-pack/test/functional/apps/dashboard/group1/drilldowns/dashboard_to_url_drilldown.ts index 5ed118c9b753a..ca057b7421b7c 100644 --- a/x-pack/test/functional/apps/dashboard/drilldowns/dashboard_to_url_drilldown.ts +++ b/x-pack/test/functional/apps/dashboard/group1/drilldowns/dashboard_to_url_drilldown.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; const DRILLDOWN_TO_DISCOVER_URL = 'Go to discover'; diff --git a/x-pack/test/functional/apps/dashboard/drilldowns/explore_data_chart_action.ts b/x-pack/test/functional/apps/dashboard/group1/drilldowns/explore_data_chart_action.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/drilldowns/explore_data_chart_action.ts rename to x-pack/test/functional/apps/dashboard/group1/drilldowns/explore_data_chart_action.ts index b9272a0a6c3bd..2e2c1f7ecca1d 100644 --- a/x-pack/test/functional/apps/dashboard/drilldowns/explore_data_chart_action.ts +++ b/x-pack/test/functional/apps/dashboard/group1/drilldowns/explore_data_chart_action.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; const ACTION_ID = 'ACTION_EXPLORE_DATA_CHART'; const ACTION_TEST_SUBJ = `embeddablePanelAction-${ACTION_ID}`; diff --git a/x-pack/test/functional/apps/dashboard/drilldowns/explore_data_panel_action.ts b/x-pack/test/functional/apps/dashboard/group1/drilldowns/explore_data_panel_action.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/drilldowns/explore_data_panel_action.ts rename to x-pack/test/functional/apps/dashboard/group1/drilldowns/explore_data_panel_action.ts index c78c716364c4b..c302d9a195397 100644 --- a/x-pack/test/functional/apps/dashboard/drilldowns/explore_data_panel_action.ts +++ b/x-pack/test/functional/apps/dashboard/group1/drilldowns/explore_data_panel_action.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; const ACTION_ID = 'ACTION_EXPLORE_DATA'; const ACTION_TEST_SUBJ = `embeddablePanelAction-${ACTION_ID}`; diff --git a/x-pack/test/functional/apps/dashboard/drilldowns/index.ts b/x-pack/test/functional/apps/dashboard/group1/drilldowns/index.ts similarity index 95% rename from x-pack/test/functional/apps/dashboard/drilldowns/index.ts rename to x-pack/test/functional/apps/dashboard/group1/drilldowns/index.ts index fac0c355ce4d0..eaa1189ab1007 100644 --- a/x-pack/test/functional/apps/dashboard/drilldowns/index.ts +++ b/x-pack/test/functional/apps/dashboard/group1/drilldowns/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile, getService }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts b/x-pack/test/functional/apps/dashboard/group1/feature_controls/dashboard_security.ts similarity index 99% rename from x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts rename to x-pack/test/functional/apps/dashboard/group1/feature_controls/dashboard_security.ts index efac6d6739fcb..47a895472d992 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_security.ts +++ b/x-pack/test/functional/apps/dashboard/group1/feature_controls/dashboard_security.ts @@ -10,7 +10,7 @@ import { createDashboardEditUrl, DashboardConstants, } from '@kbn/dashboard-plugin/public/dashboard_constants'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts b/x-pack/test/functional/apps/dashboard/group1/feature_controls/dashboard_spaces.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts rename to x-pack/test/functional/apps/dashboard/group1/feature_controls/dashboard_spaces.ts index 0d177a0f3c65b..24a90b883315e 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/dashboard_spaces.ts +++ b/x-pack/test/functional/apps/dashboard/group1/feature_controls/dashboard_spaces.ts @@ -10,7 +10,7 @@ import { createDashboardEditUrl, DashboardConstants, } from '@kbn/dashboard-plugin/public/dashboard_constants'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/index.ts b/x-pack/test/functional/apps/dashboard/group1/feature_controls/index.ts similarity index 89% rename from x-pack/test/functional/apps/dashboard/feature_controls/index.ts rename to x-pack/test/functional/apps/dashboard/group1/feature_controls/index.ts index 3b32ea031f6e2..2ea15966f3740 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/index.ts +++ b/x-pack/test/functional/apps/dashboard/group1/feature_controls/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('feature controls', function () { diff --git a/x-pack/test/functional/apps/dashboard/feature_controls/time_to_visualize_security.ts b/x-pack/test/functional/apps/dashboard/group1/feature_controls/time_to_visualize_security.ts similarity index 99% rename from x-pack/test/functional/apps/dashboard/feature_controls/time_to_visualize_security.ts rename to x-pack/test/functional/apps/dashboard/group1/feature_controls/time_to_visualize_security.ts index 9eeb49f5eb0d2..57ddc76835213 100644 --- a/x-pack/test/functional/apps/dashboard/feature_controls/time_to_visualize_security.ts +++ b/x-pack/test/functional/apps/dashboard/group1/feature_controls/time_to_visualize_security.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/x-pack/test/functional/apps/dashboard/group1/index.ts b/x-pack/test/functional/apps/dashboard/group1/index.ts new file mode 100644 index 0000000000000..f829002448f33 --- /dev/null +++ b/x-pack/test/functional/apps/dashboard/group1/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('dashboard', function () { + loadTestFile(require.resolve('./feature_controls')); + loadTestFile(require.resolve('./preserve_url')); + loadTestFile(require.resolve('./reporting')); + loadTestFile(require.resolve('./drilldowns')); + }); +} diff --git a/x-pack/test/functional/apps/dashboard/preserve_url.ts b/x-pack/test/functional/apps/dashboard/group1/preserve_url.ts similarity index 97% rename from x-pack/test/functional/apps/dashboard/preserve_url.ts rename to x-pack/test/functional/apps/dashboard/group1/preserve_url.ts index e391a8b346f6f..88ad055d34c20 100644 --- a/x-pack/test/functional/apps/dashboard/preserve_url.ts +++ b/x-pack/test/functional/apps/dashboard/group1/preserve_url.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/reporting/README.md b/x-pack/test/functional/apps/dashboard/group1/reporting/README.md similarity index 92% rename from x-pack/test/functional/apps/dashboard/reporting/README.md rename to x-pack/test/functional/apps/dashboard/group1/reporting/README.md index 3a2b8f5cc783f..149b691dc3115 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/README.md +++ b/x-pack/test/functional/apps/dashboard/group1/reporting/README.md @@ -11,8 +11,8 @@ Every now and then visual changes will be made that will require the snapshots t 1. **Load the ES Archive containing the dashboard and data.** This will load the test data into an Elasticsearch instance running via the functional test server: ``` - node scripts/es_archiver load reporting/ecommerce --config=x-pack/test/functional/config.js - node scripts/es_archiver load reporting/ecommerce_kibana --config=x-pack/test/functional/config.js + node scripts/es_archiver load reporting/ecommerce --config=x-pack/test/functional/apps/dashboard/config.ts + node scripts/es_archiver load reporting/ecommerce_kibana --config=x-pack/test/functional/apps/dashboard/config.ts ``` 2. **Generate the reports of the E-commerce dashboard in the Kibana UI.** Navigate to `http://localhost:5620`, find the archived dashboard, and generate all the types of reports for which there are stored baseline images. diff --git a/x-pack/test/functional/apps/dashboard/reporting/__snapshots__/download_csv.snap b/x-pack/test/functional/apps/dashboard/group1/reporting/__snapshots__/download_csv.snap similarity index 99% rename from x-pack/test/functional/apps/dashboard/reporting/__snapshots__/download_csv.snap rename to x-pack/test/functional/apps/dashboard/group1/reporting/__snapshots__/download_csv.snap index d524543183a3f..e6b31be13861d 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/__snapshots__/download_csv.snap +++ b/x-pack/test/functional/apps/dashboard/group1/reporting/__snapshots__/download_csv.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`dashboard Reporting Download CSV Default Saved Search Data Download CSV export of a saved search panel 1`] = ` +exports[`dashboard Reporting Download CSV Default Saved Search Data Download CSV export of a saved search panel 1`] = ` "\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku \\"Jun 22, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,23,564670,6,\\"Dec 11, 2016 @ 00:00:00.000, Dec 11, 2016 @ 00:00:00.000\\",\\"ZO0531205312, ZO0684706847\\" \\"Jun 22, 2019 @ 00:00:00.000\\",\\"Women's Clothing\\",EUR,44,564710,6,\\"Dec 11, 2016 @ 00:00:00.000, Dec 11, 2016 @ 00:00:00.000\\",\\"ZO0263402634, ZO0499404994\\" @@ -460,7 +460,7 @@ exports[`dashboard Reporting Download CSV Default Saved Search Data Download CS " `; -exports[`dashboard Reporting Download CSV Default Saved Search Data Downloads a filtered CSV export of a saved search panel 1`] = ` +exports[`dashboard Reporting Download CSV Default Saved Search Data Downloads a filtered CSV export of a saved search panel 1`] = ` "\\"order_date\\",category,currency,\\"customer_id\\",\\"order_id\\",\\"day_of_week_i\\",\\"products.created_on\\",sku \\"Jun 22, 2019 @ 00:00:00.000\\",\\"Men's Clothing, Men's Shoes\\",EUR,23,564670,6,\\"Dec 11, 2016 @ 00:00:00.000, Dec 11, 2016 @ 00:00:00.000\\",\\"ZO0531205312, ZO0684706847\\" \\"Jun 22, 2019 @ 00:00:00.000\\",\\"Men's Shoes, Men's Clothing\\",EUR,52,564513,6,\\"Dec 11, 2016 @ 00:00:00.000, Dec 11, 2016 @ 00:00:00.000\\",\\"ZO0390003900, ZO0287902879\\" @@ -562,13 +562,13 @@ exports[`dashboard Reporting Download CSV Default Saved Search Data Downloads a " `; -exports[`dashboard Reporting Download CSV Field Formatters and Scripted Fields Download CSV export of a saved search panel 1`] = ` +exports[`dashboard Reporting Download CSV Field Formatters and Scripted Fields Download CSV export of a saved search panel 1`] = ` "date,\\"_id\\",name,gender,value,year,\\"years_ago\\",\\"date_informal\\" \\"Jan 1, 1982 @ 00:00:00.000\\",\\"1982-Fethany-F\\",Fethany,F,780,1982,\\"37.00000000000000000000\\",\\"Jan 1st 82\\" " `; -exports[`dashboard Reporting Download CSV Filtered Saved Search Downloads filtered Discover saved search report 1`] = ` +exports[`dashboard Reporting Download CSV Filtered Saved Search Downloads filtered Discover saved search report 1`] = ` "\\"order_date\\",category,\\"customer_full_name\\",\\"taxful_total_price\\",currency \\"Jun 25, 2019 @ 00:00:00.000\\",\\"Women's Accessories\\",\\"Betty Reese\\",\\"22.984\\",EUR \\"Jun 25, 2019 @ 00:00:00.000\\",\\"Women's Accessories, Women's Clothing\\",\\"Betty Brewer\\",\\"28.984\\",EUR diff --git a/x-pack/test/functional/apps/dashboard/reporting/download_csv.ts b/x-pack/test/functional/apps/dashboard/group1/reporting/download_csv.ts similarity index 99% rename from x-pack/test/functional/apps/dashboard/reporting/download_csv.ts rename to x-pack/test/functional/apps/dashboard/group1/reporting/download_csv.ts index 1e2d465fee66b..bdcf95955b451 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/download_csv.ts +++ b/x-pack/test/functional/apps/dashboard/group1/reporting/download_csv.ts @@ -9,7 +9,7 @@ import { REPO_ROOT } from '@kbn/utils'; import expect from '@kbn/expect'; import fs from 'fs'; import path from 'path'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/reporting/index.ts b/x-pack/test/functional/apps/dashboard/group1/reporting/index.ts similarity index 86% rename from x-pack/test/functional/apps/dashboard/reporting/index.ts rename to x-pack/test/functional/apps/dashboard/group1/reporting/index.ts index 088e54d534b6a..ef9821a544b3a 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/index.ts +++ b/x-pack/test/functional/apps/dashboard/group1/reporting/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Reporting', function () { diff --git a/x-pack/test/functional/apps/dashboard/reporting/reports/baseline/large_dashboard_preserve_layout.png b/x-pack/test/functional/apps/dashboard/group1/reporting/reports/baseline/large_dashboard_preserve_layout.png similarity index 100% rename from x-pack/test/functional/apps/dashboard/reporting/reports/baseline/large_dashboard_preserve_layout.png rename to x-pack/test/functional/apps/dashboard/group1/reporting/reports/baseline/large_dashboard_preserve_layout.png diff --git a/x-pack/test/functional/apps/dashboard/reporting/reports/baseline/small_dashboard_preserve_layout.png b/x-pack/test/functional/apps/dashboard/group1/reporting/reports/baseline/small_dashboard_preserve_layout.png similarity index 100% rename from x-pack/test/functional/apps/dashboard/reporting/reports/baseline/small_dashboard_preserve_layout.png rename to x-pack/test/functional/apps/dashboard/group1/reporting/reports/baseline/small_dashboard_preserve_layout.png diff --git a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/group1/reporting/screenshots.ts similarity index 99% rename from x-pack/test/functional/apps/dashboard/reporting/screenshots.ts rename to x-pack/test/functional/apps/dashboard/group1/reporting/screenshots.ts index d42d23b7578a5..5a69262801d2e 100644 --- a/x-pack/test/functional/apps/dashboard/reporting/screenshots.ts +++ b/x-pack/test/functional/apps/dashboard/group1/reporting/screenshots.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import path from 'path'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; const REPORTS_FOLDER = path.resolve(__dirname, 'reports'); diff --git a/x-pack/test/functional/apps/dashboard/_async_dashboard.ts b/x-pack/test/functional/apps/dashboard/group2/_async_dashboard.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/_async_dashboard.ts rename to x-pack/test/functional/apps/dashboard/group2/_async_dashboard.ts index 89c58645b64b0..ae79c1893ac8b 100644 --- a/x-pack/test/functional/apps/dashboard/_async_dashboard.ts +++ b/x-pack/test/functional/apps/dashboard/group2/_async_dashboard.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { UI_SETTINGS } from '@kbn/data-plugin/common'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/x-pack/test/functional/apps/dashboard/group2/config.ts b/x-pack/test/functional/apps/dashboard/group2/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/dashboard/group2/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/dashboard/dashboard_lens_by_value.ts b/x-pack/test/functional/apps/dashboard/group2/dashboard_lens_by_value.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/dashboard_lens_by_value.ts rename to x-pack/test/functional/apps/dashboard/group2/dashboard_lens_by_value.ts index 9e4c2554100b9..2604b942f7313 100644 --- a/x-pack/test/functional/apps/dashboard/dashboard_lens_by_value.ts +++ b/x-pack/test/functional/apps/dashboard/group2/dashboard_lens_by_value.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'visualize', 'lens', 'timePicker']); diff --git a/x-pack/test/functional/apps/dashboard/dashboard_maps_by_value.ts b/x-pack/test/functional/apps/dashboard/group2/dashboard_maps_by_value.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/dashboard_maps_by_value.ts rename to x-pack/test/functional/apps/dashboard/group2/dashboard_maps_by_value.ts index e885d1c0d3f73..c1224b604364d 100644 --- a/x-pack/test/functional/apps/dashboard/dashboard_maps_by_value.ts +++ b/x-pack/test/functional/apps/dashboard/group2/dashboard_maps_by_value.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/x-pack/test/functional/apps/dashboard/dashboard_tagging.ts b/x-pack/test/functional/apps/dashboard/group2/dashboard_tagging.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/dashboard_tagging.ts rename to x-pack/test/functional/apps/dashboard/group2/dashboard_tagging.ts index 784d1f3678415..ca0093135b7da 100644 --- a/x-pack/test/functional/apps/dashboard/dashboard_tagging.ts +++ b/x-pack/test/functional/apps/dashboard/group2/dashboard_tagging.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const listingTable = getService('listingTable'); diff --git a/x-pack/test/functional/apps/dashboard/group2/index.ts b/x-pack/test/functional/apps/dashboard/group2/index.ts new file mode 100644 index 0000000000000..666756735e80f --- /dev/null +++ b/x-pack/test/functional/apps/dashboard/group2/index.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('dashboard', function () { + loadTestFile(require.resolve('./sync_colors')); + loadTestFile(require.resolve('./_async_dashboard')); + loadTestFile(require.resolve('./dashboard_tagging')); + loadTestFile(require.resolve('./dashboard_lens_by_value')); + loadTestFile(require.resolve('./dashboard_maps_by_value')); + loadTestFile(require.resolve('./panel_titles')); + + loadTestFile(require.resolve('./migration_smoke_tests/lens_migration_smoke_test')); + loadTestFile(require.resolve('./migration_smoke_tests/controls_migration_smoke_test')); + loadTestFile(require.resolve('./migration_smoke_tests/visualize_migration_smoke_test')); + loadTestFile(require.resolve('./migration_smoke_tests/tsvb_migration_smoke_test')); + }); +} diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/controls_migration_smoke_test.ts b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/controls_migration_smoke_test.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/controls_migration_smoke_test.ts rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/controls_migration_smoke_test.ts index b87ee15910d23..20fe8a9413723 100644 --- a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/controls_migration_smoke_test.ts +++ b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/controls_migration_smoke_test.ts @@ -12,7 +12,7 @@ import expect from '@kbn/expect'; import path from 'path'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const retry = getService('retry'); diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/controls_dashboard_migration_test_8_0_0.ndjson b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/controls_dashboard_migration_test_8_0_0.ndjson similarity index 100% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/controls_dashboard_migration_test_8_0_0.ndjson rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/controls_dashboard_migration_test_8_0_0.ndjson diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/lens_dashboard_migration_test_7_12_1.ndjson b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/lens_dashboard_migration_test_7_12_1.ndjson similarity index 100% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/lens_dashboard_migration_test_7_12_1.ndjson rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/lens_dashboard_migration_test_7_12_1.ndjson diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_12_1.ndjson b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_12_1.ndjson similarity index 100% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_12_1.ndjson rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_12_1.ndjson diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_13_3.ndjson b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_13_3.ndjson similarity index 100% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_13_3.ndjson rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/tsvb_dashboard_migration_test_7_13_3.ndjson diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/visualize_dashboard_migration_test_7_12_1.ndjson b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/visualize_dashboard_migration_test_7_12_1.ndjson similarity index 100% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/exports/visualize_dashboard_migration_test_7_12_1.ndjson rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/exports/visualize_dashboard_migration_test_7_12_1.ndjson diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/lens_migration_smoke_test.ts b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/lens_migration_smoke_test.ts similarity index 97% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/lens_migration_smoke_test.ts rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/lens_migration_smoke_test.ts index 78b7ccfe7df08..32c6449ad97b5 100644 --- a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/lens_migration_smoke_test.ts +++ b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/lens_migration_smoke_test.ts @@ -11,7 +11,7 @@ import expect from '@kbn/expect'; import path from 'path'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/tsvb_migration_smoke_test.ts b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/tsvb_migration_smoke_test.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/tsvb_migration_smoke_test.ts rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/tsvb_migration_smoke_test.ts index 22606cf6d2862..0c3f9c652a6ec 100644 --- a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/tsvb_migration_smoke_test.ts +++ b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/tsvb_migration_smoke_test.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import path from 'path'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/visualize_migration_smoke_test.ts b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/visualize_migration_smoke_test.ts similarity index 97% rename from x-pack/test/functional/apps/dashboard/migration_smoke_tests/visualize_migration_smoke_test.ts rename to x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/visualize_migration_smoke_test.ts index d3d6ca46cd227..f4e86217a4d75 100644 --- a/x-pack/test/functional/apps/dashboard/migration_smoke_tests/visualize_migration_smoke_test.ts +++ b/x-pack/test/functional/apps/dashboard/group2/migration_smoke_tests/visualize_migration_smoke_test.ts @@ -11,7 +11,7 @@ import expect from '@kbn/expect'; import path from 'path'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/panel_titles.ts b/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts similarity index 99% rename from x-pack/test/functional/apps/dashboard/panel_titles.ts rename to x-pack/test/functional/apps/dashboard/group2/panel_titles.ts index 3db72ba8d0a90..34b7e14d26a1a 100644 --- a/x-pack/test/functional/apps/dashboard/panel_titles.ts +++ b/x-pack/test/functional/apps/dashboard/group2/panel_titles.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/sync_colors.ts b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts similarity index 98% rename from x-pack/test/functional/apps/dashboard/sync_colors.ts rename to x-pack/test/functional/apps/dashboard/group2/sync_colors.ts index a3628635dfa2f..093318bb8b5cd 100644 --- a/x-pack/test/functional/apps/dashboard/sync_colors.ts +++ b/x-pack/test/functional/apps/dashboard/group2/sync_colors.ts @@ -7,7 +7,7 @@ import { DebugState } from '@elastic/charts'; import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/dashboard/index.ts b/x-pack/test/functional/apps/dashboard/index.ts deleted file mode 100644 index baf37ff56bd80..0000000000000 --- a/x-pack/test/functional/apps/dashboard/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ loadTestFile }: FtrProviderContext) { - describe('dashboard', function () { - describe('', function () { - this.tags('ciGroup19'); - loadTestFile(require.resolve('./feature_controls')); - loadTestFile(require.resolve('./preserve_url')); - loadTestFile(require.resolve('./reporting')); - loadTestFile(require.resolve('./drilldowns')); - }); - - describe('', function () { - this.tags('ciGroup31'); - loadTestFile(require.resolve('./sync_colors')); - loadTestFile(require.resolve('./_async_dashboard')); - loadTestFile(require.resolve('./dashboard_tagging')); - loadTestFile(require.resolve('./dashboard_lens_by_value')); - loadTestFile(require.resolve('./dashboard_maps_by_value')); - loadTestFile(require.resolve('./panel_titles')); - - loadTestFile(require.resolve('./migration_smoke_tests/lens_migration_smoke_test')); - loadTestFile(require.resolve('./migration_smoke_tests/controls_migration_smoke_test')); - loadTestFile(require.resolve('./migration_smoke_tests/visualize_migration_smoke_test')); - loadTestFile(require.resolve('./migration_smoke_tests/tsvb_migration_smoke_test')); - }); - }); -} diff --git a/x-pack/test/functional/apps/data_views/config.ts b/x-pack/test/functional/apps/data_views/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/data_views/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/data_views/index.ts b/x-pack/test/functional/apps/data_views/index.ts index 3b3f7b3608113..3284dc901c25a 100644 --- a/x-pack/test/functional/apps/data_views/index.ts +++ b/x-pack/test/functional/apps/data_views/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function advancedSettingsApp({ loadTestFile }: FtrProviderContext) { describe('Data Views', function indexPatternsTestSuite() { - this.tags('ciGroup2'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./spaces')); }); diff --git a/x-pack/test/functional/apps/dev_tools/config.ts b/x-pack/test/functional/apps/dev_tools/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/dev_tools/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/dev_tools/index.ts b/x-pack/test/functional/apps/dev_tools/index.ts index 4f0e9290cc25e..6ef1688bb4c4e 100644 --- a/x-pack/test/functional/apps/dev_tools/index.ts +++ b/x-pack/test/functional/apps/dev_tools/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Dev Tools', function () { - this.tags('ciGroup13'); - loadTestFile(require.resolve('./breadcrumbs')); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./searchprofiler_editor')); diff --git a/x-pack/test/functional/apps/discover/config.ts b/x-pack/test/functional/apps/discover/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/discover/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/discover/index.ts b/x-pack/test/functional/apps/discover/index.ts index 9eda11bc6e6fb..bb5ac2f8ea9d4 100644 --- a/x-pack/test/functional/apps/discover/index.ts +++ b/x-pack/test/functional/apps/discover/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('discover', function () { - this.tags('ciGroup25'); - loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./preserve_url')); loadTestFile(require.resolve('./async_scripted_fields')); diff --git a/x-pack/test/functional/apps/graph/config.ts b/x-pack/test/functional/apps/graph/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/graph/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/graph/index.ts b/x-pack/test/functional/apps/graph/index.ts index 561cf8e5833d4..ca0b02e8b0f7d 100644 --- a/x-pack/test/functional/apps/graph/index.ts +++ b/x-pack/test/functional/apps/graph/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('graph app', function () { - this.tags('ciGroup12'); - loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./graph')); }); diff --git a/x-pack/test/functional/apps/grok_debugger/config.ts b/x-pack/test/functional/apps/grok_debugger/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/grok_debugger/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/grok_debugger/index.ts b/x-pack/test/functional/apps/grok_debugger/index.ts index 1fed41f6e3e36..7b0bd70508b6f 100644 --- a/x-pack/test/functional/apps/grok_debugger/index.ts +++ b/x-pack/test/functional/apps/grok_debugger/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Grok Debugger App', function () { - this.tags('ciGroup13'); loadTestFile(require.resolve('./home_page')); }); }; diff --git a/x-pack/test/functional/apps/home/config.ts b/x-pack/test/functional/apps/home/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/home/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/home/index.ts b/x-pack/test/functional/apps/home/index.ts index c7579efff03a4..fd2c5b3b752c8 100644 --- a/x-pack/test/functional/apps/home/index.ts +++ b/x-pack/test/functional/apps/home/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Home page', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./feature_controls')); }); }; diff --git a/x-pack/test/functional/apps/index_lifecycle_management/config.ts b/x-pack/test/functional/apps/index_lifecycle_management/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/index_lifecycle_management/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts b/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts index d362b84ee479a..71056c2d836fc 100644 --- a/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts +++ b/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts @@ -29,7 +29,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { body: { type: 'fs', settings: { - // use one of the values defined in path.repo in test/functional/config.js + // use one of the values defined in path.repo in test/functional/config.base.js location: '/tmp/', }, }, diff --git a/x-pack/test/functional/apps/index_lifecycle_management/index.ts b/x-pack/test/functional/apps/index_lifecycle_management/index.ts index cf83939c942d9..38b5803bd77ef 100644 --- a/x-pack/test/functional/apps/index_lifecycle_management/index.ts +++ b/x-pack/test/functional/apps/index_lifecycle_management/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Index Lifecycle Management app', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./home_page')); }); diff --git a/x-pack/test/functional/apps/index_management/config.ts b/x-pack/test/functional/apps/index_management/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/index_management/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/index_management/index.ts b/x-pack/test/functional/apps/index_management/index.ts index 81bd94769db62..83da8cc4bba89 100644 --- a/x-pack/test/functional/apps/index_management/index.ts +++ b/x-pack/test/functional/apps/index_management/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Index Management app', function () { - this.tags('ciGroup13'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./home_page')); }); diff --git a/x-pack/test/functional/apps/infra/config.ts b/x-pack/test/functional/apps/infra/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/infra/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/infra/index.ts b/x-pack/test/functional/apps/infra/index.ts index 15f92b8f37fd4..d574c747bf041 100644 --- a/x-pack/test/functional/apps/infra/index.ts +++ b/x-pack/test/functional/apps/infra/index.ts @@ -9,14 +9,15 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('InfraOps App', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./feature_controls')); + describe('Metrics UI', function () { loadTestFile(require.resolve('./home_page')); loadTestFile(require.resolve('./metrics_source_configuration')); loadTestFile(require.resolve('./metrics_anomalies')); loadTestFile(require.resolve('./metrics_explorer')); }); + describe('Logs UI', function () { loadTestFile(require.resolve('./log_entry_categories_tab')); loadTestFile(require.resolve('./log_entry_rate_tab')); diff --git a/x-pack/test/functional/apps/ingest_pipelines/config.ts b/x-pack/test/functional/apps/ingest_pipelines/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/ingest_pipelines/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/ingest_pipelines/index.ts b/x-pack/test/functional/apps/ingest_pipelines/index.ts index 655fccaf35a95..3c585319cfe13 100644 --- a/x-pack/test/functional/apps/ingest_pipelines/index.ts +++ b/x-pack/test/functional/apps/ingest_pipelines/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Ingest pipelines app', function () { - this.tags('ciGroup13'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./ingest_pipelines')); }); diff --git a/x-pack/test/functional/apps/lens/README.md b/x-pack/test/functional/apps/lens/README.md new file mode 100644 index 0000000000000..5e87a8b210bdd --- /dev/null +++ b/x-pack/test/functional/apps/lens/README.md @@ -0,0 +1,7 @@ +# What are all these groups? + +These tests take a while so they have been broken up into groups with their own `config.ts` and `index.ts` file, causing each of these groups to be independent bundles of tests which can be run on some worker in CI without taking an incredible amount of time. + +Want to change the groups to something more logical? Have fun! Just make sure that each group executes on CI in less than 10 minutes or so. We don't currently have any mechanism for validating this right now, you just need to look at the times in the log output on CI, but we'll be working on tooling for making this information more accessible soon. + +- Kibana Operations \ No newline at end of file diff --git a/x-pack/test/functional/apps/lens/group1/config.ts b/x-pack/test/functional/apps/lens/group1/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/lens/group1/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/lens/index.ts b/x-pack/test/functional/apps/lens/group1/index.ts similarity index 55% rename from x-pack/test/functional/apps/lens/index.ts rename to x-pack/test/functional/apps/lens/group1/index.ts index 372d17b473e4d..35030e3636c96 100644 --- a/x-pack/test/functional/apps/lens/index.ts +++ b/x-pack/test/functional/apps/lens/group1/index.ts @@ -6,7 +6,7 @@ */ import { EsArchiver } from '@kbn/es-archiver'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default ({ getService, loadTestFile, getPageObjects }: FtrProviderContext) => { const browser = getService('browser'); @@ -17,7 +17,7 @@ export default ({ getService, loadTestFile, getPageObjects }: FtrProviderContext const config = getService('config'); let remoteEsArchiver; - describe('lens app', () => { + describe('lens app - group 1', () => { const esArchive = 'x-pack/test/functional/es_archives/logstash_functional'; const localIndexPatternString = 'logstash-*'; const remoteIndexPatternString = 'ftr-remote:logstash-*'; @@ -70,54 +70,12 @@ export default ({ getService, loadTestFile, getPageObjects }: FtrProviderContext }); if (config.get('esTestCluster.ccs')) { - describe('', function () { - this.tags(['ciGroup3', 'skipFirefox']); - loadTestFile(require.resolve('./smokescreen')); - }); + loadTestFile(require.resolve('./smokescreen')); } else { - describe('', function () { - this.tags(['ciGroup3', 'skipFirefox']); - loadTestFile(require.resolve('./smokescreen')); - loadTestFile(require.resolve('./persistent_context')); - }); - - describe('', function () { - this.tags(['ciGroup16', 'skipFirefox']); - - loadTestFile(require.resolve('./add_to_dashboard')); - loadTestFile(require.resolve('./table_dashboard')); - loadTestFile(require.resolve('./table')); - loadTestFile(require.resolve('./runtime_fields')); - loadTestFile(require.resolve('./dashboard')); - loadTestFile(require.resolve('./multi_terms')); - loadTestFile(require.resolve('./epoch_millis')); - loadTestFile(require.resolve('./show_underlying_data')); - loadTestFile(require.resolve('./show_underlying_data_dashboard')); - }); - - describe('', function () { - this.tags(['ciGroup4', 'skipFirefox']); - - loadTestFile(require.resolve('./colors')); - loadTestFile(require.resolve('./chart_data')); - loadTestFile(require.resolve('./time_shift')); - loadTestFile(require.resolve('./drag_and_drop')); - loadTestFile(require.resolve('./disable_auto_apply')); - loadTestFile(require.resolve('./geo_field')); - loadTestFile(require.resolve('./formula')); - loadTestFile(require.resolve('./heatmap')); - loadTestFile(require.resolve('./gauge')); - loadTestFile(require.resolve('./metrics')); - loadTestFile(require.resolve('./reference_lines')); - loadTestFile(require.resolve('./annotations')); - loadTestFile(require.resolve('./inspector')); - loadTestFile(require.resolve('./error_handling')); - loadTestFile(require.resolve('./lens_tagging')); - loadTestFile(require.resolve('./lens_reporting')); - loadTestFile(require.resolve('./tsvb_open_in_lens')); - // has to be last one in the suite because it overrides saved objects - loadTestFile(require.resolve('./rollup')); - }); + loadTestFile(require.resolve('./smokescreen')); + loadTestFile(require.resolve('./persistent_context')); + loadTestFile(require.resolve('./table_dashboard')); + loadTestFile(require.resolve('./table')); } }); }; diff --git a/x-pack/test/functional/apps/lens/persistent_context.ts b/x-pack/test/functional/apps/lens/group1/persistent_context.ts similarity index 99% rename from x-pack/test/functional/apps/lens/persistent_context.ts rename to x-pack/test/functional/apps/lens/group1/persistent_context.ts index 445caa1abbec2..b6c37f8842329 100644 --- a/x-pack/test/functional/apps/lens/persistent_context.ts +++ b/x-pack/test/functional/apps/lens/group1/persistent_context.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/x-pack/test/functional/apps/lens/smokescreen.ts b/x-pack/test/functional/apps/lens/group1/smokescreen.ts similarity index 99% rename from x-pack/test/functional/apps/lens/smokescreen.ts rename to x-pack/test/functional/apps/lens/group1/smokescreen.ts index d817ee912664a..70887b337114f 100644 --- a/x-pack/test/functional/apps/lens/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/group1/smokescreen.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { range } from 'lodash'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/table.ts b/x-pack/test/functional/apps/lens/group1/table.ts similarity index 99% rename from x-pack/test/functional/apps/lens/table.ts rename to x-pack/test/functional/apps/lens/group1/table.ts index 2070eb047ef61..18ecc2e90cfe4 100644 --- a/x-pack/test/functional/apps/lens/table.ts +++ b/x-pack/test/functional/apps/lens/group1/table.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/table_dashboard.ts b/x-pack/test/functional/apps/lens/group1/table_dashboard.ts similarity index 97% rename from x-pack/test/functional/apps/lens/table_dashboard.ts rename to x-pack/test/functional/apps/lens/group1/table_dashboard.ts index 6e76d816fa6a6..136f1903420de 100644 --- a/x-pack/test/functional/apps/lens/table_dashboard.ts +++ b/x-pack/test/functional/apps/lens/group1/table_dashboard.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['lens', 'visualize', 'dashboard']); diff --git a/x-pack/test/functional/apps/lens/add_to_dashboard.ts b/x-pack/test/functional/apps/lens/group2/add_to_dashboard.ts similarity index 99% rename from x-pack/test/functional/apps/lens/add_to_dashboard.ts rename to x-pack/test/functional/apps/lens/group2/add_to_dashboard.ts index 5fbfdd0a5806e..8ad5cd41e0bec 100644 --- a/x-pack/test/functional/apps/lens/add_to_dashboard.ts +++ b/x-pack/test/functional/apps/lens/group2/add_to_dashboard.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/x-pack/test/functional/apps/lens/group2/config.ts b/x-pack/test/functional/apps/lens/group2/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/lens/group2/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/lens/dashboard.ts b/x-pack/test/functional/apps/lens/group2/dashboard.ts similarity index 99% rename from x-pack/test/functional/apps/lens/dashboard.ts rename to x-pack/test/functional/apps/lens/group2/dashboard.ts index 97dc29280761f..9a8cc99b24315 100644 --- a/x-pack/test/functional/apps/lens/dashboard.ts +++ b/x-pack/test/functional/apps/lens/group2/dashboard.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/x-pack/test/functional/apps/lens/epoch_millis.ts b/x-pack/test/functional/apps/lens/group2/epoch_millis.ts similarity index 97% rename from x-pack/test/functional/apps/lens/epoch_millis.ts rename to x-pack/test/functional/apps/lens/group2/epoch_millis.ts index d882d69ddd1fd..ce773baf27ad9 100644 --- a/x-pack/test/functional/apps/lens/epoch_millis.ts +++ b/x-pack/test/functional/apps/lens/group2/epoch_millis.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/group2/index.ts b/x-pack/test/functional/apps/lens/group2/index.ts new file mode 100644 index 0000000000000..0e1c732dff41c --- /dev/null +++ b/x-pack/test/functional/apps/lens/group2/index.ts @@ -0,0 +1,80 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EsArchiver } from '@kbn/es-archiver'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getService, loadTestFile, getPageObjects }: FtrProviderContext) => { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['timePicker']); + const config = getService('config'); + let remoteEsArchiver; + + describe('lens app - group 2', () => { + const esArchive = 'x-pack/test/functional/es_archives/logstash_functional'; + const localIndexPatternString = 'logstash-*'; + const remoteIndexPatternString = 'ftr-remote:logstash-*'; + const localFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/default', + }; + + const remoteFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/default', + }; + let esNode: EsArchiver; + let fixtureDirs: { + lensBasic: string; + lensDefault: string; + }; + let indexPatternString: string; + before(async () => { + await log.debug('Starting lens before method'); + await browser.setWindowSize(1280, 1200); + try { + config.get('esTestCluster.ccs'); + remoteEsArchiver = getService('remoteEsArchiver' as 'esArchiver'); + esNode = remoteEsArchiver; + fixtureDirs = remoteFixtures; + indexPatternString = remoteIndexPatternString; + } catch (error) { + esNode = esArchiver; + fixtureDirs = localFixtures; + indexPatternString = localIndexPatternString; + } + + await esNode.load(esArchive); + // changing the timepicker default here saves us from having to set it in Discover (~8s) + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.uiSettings.update({ + defaultIndex: indexPatternString, + 'dateFormat:tz': 'UTC', + }); + await kibanaServer.importExport.load(fixtureDirs.lensBasic); + await kibanaServer.importExport.load(fixtureDirs.lensDefault); + }); + + after(async () => { + await esArchiver.unload(esArchive); + await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.importExport.unload(fixtureDirs.lensBasic); + await kibanaServer.importExport.unload(fixtureDirs.lensDefault); + }); + + loadTestFile(require.resolve('./add_to_dashboard')); + loadTestFile(require.resolve('./runtime_fields')); + loadTestFile(require.resolve('./dashboard')); + loadTestFile(require.resolve('./multi_terms')); + loadTestFile(require.resolve('./epoch_millis')); + loadTestFile(require.resolve('./show_underlying_data')); + loadTestFile(require.resolve('./show_underlying_data_dashboard')); + }); +}; diff --git a/x-pack/test/functional/apps/lens/multi_terms.ts b/x-pack/test/functional/apps/lens/group2/multi_terms.ts similarity index 97% rename from x-pack/test/functional/apps/lens/multi_terms.ts rename to x-pack/test/functional/apps/lens/group2/multi_terms.ts index 05283b80a7c81..58fa172378964 100644 --- a/x-pack/test/functional/apps/lens/multi_terms.ts +++ b/x-pack/test/functional/apps/lens/group2/multi_terms.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/runtime_fields.ts b/x-pack/test/functional/apps/lens/group2/runtime_fields.ts similarity index 97% rename from x-pack/test/functional/apps/lens/runtime_fields.ts rename to x-pack/test/functional/apps/lens/group2/runtime_fields.ts index 252951cba4bd0..868432ce1ae4d 100644 --- a/x-pack/test/functional/apps/lens/runtime_fields.ts +++ b/x-pack/test/functional/apps/lens/group2/runtime_fields.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/show_underlying_data.ts b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts similarity index 99% rename from x-pack/test/functional/apps/lens/show_underlying_data.ts rename to x-pack/test/functional/apps/lens/group2/show_underlying_data.ts index 4bc8be22eb8f4..910a4a6880644 100644 --- a/x-pack/test/functional/apps/lens/show_underlying_data.ts +++ b/x-pack/test/functional/apps/lens/group2/show_underlying_data.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header', 'discover']); diff --git a/x-pack/test/functional/apps/lens/show_underlying_data_dashboard.ts b/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts similarity index 98% rename from x-pack/test/functional/apps/lens/show_underlying_data_dashboard.ts rename to x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts index dc25e5f77f412..9446b28c1e3ca 100644 --- a/x-pack/test/functional/apps/lens/show_underlying_data_dashboard.ts +++ b/x-pack/test/functional/apps/lens/group2/show_underlying_data_dashboard.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; import uuid from 'uuid'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/x-pack/test/functional/apps/lens/annotations.ts b/x-pack/test/functional/apps/lens/group3/annotations.ts similarity index 97% rename from x-pack/test/functional/apps/lens/annotations.ts rename to x-pack/test/functional/apps/lens/group3/annotations.ts index c54b3081f7418..2b641c6c161d4 100644 --- a/x-pack/test/functional/apps/lens/annotations.ts +++ b/x-pack/test/functional/apps/lens/group3/annotations.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/chart_data.ts b/x-pack/test/functional/apps/lens/group3/chart_data.ts similarity index 98% rename from x-pack/test/functional/apps/lens/chart_data.ts rename to x-pack/test/functional/apps/lens/group3/chart_data.ts index 7ea61c1fa3d81..6ef40c11407e8 100644 --- a/x-pack/test/functional/apps/lens/chart_data.ts +++ b/x-pack/test/functional/apps/lens/group3/chart_data.ts @@ -8,7 +8,7 @@ import { DebugState } from '@elastic/charts'; import expect from '@kbn/expect'; import { range } from 'lodash'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/colors.ts b/x-pack/test/functional/apps/lens/group3/colors.ts similarity index 96% rename from x-pack/test/functional/apps/lens/colors.ts rename to x-pack/test/functional/apps/lens/group3/colors.ts index 638da79b5c5cb..4078b0663d7ae 100644 --- a/x-pack/test/functional/apps/lens/colors.ts +++ b/x-pack/test/functional/apps/lens/group3/colors.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common']); diff --git a/x-pack/test/functional/apps/lens/group3/config.ts b/x-pack/test/functional/apps/lens/group3/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/lens/group3/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/lens/disable_auto_apply.ts b/x-pack/test/functional/apps/lens/group3/disable_auto_apply.ts similarity index 98% rename from x-pack/test/functional/apps/lens/disable_auto_apply.ts rename to x-pack/test/functional/apps/lens/group3/disable_auto_apply.ts index f73ce56bae694..e52b1cccda8a3 100644 --- a/x-pack/test/functional/apps/lens/disable_auto_apply.ts +++ b/x-pack/test/functional/apps/lens/group3/disable_auto_apply.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['lens', 'visualize']); diff --git a/x-pack/test/functional/apps/lens/drag_and_drop.ts b/x-pack/test/functional/apps/lens/group3/drag_and_drop.ts similarity index 99% rename from x-pack/test/functional/apps/lens/drag_and_drop.ts rename to x-pack/test/functional/apps/lens/group3/drag_and_drop.ts index d5b929481e6dc..dec72008d6f04 100644 --- a/x-pack/test/functional/apps/lens/drag_and_drop.ts +++ b/x-pack/test/functional/apps/lens/group3/drag_and_drop.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/error_handling.ts b/x-pack/test/functional/apps/lens/group3/error_handling.ts similarity index 97% rename from x-pack/test/functional/apps/lens/error_handling.ts rename to x-pack/test/functional/apps/lens/group3/error_handling.ts index 87f62abf88e4f..8f6659bda1562 100644 --- a/x-pack/test/functional/apps/lens/error_handling.ts +++ b/x-pack/test/functional/apps/lens/group3/error_handling.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects([ diff --git a/x-pack/test/functional/apps/lens/formula.ts b/x-pack/test/functional/apps/lens/group3/formula.ts similarity index 99% rename from x-pack/test/functional/apps/lens/formula.ts rename to x-pack/test/functional/apps/lens/group3/formula.ts index 02d4fda0e96a6..33a24d3aefb1c 100644 --- a/x-pack/test/functional/apps/lens/formula.ts +++ b/x-pack/test/functional/apps/lens/group3/formula.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common']); diff --git a/x-pack/test/functional/apps/lens/gauge.ts b/x-pack/test/functional/apps/lens/group3/gauge.ts similarity index 98% rename from x-pack/test/functional/apps/lens/gauge.ts rename to x-pack/test/functional/apps/lens/group3/gauge.ts index c21ddf5b70791..9cbcbb606b423 100644 --- a/x-pack/test/functional/apps/lens/gauge.ts +++ b/x-pack/test/functional/apps/lens/group3/gauge.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/geo_field.ts b/x-pack/test/functional/apps/lens/group3/geo_field.ts similarity index 95% rename from x-pack/test/functional/apps/lens/geo_field.ts rename to x-pack/test/functional/apps/lens/group3/geo_field.ts index f9b8277a22731..bb8012ba50d23 100644 --- a/x-pack/test/functional/apps/lens/geo_field.ts +++ b/x-pack/test/functional/apps/lens/group3/geo_field.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'header', 'maps', 'timePicker']); diff --git a/x-pack/test/functional/apps/lens/heatmap.ts b/x-pack/test/functional/apps/lens/group3/heatmap.ts similarity index 99% rename from x-pack/test/functional/apps/lens/heatmap.ts rename to x-pack/test/functional/apps/lens/group3/heatmap.ts index ff1378ac82539..aa1e10a715547 100644 --- a/x-pack/test/functional/apps/lens/heatmap.ts +++ b/x-pack/test/functional/apps/lens/group3/heatmap.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common']); diff --git a/x-pack/test/functional/apps/lens/group3/index.ts b/x-pack/test/functional/apps/lens/group3/index.ts new file mode 100644 index 0000000000000..03c42e4c70ebf --- /dev/null +++ b/x-pack/test/functional/apps/lens/group3/index.ts @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EsArchiver } from '@kbn/es-archiver'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getService, loadTestFile, getPageObjects }: FtrProviderContext) => { + const browser = getService('browser'); + const log = getService('log'); + const esArchiver = getService('esArchiver'); + const kibanaServer = getService('kibanaServer'); + const PageObjects = getPageObjects(['timePicker']); + const config = getService('config'); + let remoteEsArchiver; + + describe('lens app - group 3', () => { + const esArchive = 'x-pack/test/functional/es_archives/logstash_functional'; + const localIndexPatternString = 'logstash-*'; + const remoteIndexPatternString = 'ftr-remote:logstash-*'; + const localFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/default', + }; + + const remoteFixtures = { + lensBasic: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/lens_basic.json', + lensDefault: 'x-pack/test/functional/fixtures/kbn_archiver/lens/ccs/default', + }; + let esNode: EsArchiver; + let fixtureDirs: { + lensBasic: string; + lensDefault: string; + }; + let indexPatternString: string; + before(async () => { + await log.debug('Starting lens before method'); + await browser.setWindowSize(1280, 1200); + try { + config.get('esTestCluster.ccs'); + remoteEsArchiver = getService('remoteEsArchiver' as 'esArchiver'); + esNode = remoteEsArchiver; + fixtureDirs = remoteFixtures; + indexPatternString = remoteIndexPatternString; + } catch (error) { + esNode = esArchiver; + fixtureDirs = localFixtures; + indexPatternString = localIndexPatternString; + } + + await esNode.load(esArchive); + // changing the timepicker default here saves us from having to set it in Discover (~8s) + await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.uiSettings.update({ + defaultIndex: indexPatternString, + 'dateFormat:tz': 'UTC', + }); + await kibanaServer.importExport.load(fixtureDirs.lensBasic); + await kibanaServer.importExport.load(fixtureDirs.lensDefault); + }); + + after(async () => { + await esArchiver.unload(esArchive); + await PageObjects.timePicker.resetDefaultAbsoluteRangeViaUiSettings(); + await kibanaServer.importExport.unload(fixtureDirs.lensBasic); + await kibanaServer.importExport.unload(fixtureDirs.lensDefault); + }); + + loadTestFile(require.resolve('./colors')); + loadTestFile(require.resolve('./chart_data')); + loadTestFile(require.resolve('./time_shift')); + loadTestFile(require.resolve('./drag_and_drop')); + loadTestFile(require.resolve('./disable_auto_apply')); + loadTestFile(require.resolve('./geo_field')); + loadTestFile(require.resolve('./formula')); + loadTestFile(require.resolve('./heatmap')); + loadTestFile(require.resolve('./gauge')); + loadTestFile(require.resolve('./metrics')); + loadTestFile(require.resolve('./reference_lines')); + loadTestFile(require.resolve('./annotations')); + loadTestFile(require.resolve('./inspector')); + loadTestFile(require.resolve('./error_handling')); + loadTestFile(require.resolve('./lens_tagging')); + loadTestFile(require.resolve('./lens_reporting')); + loadTestFile(require.resolve('./tsvb_open_in_lens')); + // has to be last one in the suite because it overrides saved objects + loadTestFile(require.resolve('./rollup')); + }); +}; diff --git a/x-pack/test/functional/apps/lens/inspector.ts b/x-pack/test/functional/apps/lens/group3/inspector.ts similarity index 96% rename from x-pack/test/functional/apps/lens/inspector.ts rename to x-pack/test/functional/apps/lens/group3/inspector.ts index d94d3413c07b0..9f52d783011c4 100644 --- a/x-pack/test/functional/apps/lens/inspector.ts +++ b/x-pack/test/functional/apps/lens/group3/inspector.ts @@ -5,7 +5,7 @@ * 2.0. */ import expect from '@kbn/expect'; -import type { FtrProviderContext } from '../../ftr_provider_context'; +import type { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/lens_reporting.ts b/x-pack/test/functional/apps/lens/group3/lens_reporting.ts similarity index 96% rename from x-pack/test/functional/apps/lens/lens_reporting.ts rename to x-pack/test/functional/apps/lens/group3/lens_reporting.ts index 6dfb1dd923b3e..2cbb55ae03d97 100644 --- a/x-pack/test/functional/apps/lens/lens_reporting.ts +++ b/x-pack/test/functional/apps/lens/group3/lens_reporting.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'dashboard', 'reporting', 'timePicker']); diff --git a/x-pack/test/functional/apps/lens/lens_tagging.ts b/x-pack/test/functional/apps/lens/group3/lens_tagging.ts similarity index 98% rename from x-pack/test/functional/apps/lens/lens_tagging.ts rename to x-pack/test/functional/apps/lens/group3/lens_tagging.ts index 3852fdb0456ac..d69b49403fc31 100644 --- a/x-pack/test/functional/apps/lens/lens_tagging.ts +++ b/x-pack/test/functional/apps/lens/group3/lens_tagging.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const listingTable = getService('listingTable'); diff --git a/x-pack/test/functional/apps/lens/metrics.ts b/x-pack/test/functional/apps/lens/group3/metrics.ts similarity index 97% rename from x-pack/test/functional/apps/lens/metrics.ts rename to x-pack/test/functional/apps/lens/group3/metrics.ts index 62a8b69141a58..bf651f7a12a1b 100644 --- a/x-pack/test/functional/apps/lens/metrics.ts +++ b/x-pack/test/functional/apps/lens/group3/metrics.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/reference_lines.ts b/x-pack/test/functional/apps/lens/group3/reference_lines.ts similarity index 98% rename from x-pack/test/functional/apps/lens/reference_lines.ts rename to x-pack/test/functional/apps/lens/group3/reference_lines.ts index 97c6ebf5b138f..f022a6cef6e7a 100644 --- a/x-pack/test/functional/apps/lens/reference_lines.ts +++ b/x-pack/test/functional/apps/lens/group3/reference_lines.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/rollup.ts b/x-pack/test/functional/apps/lens/group3/rollup.ts similarity index 98% rename from x-pack/test/functional/apps/lens/rollup.ts rename to x-pack/test/functional/apps/lens/group3/rollup.ts index 25ab766d04bbd..d42cc67ad673c 100644 --- a/x-pack/test/functional/apps/lens/rollup.ts +++ b/x-pack/test/functional/apps/lens/group3/rollup.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'header', 'timePicker']); diff --git a/x-pack/test/functional/apps/lens/time_shift.ts b/x-pack/test/functional/apps/lens/group3/time_shift.ts similarity index 97% rename from x-pack/test/functional/apps/lens/time_shift.ts rename to x-pack/test/functional/apps/lens/group3/time_shift.ts index e3363bee419aa..4dd22ea719ec7 100644 --- a/x-pack/test/functional/apps/lens/time_shift.ts +++ b/x-pack/test/functional/apps/lens/group3/time_shift.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'common', 'header']); diff --git a/x-pack/test/functional/apps/lens/tsvb_open_in_lens.ts b/x-pack/test/functional/apps/lens/group3/tsvb_open_in_lens.ts similarity index 99% rename from x-pack/test/functional/apps/lens/tsvb_open_in_lens.ts rename to x-pack/test/functional/apps/lens/group3/tsvb_open_in_lens.ts index 0315d20e5fc91..f9d21f80462e6 100644 --- a/x-pack/test/functional/apps/lens/tsvb_open_in_lens.ts +++ b/x-pack/test/functional/apps/lens/group3/tsvb_open_in_lens.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const { visualize, visualBuilder, header, lens, timeToVisualize, dashboard, canvas } = diff --git a/x-pack/test/functional/apps/license_management/config.ts b/x-pack/test/functional/apps/license_management/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/license_management/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/license_management/index.ts b/x-pack/test/functional/apps/license_management/index.ts index a209a4370ced9..d4256588667ec 100644 --- a/x-pack/test/functional/apps/license_management/index.ts +++ b/x-pack/test/functional/apps/license_management/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('License app', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./home_page')); }); diff --git a/x-pack/test/functional/apps/logstash/config.ts b/x-pack/test/functional/apps/logstash/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/logstash/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/logstash/feature_controls/index.ts b/x-pack/test/functional/apps/logstash/feature_controls/index.ts index eb4c681531cbc..c50611d7fa7c4 100644 --- a/x-pack/test/functional/apps/logstash/feature_controls/index.ts +++ b/x-pack/test/functional/apps/logstash/feature_controls/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('feature controls', function () { - this.tags(['ciGroup2']); - loadTestFile(require.resolve('./logstash_security')); }); } diff --git a/x-pack/test/functional/apps/logstash/index.js b/x-pack/test/functional/apps/logstash/index.js index 8c1ac233e9c57..deaf4041b1b59 100644 --- a/x-pack/test/functional/apps/logstash/index.js +++ b/x-pack/test/functional/apps/logstash/index.js @@ -7,8 +7,6 @@ export default function ({ loadTestFile }) { describe('logstash', function () { - this.tags(['ciGroup2']); - loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./pipeline_list')); loadTestFile(require.resolve('./pipeline_create')); diff --git a/x-pack/test/functional/apps/management/config.ts b/x-pack/test/functional/apps/management/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/management/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/management/feature_controls/index.ts b/x-pack/test/functional/apps/management/feature_controls/index.ts index 66eb2e4937620..17e71ef190856 100644 --- a/x-pack/test/functional/apps/management/feature_controls/index.ts +++ b/x-pack/test/functional/apps/management/feature_controls/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('feature controls', function () { - this.tags(['ciGroup2']); - loadTestFile(require.resolve('./management_security')); }); } diff --git a/x-pack/test/functional/apps/management/index.ts b/x-pack/test/functional/apps/management/index.ts index 03fec9fffe4fb..72da3e0fd739a 100644 --- a/x-pack/test/functional/apps/management/index.ts +++ b/x-pack/test/functional/apps/management/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('management', function () { - this.tags(['ciGroup2']); - loadTestFile(require.resolve('./create_index_pattern_wizard')); loadTestFile(require.resolve('./feature_controls')); }); diff --git a/x-pack/test/functional/apps/maps/README.md b/x-pack/test/functional/apps/maps/README.md new file mode 100644 index 0000000000000..5e87a8b210bdd --- /dev/null +++ b/x-pack/test/functional/apps/maps/README.md @@ -0,0 +1,7 @@ +# What are all these groups? + +These tests take a while so they have been broken up into groups with their own `config.ts` and `index.ts` file, causing each of these groups to be independent bundles of tests which can be run on some worker in CI without taking an incredible amount of time. + +Want to change the groups to something more logical? Have fun! Just make sure that each group executes on CI in less than 10 minutes or so. We don't currently have any mechanism for validating this right now, you just need to look at the times in the log output on CI, but we'll be working on tooling for making this information more accessible soon. + +- Kibana Operations \ No newline at end of file diff --git a/x-pack/test/functional/apps/maps/auto_fit_to_bounds.js b/x-pack/test/functional/apps/maps/group1/auto_fit_to_bounds.js similarity index 100% rename from x-pack/test/functional/apps/maps/auto_fit_to_bounds.js rename to x-pack/test/functional/apps/maps/group1/auto_fit_to_bounds.js diff --git a/x-pack/test/functional/apps/maps/blended_vector_layer.js b/x-pack/test/functional/apps/maps/group1/blended_vector_layer.js similarity index 100% rename from x-pack/test/functional/apps/maps/blended_vector_layer.js rename to x-pack/test/functional/apps/maps/group1/blended_vector_layer.js diff --git a/x-pack/test/functional/apps/maps/group1/config.ts b/x-pack/test/functional/apps/maps/group1/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/maps/group1/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/maps/documents_source/docvalue_fields.js b/x-pack/test/functional/apps/maps/group1/documents_source/docvalue_fields.js similarity index 100% rename from x-pack/test/functional/apps/maps/documents_source/docvalue_fields.js rename to x-pack/test/functional/apps/maps/group1/documents_source/docvalue_fields.js diff --git a/x-pack/test/functional/apps/maps/documents_source/index.js b/x-pack/test/functional/apps/maps/group1/documents_source/index.js similarity index 100% rename from x-pack/test/functional/apps/maps/documents_source/index.js rename to x-pack/test/functional/apps/maps/group1/documents_source/index.js diff --git a/x-pack/test/functional/apps/maps/documents_source/search_hits.js b/x-pack/test/functional/apps/maps/group1/documents_source/search_hits.js similarity index 100% rename from x-pack/test/functional/apps/maps/documents_source/search_hits.js rename to x-pack/test/functional/apps/maps/group1/documents_source/search_hits.js diff --git a/x-pack/test/functional/apps/maps/documents_source/top_hits.js b/x-pack/test/functional/apps/maps/group1/documents_source/top_hits.js similarity index 100% rename from x-pack/test/functional/apps/maps/documents_source/top_hits.js rename to x-pack/test/functional/apps/maps/group1/documents_source/top_hits.js diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts b/x-pack/test/functional/apps/maps/group1/feature_controls/maps_security.ts similarity index 99% rename from x-pack/test/functional/apps/maps/feature_controls/maps_security.ts rename to x-pack/test/functional/apps/maps/group1/feature_controls/maps_security.ts index db6bfb642ebbb..ad4a2acd475a0 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_security.ts +++ b/x-pack/test/functional/apps/maps/group1/feature_controls/maps_security.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const security = getService('security'); diff --git a/x-pack/test/functional/apps/maps/feature_controls/maps_spaces.ts b/x-pack/test/functional/apps/maps/group1/feature_controls/maps_spaces.ts similarity index 98% rename from x-pack/test/functional/apps/maps/feature_controls/maps_spaces.ts rename to x-pack/test/functional/apps/maps/group1/feature_controls/maps_spaces.ts index 1beddd72d3fde..a306c15bfbdb2 100644 --- a/x-pack/test/functional/apps/maps/feature_controls/maps_spaces.ts +++ b/x-pack/test/functional/apps/maps/group1/feature_controls/maps_spaces.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { APP_ID } from '@kbn/maps-plugin/common/constants'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const spacesService = getService('spaces'); diff --git a/x-pack/test/functional/apps/maps/full_screen_mode.js b/x-pack/test/functional/apps/maps/group1/full_screen_mode.js similarity index 100% rename from x-pack/test/functional/apps/maps/full_screen_mode.js rename to x-pack/test/functional/apps/maps/group1/full_screen_mode.js diff --git a/x-pack/test/functional/apps/maps/group1/index.js b/x-pack/test/functional/apps/maps/group1/index.js new file mode 100644 index 0000000000000..be59d43012626 --- /dev/null +++ b/x-pack/test/functional/apps/maps/group1/index.js @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export default function ({ loadTestFile, getService }) { + const kibanaServer = getService('kibanaServer'); + const esArchiver = getService('esArchiver'); + const browser = getService('browser'); + const log = getService('log'); + const supertest = getService('supertest'); + + describe('maps app', function () { + this.tags(['skipFirefox']); + + before(async () => { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' + ); + // Functional tests verify behavior when referenced index pattern saved objects can not be found. + // However, saved object import fails when reference saved objects can not be found. + // To prevent import errors, index pattern saved object references exist during import + // but are then deleted afterwards to enable testing of missing reference index pattern saved objects. + + log.info('Delete index pattern'); + log.debug('id: ' + 'idThatDoesNotExitForESGeoGridSource'); + log.debug('id: ' + 'idThatDoesNotExitForESSearchSource'); + log.debug('id: ' + 'idThatDoesNotExitForESJoinSource'); + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESGeoGridSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESSearchSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESJoinSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await esArchiver.load('x-pack/test/functional/es_archives/maps/data'); + await kibanaServer.uiSettings.replace({ + defaultIndex: 'c698b940-e149-11e8-a35a-370a8516603a', + }); + await browser.setWindowSize(1600, 1000); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/maps/data'); + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' + ); + }); + + loadTestFile(require.resolve('./documents_source')); + loadTestFile(require.resolve('./blended_vector_layer')); + loadTestFile(require.resolve('./vector_styling')); + loadTestFile(require.resolve('./saved_object_management')); + loadTestFile(require.resolve('./sample_data')); + loadTestFile(require.resolve('./auto_fit_to_bounds')); + loadTestFile(require.resolve('./layer_visibility')); + loadTestFile(require.resolve('./feature_controls/maps_security')); + loadTestFile(require.resolve('./feature_controls/maps_spaces')); + loadTestFile(require.resolve('./full_screen_mode')); + }); +} diff --git a/x-pack/test/functional/apps/maps/layer_visibility.js b/x-pack/test/functional/apps/maps/group1/layer_visibility.js similarity index 100% rename from x-pack/test/functional/apps/maps/layer_visibility.js rename to x-pack/test/functional/apps/maps/group1/layer_visibility.js diff --git a/x-pack/test/functional/apps/maps/sample_data.js b/x-pack/test/functional/apps/maps/group1/sample_data.js similarity index 100% rename from x-pack/test/functional/apps/maps/sample_data.js rename to x-pack/test/functional/apps/maps/group1/sample_data.js diff --git a/x-pack/test/functional/apps/maps/saved_object_management.js b/x-pack/test/functional/apps/maps/group1/saved_object_management.js similarity index 100% rename from x-pack/test/functional/apps/maps/saved_object_management.js rename to x-pack/test/functional/apps/maps/group1/saved_object_management.js diff --git a/x-pack/test/functional/apps/maps/vector_styling.js b/x-pack/test/functional/apps/maps/group1/vector_styling.js similarity index 100% rename from x-pack/test/functional/apps/maps/vector_styling.js rename to x-pack/test/functional/apps/maps/group1/vector_styling.js diff --git a/x-pack/test/functional/apps/maps/group2/config.ts b/x-pack/test/functional/apps/maps/group2/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/maps/group2/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/maps/embeddable/add_to_dashboard.js b/x-pack/test/functional/apps/maps/group2/embeddable/add_to_dashboard.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/add_to_dashboard.js rename to x-pack/test/functional/apps/maps/group2/embeddable/add_to_dashboard.js diff --git a/x-pack/test/functional/apps/maps/embeddable/dashboard.js b/x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/dashboard.js rename to x-pack/test/functional/apps/maps/group2/embeddable/dashboard.js diff --git a/x-pack/test/functional/apps/maps/embeddable/embeddable_library.js b/x-pack/test/functional/apps/maps/group2/embeddable/embeddable_library.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/embeddable_library.js rename to x-pack/test/functional/apps/maps/group2/embeddable/embeddable_library.js diff --git a/x-pack/test/functional/apps/maps/embeddable/embeddable_state.js b/x-pack/test/functional/apps/maps/group2/embeddable/embeddable_state.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/embeddable_state.js rename to x-pack/test/functional/apps/maps/group2/embeddable/embeddable_state.js diff --git a/x-pack/test/functional/apps/maps/embeddable/filter_by_map_extent.js b/x-pack/test/functional/apps/maps/group2/embeddable/filter_by_map_extent.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/filter_by_map_extent.js rename to x-pack/test/functional/apps/maps/group2/embeddable/filter_by_map_extent.js diff --git a/x-pack/test/functional/apps/maps/embeddable/index.js b/x-pack/test/functional/apps/maps/group2/embeddable/index.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/index.js rename to x-pack/test/functional/apps/maps/group2/embeddable/index.js diff --git a/x-pack/test/functional/apps/maps/embeddable/save_and_return.js b/x-pack/test/functional/apps/maps/group2/embeddable/save_and_return.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/save_and_return.js rename to x-pack/test/functional/apps/maps/group2/embeddable/save_and_return.js diff --git a/x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js b/x-pack/test/functional/apps/maps/group2/embeddable/tooltip_filter_actions.js similarity index 100% rename from x-pack/test/functional/apps/maps/embeddable/tooltip_filter_actions.js rename to x-pack/test/functional/apps/maps/group2/embeddable/tooltip_filter_actions.js diff --git a/x-pack/test/functional/apps/maps/es_geo_grid_source.js b/x-pack/test/functional/apps/maps/group2/es_geo_grid_source.js similarity index 100% rename from x-pack/test/functional/apps/maps/es_geo_grid_source.js rename to x-pack/test/functional/apps/maps/group2/es_geo_grid_source.js diff --git a/x-pack/test/functional/apps/maps/group2/index.js b/x-pack/test/functional/apps/maps/group2/index.js new file mode 100644 index 0000000000000..b8b3a15a10ed5 --- /dev/null +++ b/x-pack/test/functional/apps/maps/group2/index.js @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export default function ({ loadTestFile, getService }) { + const kibanaServer = getService('kibanaServer'); + const esArchiver = getService('esArchiver'); + const browser = getService('browser'); + const log = getService('log'); + const supertest = getService('supertest'); + + describe('maps app', function () { + this.tags(['skipFirefox']); + + before(async () => { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' + ); + // Functional tests verify behavior when referenced index pattern saved objects can not be found. + // However, saved object import fails when reference saved objects can not be found. + // To prevent import errors, index pattern saved object references exist during import + // but are then deleted afterwards to enable testing of missing reference index pattern saved objects. + + log.info('Delete index pattern'); + log.debug('id: ' + 'idThatDoesNotExitForESGeoGridSource'); + log.debug('id: ' + 'idThatDoesNotExitForESSearchSource'); + log.debug('id: ' + 'idThatDoesNotExitForESJoinSource'); + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESGeoGridSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESSearchSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESJoinSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await esArchiver.load('x-pack/test/functional/es_archives/maps/data'); + await kibanaServer.uiSettings.replace({ + defaultIndex: 'c698b940-e149-11e8-a35a-370a8516603a', + }); + await browser.setWindowSize(1600, 1000); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/maps/data'); + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' + ); + }); + + loadTestFile(require.resolve('./es_geo_grid_source')); + loadTestFile(require.resolve('./embeddable')); + }); +} diff --git a/x-pack/test/functional/apps/maps/group3/config.ts b/x-pack/test/functional/apps/maps/group3/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/maps/group3/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/maps/group3/index.js b/x-pack/test/functional/apps/maps/group3/index.js new file mode 100644 index 0000000000000..fda116cecc307 --- /dev/null +++ b/x-pack/test/functional/apps/maps/group3/index.js @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export default function ({ loadTestFile, getService }) { + const kibanaServer = getService('kibanaServer'); + const esArchiver = getService('esArchiver'); + const browser = getService('browser'); + const log = getService('log'); + const supertest = getService('supertest'); + + describe('maps app', function () { + this.tags(['skipFirefox']); + + before(async () => { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' + ); + // Functional tests verify behavior when referenced index pattern saved objects can not be found. + // However, saved object import fails when reference saved objects can not be found. + // To prevent import errors, index pattern saved object references exist during import + // but are then deleted afterwards to enable testing of missing reference index pattern saved objects. + + log.info('Delete index pattern'); + log.debug('id: ' + 'idThatDoesNotExitForESGeoGridSource'); + log.debug('id: ' + 'idThatDoesNotExitForESSearchSource'); + log.debug('id: ' + 'idThatDoesNotExitForESJoinSource'); + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESGeoGridSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESSearchSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await supertest + .delete('/api/index_patterns/index_pattern/' + 'idThatDoesNotExitForESJoinSource') + .set('kbn-xsrf', 'true') + .expect(200); + + await esArchiver.load('x-pack/test/functional/es_archives/maps/data'); + await kibanaServer.uiSettings.replace({ + defaultIndex: 'c698b940-e149-11e8-a35a-370a8516603a', + }); + await browser.setWindowSize(1600, 1000); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/maps/data'); + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/maps.json' + ); + }); + + loadTestFile(require.resolve('./reports')); + }); +} diff --git a/x-pack/test/functional/apps/maps/reports/baseline/example_map_report.png b/x-pack/test/functional/apps/maps/group3/reports/baseline/example_map_report.png similarity index 100% rename from x-pack/test/functional/apps/maps/reports/baseline/example_map_report.png rename to x-pack/test/functional/apps/maps/group3/reports/baseline/example_map_report.png diff --git a/x-pack/test/functional/apps/maps/reports/baseline/geo_map_report.png b/x-pack/test/functional/apps/maps/group3/reports/baseline/geo_map_report.png similarity index 100% rename from x-pack/test/functional/apps/maps/reports/baseline/geo_map_report.png rename to x-pack/test/functional/apps/maps/group3/reports/baseline/geo_map_report.png diff --git a/x-pack/test/functional/apps/maps/reports/index.ts b/x-pack/test/functional/apps/maps/group3/reports/index.ts similarity index 97% rename from x-pack/test/functional/apps/maps/reports/index.ts rename to x-pack/test/functional/apps/maps/group3/reports/index.ts index 4e942b1e150ef..c892842782aa6 100644 --- a/x-pack/test/functional/apps/maps/reports/index.ts +++ b/x-pack/test/functional/apps/maps/group3/reports/index.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; const REPORTS_FOLDER = __dirname; diff --git a/x-pack/test/functional/apps/maps/add_layer_panel.js b/x-pack/test/functional/apps/maps/group4/add_layer_panel.js similarity index 100% rename from x-pack/test/functional/apps/maps/add_layer_panel.js rename to x-pack/test/functional/apps/maps/group4/add_layer_panel.js diff --git a/x-pack/test/functional/apps/maps/group4/config.ts b/x-pack/test/functional/apps/maps/group4/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/maps/group4/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/maps/discover.js b/x-pack/test/functional/apps/maps/group4/discover.js similarity index 100% rename from x-pack/test/functional/apps/maps/discover.js rename to x-pack/test/functional/apps/maps/group4/discover.js diff --git a/x-pack/test/functional/apps/maps/es_pew_pew_source.js b/x-pack/test/functional/apps/maps/group4/es_pew_pew_source.js similarity index 100% rename from x-pack/test/functional/apps/maps/es_pew_pew_source.js rename to x-pack/test/functional/apps/maps/group4/es_pew_pew_source.js diff --git a/x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.dbf b/x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.dbf similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.dbf rename to x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.dbf diff --git a/x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.prj b/x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.prj similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.prj rename to x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.prj diff --git a/x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.shp b/x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.shp similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.shp rename to x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.shp diff --git a/x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.shx b/x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.shx similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/files/cb_2018_us_csa_500k.shx rename to x-pack/test/functional/apps/maps/group4/file_upload/files/cb_2018_us_csa_500k.shx diff --git a/x-pack/test/functional/apps/maps/file_upload/files/point.json b/x-pack/test/functional/apps/maps/group4/file_upload/files/point.json similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/files/point.json rename to x-pack/test/functional/apps/maps/group4/file_upload/files/point.json diff --git a/x-pack/test/functional/apps/maps/file_upload/files/polygon.json b/x-pack/test/functional/apps/maps/group4/file_upload/files/polygon.json similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/files/polygon.json rename to x-pack/test/functional/apps/maps/group4/file_upload/files/polygon.json diff --git a/x-pack/test/functional/apps/maps/file_upload/files/world_countries_v7.geo.json b/x-pack/test/functional/apps/maps/group4/file_upload/files/world_countries_v7.geo.json similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/files/world_countries_v7.geo.json rename to x-pack/test/functional/apps/maps/group4/file_upload/files/world_countries_v7.geo.json diff --git a/x-pack/test/functional/apps/maps/file_upload/geojson.js b/x-pack/test/functional/apps/maps/group4/file_upload/geojson.js similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/geojson.js rename to x-pack/test/functional/apps/maps/group4/file_upload/geojson.js diff --git a/x-pack/test/functional/apps/maps/file_upload/index.js b/x-pack/test/functional/apps/maps/group4/file_upload/index.js similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/index.js rename to x-pack/test/functional/apps/maps/group4/file_upload/index.js diff --git a/x-pack/test/functional/apps/maps/file_upload/shapefile.js b/x-pack/test/functional/apps/maps/group4/file_upload/shapefile.js similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/shapefile.js rename to x-pack/test/functional/apps/maps/group4/file_upload/shapefile.js diff --git a/x-pack/test/functional/apps/maps/file_upload/wizard.js b/x-pack/test/functional/apps/maps/group4/file_upload/wizard.js similarity index 100% rename from x-pack/test/functional/apps/maps/file_upload/wizard.js rename to x-pack/test/functional/apps/maps/group4/file_upload/wizard.js diff --git a/x-pack/test/functional/apps/maps/geofile_wizard_auto_open.ts b/x-pack/test/functional/apps/maps/group4/geofile_wizard_auto_open.ts similarity index 95% rename from x-pack/test/functional/apps/maps/geofile_wizard_auto_open.ts rename to x-pack/test/functional/apps/maps/group4/geofile_wizard_auto_open.ts index dd69cc7882fc7..ebe434b6afe6e 100644 --- a/x-pack/test/functional/apps/maps/geofile_wizard_auto_open.ts +++ b/x-pack/test/functional/apps/maps/group4/geofile_wizard_auto_open.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'maps']); diff --git a/x-pack/test/functional/apps/maps/index.js b/x-pack/test/functional/apps/maps/group4/index.js similarity index 57% rename from x-pack/test/functional/apps/maps/index.js rename to x-pack/test/functional/apps/maps/group4/index.js index 9d7e7a9cbddcc..70cb5ac660768 100644 --- a/x-pack/test/functional/apps/maps/index.js +++ b/x-pack/test/functional/apps/maps/group4/index.js @@ -58,46 +58,18 @@ export default function ({ loadTestFile, getService }) { ); }); - describe('', async function () { - this.tags('ciGroup9'); - loadTestFile(require.resolve('./documents_source')); - loadTestFile(require.resolve('./blended_vector_layer')); - loadTestFile(require.resolve('./vector_styling')); - loadTestFile(require.resolve('./saved_object_management')); - loadTestFile(require.resolve('./sample_data')); - loadTestFile(require.resolve('./auto_fit_to_bounds')); - loadTestFile(require.resolve('./layer_visibility')); - loadTestFile(require.resolve('./feature_controls/maps_security')); - loadTestFile(require.resolve('./feature_controls/maps_spaces')); - loadTestFile(require.resolve('./full_screen_mode')); - }); - - describe('', function () { - this.tags('ciGroup22'); - loadTestFile(require.resolve('./es_geo_grid_source')); - loadTestFile(require.resolve('./embeddable')); - }); - - describe('', function () { - this.tags('ciGroup2'); // same group used in x-pack/test/reporting_functional - loadTestFile(require.resolve('./reports')); - }); - - describe('', function () { - this.tags('ciGroup10'); - loadTestFile(require.resolve('./es_pew_pew_source')); - loadTestFile(require.resolve('./joins')); - loadTestFile(require.resolve('./mvt_joins')); - loadTestFile(require.resolve('./mapbox_styles')); - loadTestFile(require.resolve('./mvt_scaling')); - loadTestFile(require.resolve('./mvt_geotile_grid')); - loadTestFile(require.resolve('./add_layer_panel')); - loadTestFile(require.resolve('./file_upload')); - loadTestFile(require.resolve('./layer_errors')); - loadTestFile(require.resolve('./visualize_create_menu')); - loadTestFile(require.resolve('./discover')); - loadTestFile(require.resolve('./geofile_wizard_auto_open')); - loadTestFile(require.resolve('./lens')); - }); + loadTestFile(require.resolve('./es_pew_pew_source')); + loadTestFile(require.resolve('./joins')); + loadTestFile(require.resolve('./mvt_joins')); + loadTestFile(require.resolve('./mapbox_styles')); + loadTestFile(require.resolve('./mvt_scaling')); + loadTestFile(require.resolve('./mvt_geotile_grid')); + loadTestFile(require.resolve('./add_layer_panel')); + loadTestFile(require.resolve('./file_upload')); + loadTestFile(require.resolve('./layer_errors')); + loadTestFile(require.resolve('./visualize_create_menu')); + loadTestFile(require.resolve('./discover')); + loadTestFile(require.resolve('./geofile_wizard_auto_open')); + loadTestFile(require.resolve('./lens')); }); } diff --git a/x-pack/test/functional/apps/maps/joins.js b/x-pack/test/functional/apps/maps/group4/joins.js similarity index 100% rename from x-pack/test/functional/apps/maps/joins.js rename to x-pack/test/functional/apps/maps/group4/joins.js diff --git a/x-pack/test/functional/apps/maps/layer_errors.js b/x-pack/test/functional/apps/maps/group4/layer_errors.js similarity index 100% rename from x-pack/test/functional/apps/maps/layer_errors.js rename to x-pack/test/functional/apps/maps/group4/layer_errors.js diff --git a/x-pack/test/functional/apps/maps/lens/choropleth_chart.ts b/x-pack/test/functional/apps/maps/group4/lens/choropleth_chart.ts similarity index 97% rename from x-pack/test/functional/apps/maps/lens/choropleth_chart.ts rename to x-pack/test/functional/apps/maps/group4/lens/choropleth_chart.ts index 420f895fe6aa6..b026dd7444748 100644 --- a/x-pack/test/functional/apps/maps/lens/choropleth_chart.ts +++ b/x-pack/test/functional/apps/maps/group4/lens/choropleth_chart.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['visualize', 'lens', 'maps']); diff --git a/x-pack/test/functional/apps/maps/lens/index.ts b/x-pack/test/functional/apps/maps/group4/lens/index.ts similarity index 85% rename from x-pack/test/functional/apps/maps/lens/index.ts rename to x-pack/test/functional/apps/maps/group4/lens/index.ts index 78086303166a1..484faf431be75 100644 --- a/x-pack/test/functional/apps/maps/lens/index.ts +++ b/x-pack/test/functional/apps/maps/group4/lens/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('lens', function () { diff --git a/x-pack/test/functional/apps/maps/mapbox_styles.js b/x-pack/test/functional/apps/maps/group4/mapbox_styles.js similarity index 100% rename from x-pack/test/functional/apps/maps/mapbox_styles.js rename to x-pack/test/functional/apps/maps/group4/mapbox_styles.js diff --git a/x-pack/test/functional/apps/maps/mvt_geotile_grid.js b/x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js similarity index 100% rename from x-pack/test/functional/apps/maps/mvt_geotile_grid.js rename to x-pack/test/functional/apps/maps/group4/mvt_geotile_grid.js diff --git a/x-pack/test/functional/apps/maps/mvt_joins.ts b/x-pack/test/functional/apps/maps/group4/mvt_joins.ts similarity index 98% rename from x-pack/test/functional/apps/maps/mvt_joins.ts rename to x-pack/test/functional/apps/maps/group4/mvt_joins.ts index 2ae8f7ea5943b..c6567c84b2165 100644 --- a/x-pack/test/functional/apps/maps/mvt_joins.ts +++ b/x-pack/test/functional/apps/maps/group4/mvt_joins.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['maps']); diff --git a/x-pack/test/functional/apps/maps/mvt_scaling.js b/x-pack/test/functional/apps/maps/group4/mvt_scaling.js similarity index 100% rename from x-pack/test/functional/apps/maps/mvt_scaling.js rename to x-pack/test/functional/apps/maps/group4/mvt_scaling.js diff --git a/x-pack/test/functional/apps/maps/visualize_create_menu.js b/x-pack/test/functional/apps/maps/group4/visualize_create_menu.js similarity index 100% rename from x-pack/test/functional/apps/maps/visualize_create_menu.js rename to x-pack/test/functional/apps/maps/group4/visualize_create_menu.js diff --git a/x-pack/test/functional/apps/ml/README.md b/x-pack/test/functional/apps/ml/README.md new file mode 100644 index 0000000000000..5e87a8b210bdd --- /dev/null +++ b/x-pack/test/functional/apps/ml/README.md @@ -0,0 +1,7 @@ +# What are all these groups? + +These tests take a while so they have been broken up into groups with their own `config.ts` and `index.ts` file, causing each of these groups to be independent bundles of tests which can be run on some worker in CI without taking an incredible amount of time. + +Want to change the groups to something more logical? Have fun! Just make sure that each group executes on CI in less than 10 minutes or so. We don't currently have any mechanism for validating this right now, you just need to look at the times in the log output on CI, but we'll be working on tooling for making this information more accessible soon. + +- Kibana Operations \ No newline at end of file diff --git a/x-pack/test/functional/apps/ml/data_visualizer/config.ts b/x-pack/test/functional/apps/ml/data_visualizer/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/ml/data_visualizer/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts index f5610e8b607da..ef15775f86204 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/file_data_visualizer.ts @@ -5,8 +5,6 @@ * 2.0. */ -import path from 'path'; - import { ML_JOB_FIELD_TYPES } from '@kbn/ml-plugin/common/constants/field_types'; import { FtrProviderContext } from '../../../ftr_provider_context'; @@ -16,7 +14,7 @@ export default function ({ getService }: FtrProviderContext) { const testDataListPositive = [ { suiteSuffix: 'with an artificial server log', - filePath: path.join(__dirname, 'files_to_import', 'artificial_server_log'), + filePath: require.resolve('./files_to_import/artificial_server_log'), indexName: 'user-import_1', createIndexPattern: false, fieldTypeFilters: [ML_JOB_FIELD_TYPES.NUMBER, ML_JOB_FIELD_TYPES.DATE], @@ -116,7 +114,7 @@ export default function ({ getService }: FtrProviderContext) { }, { suiteSuffix: 'with a file containing geo field', - filePath: path.join(__dirname, 'files_to_import', 'geo_file.csv'), + filePath: require.resolve('./files_to_import/geo_file.csv'), indexName: 'user-import_2', createIndexPattern: false, fieldTypeFilters: [ML_JOB_FIELD_TYPES.GEO_POINT], @@ -158,7 +156,7 @@ export default function ({ getService }: FtrProviderContext) { }, { suiteSuffix: 'with a file with a missing new line char at the end', - filePath: path.join(__dirname, 'files_to_import', 'missing_end_of_file_newline.csv'), + filePath: require.resolve('./files_to_import/missing_end_of_file_newline.csv'), indexName: 'user-import_3', createIndexPattern: false, fieldTypeFilters: [], @@ -205,7 +203,7 @@ export default function ({ getService }: FtrProviderContext) { const testDataListNegative = [ { suiteSuffix: 'with a non-log file', - filePath: path.join(__dirname, 'files_to_import', 'not_a_log_file'), + filePath: require.resolve('./files_to_import/not_a_log_file'), }, ]; diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index.ts b/x-pack/test/functional/apps/ml/data_visualizer/index.ts index 3bb8e3d728318..973ebf2bbe3ab 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index.ts @@ -7,10 +7,38 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function ({ loadTestFile }: FtrProviderContext) { - describe('data visualizer', function () { +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('machine learning - data visualizer', function () { this.tags(['skipFirefox', 'mlqa']); + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + // NOTE: Logout needs to happen before anything else to avoid flaky behavior + await ml.securityUI.logout(); + + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote_small'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/ecommerce'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/categorization_small'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/event_rate_nanos'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/bm_classification'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/ihp_outlier'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/egs_regression'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/module_sample_ecommerce'); + + await ml.testResources.resetKibanaTimeZone(); + }); + loadTestFile(require.resolve('./index_data_visualizer')); loadTestFile(require.resolve('./index_data_visualizer_grid_in_discover')); loadTestFile(require.resolve('./index_data_visualizer_grid_in_dashboard')); diff --git a/x-pack/test/functional/apps/ml/group1/config.ts b/x-pack/test/functional/apps/ml/group1/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/ml/group1/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/classification_creation.ts similarity index 98% rename from x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/classification_creation.ts index 2ba4ac6f08350..0cf7c4177f057 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/classification_creation.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { AnalyticsTableRowDetails } from '../../../services/ml/data_frame_analytics_table'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { AnalyticsTableRowDetails } from '../../../../services/ml/data_frame_analytics_table'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation_saved_search.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/classification_creation_saved_search.ts similarity index 98% rename from x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation_saved_search.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/classification_creation_saved_search.ts index 67550ae17a4b0..cfba10c25b17b 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation_saved_search.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/classification_creation_saved_search.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { AnalyticsTableRowDetails } from '../../../services/ml/data_frame_analytics_table'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { AnalyticsTableRowDetails } from '../../../../services/ml/data_frame_analytics_table'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/cloning.ts similarity index 99% rename from x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/cloning.ts index 3a33c95edba42..82f76e66b4ebd 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/cloning.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/cloning.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { DeepPartial } from '@kbn/ml-plugin/common/types/common'; import { DataFrameAnalyticsConfig } from '@kbn/ml-plugin/public/application/data_frame_analytics/common'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/index.ts similarity index 93% rename from x-pack/test/functional/apps/ml/data_frame_analytics/index.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/index.ts index bc11a44148546..cf9bd17f11b81 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('data frame analytics', function () { diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation.ts similarity index 98% rename from x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation.ts index 1dacd8a7e80b4..8a53528a89922 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; -import { AnalyticsTableRowDetails } from '../../../services/ml/data_frame_analytics_table'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { AnalyticsTableRowDetails } from '../../../../services/ml/data_frame_analytics_table'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation_saved_search.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation_saved_search.ts similarity index 99% rename from x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation_saved_search.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation_saved_search.ts index 861be18591a11..89247aed78ac4 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/outlier_detection_creation_saved_search.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation_saved_search.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { AnalyticsTableRowDetails } from '../../../services/ml/data_frame_analytics_table'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { AnalyticsTableRowDetails } from '../../../../services/ml/data_frame_analytics_table'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/regression_creation.ts similarity index 98% rename from x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/regression_creation.ts index 7a84c41aa4a66..a0cbd123b5169 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/regression_creation.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; -import { AnalyticsTableRowDetails } from '../../../services/ml/data_frame_analytics_table'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { AnalyticsTableRowDetails } from '../../../../services/ml/data_frame_analytics_table'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation_saved_search.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/regression_creation_saved_search.ts similarity index 98% rename from x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation_saved_search.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/regression_creation_saved_search.ts index e22c4908486d1..6b09b35c610a0 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/regression_creation_saved_search.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/regression_creation_saved_search.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { AnalyticsTableRowDetails } from '../../../services/ml/data_frame_analytics_table'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { AnalyticsTableRowDetails } from '../../../../services/ml/data_frame_analytics_table'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/results_view_content.ts similarity index 99% rename from x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts rename to x-pack/test/functional/apps/ml/group1/data_frame_analytics/results_view_content.ts index 2bddf0a7d9512..8d04c4897dab0 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/results_view_content.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/results_view_content.ts @@ -8,7 +8,7 @@ import { DeepPartial } from '@kbn/ml-plugin/common/types/common'; import { DataFrameAnalyticsConfig } from '@kbn/ml-plugin/public/application/data_frame_analytics/common'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/index.ts b/x-pack/test/functional/apps/ml/group1/index.ts similarity index 64% rename from x-pack/test/functional/apps/ml/index.ts rename to x-pack/test/functional/apps/ml/group1/index.ts index c58b20e1c374b..7129f3e24d4f1 100644 --- a/x-pack/test/functional/apps/ml/index.ts +++ b/x-pack/test/functional/apps/ml/group1/index.ts @@ -5,13 +5,13 @@ * 2.0. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService, loadTestFile }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); - describe('machine learning', function () { + describe('machine learning - group 2', () => { before(async () => { await ml.securityCommon.createMlRoles(); await ml.securityCommon.createMlUsers(); @@ -37,26 +37,9 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { await ml.testResources.resetKibanaTimeZone(); }); - describe('', function () { - this.tags('ciGroup15'); - loadTestFile(require.resolve('./permissions')); - loadTestFile(require.resolve('./pages')); - loadTestFile(require.resolve('./data_visualizer')); - loadTestFile(require.resolve('./data_frame_analytics')); - loadTestFile(require.resolve('./model_management')); - }); - - describe('', function () { - this.tags('ciGroup26'); - loadTestFile(require.resolve('./anomaly_detection')); - }); - - describe('', function () { - this.tags('ciGroup8'); - loadTestFile(require.resolve('./feature_controls')); - loadTestFile(require.resolve('./settings')); - loadTestFile(require.resolve('./embeddables')); - loadTestFile(require.resolve('./stack_management_jobs')); - }); + loadTestFile(require.resolve('./permissions')); + loadTestFile(require.resolve('./pages')); + loadTestFile(require.resolve('./data_frame_analytics')); + loadTestFile(require.resolve('./model_management')); }); } diff --git a/x-pack/test/functional/apps/ml/model_management/index.ts b/x-pack/test/functional/apps/ml/group1/model_management/index.ts similarity index 86% rename from x-pack/test/functional/apps/ml/model_management/index.ts rename to x-pack/test/functional/apps/ml/group1/model_management/index.ts index e958392d9ba74..5595486260dee 100644 --- a/x-pack/test/functional/apps/ml/model_management/index.ts +++ b/x-pack/test/functional/apps/ml/group1/model_management/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('model management', function () { diff --git a/x-pack/test/functional/apps/ml/model_management/model_list.ts b/x-pack/test/functional/apps/ml/group1/model_management/model_list.ts similarity index 99% rename from x-pack/test/functional/apps/ml/model_management/model_list.ts rename to x-pack/test/functional/apps/ml/group1/model_management/model_list.ts index 08fb3b7124aec..ca360130b89f9 100644 --- a/x-pack/test/functional/apps/ml/model_management/model_list.ts +++ b/x-pack/test/functional/apps/ml/group1/model_management/model_list.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const ml = getService('ml'); diff --git a/x-pack/test/functional/apps/ml/pages.ts b/x-pack/test/functional/apps/ml/group1/pages.ts similarity index 94% rename from x-pack/test/functional/apps/ml/pages.ts rename to x-pack/test/functional/apps/ml/group1/pages.ts index 6c8687d213cee..2cc271e67194e 100644 --- a/x-pack/test/functional/apps/ml/pages.ts +++ b/x-pack/test/functional/apps/ml/group1/pages.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../ftr_provider_context'; +import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const ml = getService('ml'); @@ -21,7 +21,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('loads the ML home page'); await ml.navigation.navigateToMl(); - await ml.testExecution.logTestStep('loads the overview page'); + await ml.testExecution.logTestStep('loads the overview page'); await ml.navigation.navigateToOverview(); await ml.testExecution.logTestStep('loads the anomaly detection area'); diff --git a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional/apps/ml/group1/permissions/full_ml_access.ts similarity index 98% rename from x-pack/test/functional/apps/ml/permissions/full_ml_access.ts rename to x-pack/test/functional/apps/ml/group1/permissions/full_ml_access.ts index 467bfc370e8e2..c632ae48b3f88 100644 --- a/x-pack/test/functional/apps/ml/permissions/full_ml_access.ts +++ b/x-pack/test/functional/apps/ml/group1/permissions/full_ml_access.ts @@ -5,11 +5,9 @@ * 2.0. */ -import path from 'path'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -import { USER } from '../../../services/ml/security_common'; +import { USER } from '../../../../services/ml/security_common'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); @@ -123,12 +121,8 @@ export default function ({ getService }: FtrProviderContext) { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - const uploadFilePath = path.join( - __dirname, - '..', - 'data_visualizer', - 'files_to_import', - 'artificial_server_log' + const uploadFilePath = require.resolve( + '../../data_visualizer/files_to_import/artificial_server_log' ); const expectedUploadFileTitle = 'artificial_server_log'; diff --git a/x-pack/test/functional/apps/ml/permissions/index.ts b/x-pack/test/functional/apps/ml/group1/permissions/index.ts similarity index 88% rename from x-pack/test/functional/apps/ml/permissions/index.ts rename to x-pack/test/functional/apps/ml/group1/permissions/index.ts index e777f241eaf85..23d7d6fe9e2b5 100644 --- a/x-pack/test/functional/apps/ml/permissions/index.ts +++ b/x-pack/test/functional/apps/ml/group1/permissions/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('permissions', function () { diff --git a/x-pack/test/functional/apps/ml/permissions/no_ml_access.ts b/x-pack/test/functional/apps/ml/group1/permissions/no_ml_access.ts similarity index 93% rename from x-pack/test/functional/apps/ml/permissions/no_ml_access.ts rename to x-pack/test/functional/apps/ml/group1/permissions/no_ml_access.ts index 6132e6e63b1b0..4a1c108b2fa5a 100644 --- a/x-pack/test/functional/apps/ml/permissions/no_ml_access.ts +++ b/x-pack/test/functional/apps/ml/group1/permissions/no_ml_access.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; -import { USER } from '../../../services/ml/security_common'; +import { USER } from '../../../../services/ml/security_common'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'error']); diff --git a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional/apps/ml/group1/permissions/read_ml_access.ts similarity index 98% rename from x-pack/test/functional/apps/ml/permissions/read_ml_access.ts rename to x-pack/test/functional/apps/ml/group1/permissions/read_ml_access.ts index fd9cb2cb4c79e..a18a6075055a6 100644 --- a/x-pack/test/functional/apps/ml/permissions/read_ml_access.ts +++ b/x-pack/test/functional/apps/ml/group1/permissions/read_ml_access.ts @@ -5,11 +5,9 @@ * 2.0. */ -import path from 'path'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -import { USER } from '../../../services/ml/security_common'; +import { USER } from '../../../../services/ml/security_common'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); @@ -117,12 +115,8 @@ export default function ({ getService }: FtrProviderContext) { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - const uploadFilePath = path.join( - __dirname, - '..', - 'data_visualizer', - 'files_to_import', - 'artificial_server_log' + const uploadFilePath = require.resolve( + '../../data_visualizer/files_to_import/artificial_server_log' ); const expectedUploadFileTitle = 'artificial_server_log'; diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/advanced_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/advanced_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/advanced_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/advanced_job.ts index 1fc4c87619f18..ba0d030cfcf6f 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/advanced_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/advanced_job.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; interface Detector { identifier: string; diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/aggregated_scripted_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/aggregated_scripted_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/aggregated_scripted_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/aggregated_scripted_job.ts index c47171c1cd75a..78974ecf1e64c 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/aggregated_scripted_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/aggregated_scripted_job.ts @@ -6,7 +6,7 @@ */ import { Datafeed, Job } from '@kbn/ml-plugin/common/types/anomaly_detection_jobs'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/annotations.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/annotations.ts index 3b36701e651a7..17c576281835a 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/annotations.ts @@ -6,7 +6,7 @@ */ import { Annotation } from '@kbn/ml-plugin/common/types/annotations'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/anomaly_explorer.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/anomaly_explorer.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/anomaly_explorer.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/anomaly_explorer.ts index bf6fcd10a9152..c71f4a5789fd2 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/anomaly_explorer.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/anomaly_explorer.ts @@ -6,7 +6,7 @@ */ import { Job, Datafeed } from '@kbn/ml-plugin/common/types/anomaly_detection_jobs'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; // @ts-expect-error not full interface const JOB_CONFIG: Job = { diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/categorization_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/categorization_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/categorization_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/categorization_job.ts index 555040ef8e59e..96c02f7827a58 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/categorization_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/categorization_job.ts @@ -6,7 +6,7 @@ */ import { CATEGORY_EXAMPLES_VALIDATION_STATUS } from '@kbn/ml-plugin/common/constants/categorization_job'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/custom_urls.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/custom_urls.ts similarity index 98% rename from x-pack/test/functional/apps/ml/anomaly_detection/custom_urls.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/custom_urls.ts index a83f5d814c028..1e6e020aff69c 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/custom_urls.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/custom_urls.ts @@ -7,12 +7,12 @@ import { Job, Datafeed } from '@kbn/ml-plugin/common/types/anomaly_detection_jobs'; import { TIME_RANGE_TYPE } from '@kbn/ml-plugin/public/application/jobs/components/custom_url_editor/constants'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import type { DiscoverUrlConfig, DashboardUrlConfig, OtherUrlConfig, -} from '../../../services/ml/job_table'; +} from '../../../../services/ml/job_table'; // @ts-expect-error doesn't implement the full interface const JOB_CONFIG: Job = { diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/date_nanos_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/date_nanos_job.ts index 0401d13780403..4b593aacbebf1 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/date_nanos_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/date_nanos_job.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; interface Detector { identifier: string; diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/forecasts.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/forecasts.ts similarity index 98% rename from x-pack/test/functional/apps/ml/anomaly_detection/forecasts.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/forecasts.ts index 964e0762d9322..b290789419ed8 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/forecasts.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/forecasts.ts @@ -6,7 +6,7 @@ */ import { Job, Datafeed } from '@kbn/ml-plugin/common/types/anomaly_detection_jobs'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; // @ts-expect-error not full interface const JOB_CONFIG: Job = { diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/index.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/index.ts similarity index 94% rename from x-pack/test/functional/apps/ml/anomaly_detection/index.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/index.ts index ed5f618f86644..a1127c0e71c77 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/index.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('anomaly detection', function () { diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/multi_metric_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/multi_metric_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/multi_metric_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/multi_metric_job.ts index 4786f51bdc414..783312b0d8608 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/multi_metric_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/multi_metric_job.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/population_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/population_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/population_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/population_job.ts index f522f5ebefd9a..af2573e21f93d 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/population_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/population_job.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/saved_search_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/saved_search_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/saved_search_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/saved_search_job.ts index f314052035ff1..72dbac602cf8f 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/saved_search_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/saved_search_job.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_job.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_job.ts index 8ec2e4a48e228..e698dd270e1a8 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_job.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job_without_datafeed_start.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_job_without_datafeed_start.ts similarity index 98% rename from x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job_without_datafeed_start.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_job_without_datafeed_start.ts index 8d08fb84a8f55..2afa284fcc3d7 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job_without_datafeed_start.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_job_without_datafeed_start.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_viewer.ts b/x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_viewer.ts similarity index 99% rename from x-pack/test/functional/apps/ml/anomaly_detection/single_metric_viewer.ts rename to x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_viewer.ts index c0946713a2564..b970a0efe5602 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_viewer.ts +++ b/x-pack/test/functional/apps/ml/group2/anomaly_detection/single_metric_viewer.ts @@ -6,7 +6,7 @@ */ import { Job, Datafeed } from '@kbn/ml-plugin/common/types/anomaly_detection_jobs'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; // @ts-expect-error not full interface const JOB_CONFIG: Job = { diff --git a/x-pack/test/functional/apps/ml/group2/config.ts b/x-pack/test/functional/apps/ml/group2/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/ml/group2/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/ml/group2/index.ts b/x-pack/test/functional/apps/ml/group2/index.ts new file mode 100644 index 0000000000000..4515715327e05 --- /dev/null +++ b/x-pack/test/functional/apps/ml/group2/index.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('machine learning - group 2', () => { + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + // NOTE: Logout needs to happen before anything else to avoid flaky behavior + await ml.securityUI.logout(); + + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote_small'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/ecommerce'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/categorization_small'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/event_rate_nanos'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/bm_classification'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/ihp_outlier'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/egs_regression'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/module_sample_ecommerce'); + + await ml.testResources.resetKibanaTimeZone(); + }); + + loadTestFile(require.resolve('./anomaly_detection')); + }); +} diff --git a/x-pack/test/functional/apps/ml/group3/config.ts b/x-pack/test/functional/apps/ml/group3/config.ts new file mode 100644 index 0000000000000..d927f93adeffd --- /dev/null +++ b/x-pack/test/functional/apps/ml/group3/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/ml/embeddables/anomaly_charts_dashboard_embeddables.ts b/x-pack/test/functional/apps/ml/group3/embeddables/anomaly_charts_dashboard_embeddables.ts similarity index 98% rename from x-pack/test/functional/apps/ml/embeddables/anomaly_charts_dashboard_embeddables.ts rename to x-pack/test/functional/apps/ml/group3/embeddables/anomaly_charts_dashboard_embeddables.ts index 89b733c21498f..68981de99fc9a 100644 --- a/x-pack/test/functional/apps/ml/embeddables/anomaly_charts_dashboard_embeddables.ts +++ b/x-pack/test/functional/apps/ml/group3/embeddables/anomaly_charts_dashboard_embeddables.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { JOB_CONFIG, DATAFEED_CONFIG, ML_EMBEDDABLE_TYPES } from './constants'; const testDataList = [ diff --git a/x-pack/test/functional/apps/ml/embeddables/anomaly_embeddables_migration.ts b/x-pack/test/functional/apps/ml/group3/embeddables/anomaly_embeddables_migration.ts similarity index 98% rename from x-pack/test/functional/apps/ml/embeddables/anomaly_embeddables_migration.ts rename to x-pack/test/functional/apps/ml/group3/embeddables/anomaly_embeddables_migration.ts index ed38ff7021a92..a4c50549f5aed 100644 --- a/x-pack/test/functional/apps/ml/embeddables/anomaly_embeddables_migration.ts +++ b/x-pack/test/functional/apps/ml/group3/embeddables/anomaly_embeddables_migration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { JOB_CONFIG, DATAFEED_CONFIG, ML_EMBEDDABLE_TYPES } from './constants'; const testDataList = [ diff --git a/x-pack/test/functional/apps/ml/embeddables/constants.ts b/x-pack/test/functional/apps/ml/group3/embeddables/constants.ts similarity index 100% rename from x-pack/test/functional/apps/ml/embeddables/constants.ts rename to x-pack/test/functional/apps/ml/group3/embeddables/constants.ts diff --git a/x-pack/test/functional/apps/ml/embeddables/index.ts b/x-pack/test/functional/apps/ml/group3/embeddables/index.ts similarity index 88% rename from x-pack/test/functional/apps/ml/embeddables/index.ts rename to x-pack/test/functional/apps/ml/group3/embeddables/index.ts index 31074a59866a6..d786491e55a4e 100644 --- a/x-pack/test/functional/apps/ml/embeddables/index.ts +++ b/x-pack/test/functional/apps/ml/group3/embeddables/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('embeddables', function () { diff --git a/x-pack/test/functional/apps/ml/feature_controls/index.ts b/x-pack/test/functional/apps/ml/group3/feature_controls/index.ts similarity index 87% rename from x-pack/test/functional/apps/ml/feature_controls/index.ts rename to x-pack/test/functional/apps/ml/group3/feature_controls/index.ts index ffe419b506fd6..ab0988c424761 100644 --- a/x-pack/test/functional/apps/ml/feature_controls/index.ts +++ b/x-pack/test/functional/apps/ml/group3/feature_controls/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('feature controls', function () { diff --git a/x-pack/test/functional/apps/ml/feature_controls/ml_security.ts b/x-pack/test/functional/apps/ml/group3/feature_controls/ml_security.ts similarity index 98% rename from x-pack/test/functional/apps/ml/feature_controls/ml_security.ts rename to x-pack/test/functional/apps/ml/group3/feature_controls/ml_security.ts index 58af3abbf6a47..fd498f00a8262 100644 --- a/x-pack/test/functional/apps/ml/feature_controls/ml_security.ts +++ b/x-pack/test/functional/apps/ml/group3/feature_controls/ml_security.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const security = getService('security'); diff --git a/x-pack/test/functional/apps/ml/feature_controls/ml_spaces.ts b/x-pack/test/functional/apps/ml/group3/feature_controls/ml_spaces.ts similarity index 97% rename from x-pack/test/functional/apps/ml/feature_controls/ml_spaces.ts rename to x-pack/test/functional/apps/ml/group3/feature_controls/ml_spaces.ts index 1ea0e1e717e5f..0352a0059ba55 100644 --- a/x-pack/test/functional/apps/ml/feature_controls/ml_spaces.ts +++ b/x-pack/test/functional/apps/ml/group3/feature_controls/ml_spaces.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const spacesService = getService('spaces'); diff --git a/x-pack/test/functional/apps/ml/group3/index.ts b/x-pack/test/functional/apps/ml/group3/index.ts new file mode 100644 index 0000000000000..e85b95b274720 --- /dev/null +++ b/x-pack/test/functional/apps/ml/group3/index.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const ml = getService('ml'); + + describe('machine learning - group 3', function () { + before(async () => { + await ml.securityCommon.createMlRoles(); + await ml.securityCommon.createMlUsers(); + }); + + after(async () => { + // NOTE: Logout needs to happen before anything else to avoid flaky behavior + await ml.securityUI.logout(); + + await ml.securityCommon.cleanMlUsers(); + await ml.securityCommon.cleanMlRoles(); + + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/farequote_small'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/ecommerce'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/categorization_small'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/event_rate_nanos'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/bm_classification'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/ihp_outlier'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/egs_regression'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/module_sample_ecommerce'); + + await ml.testResources.resetKibanaTimeZone(); + }); + + loadTestFile(require.resolve('./feature_controls')); + loadTestFile(require.resolve('./settings')); + loadTestFile(require.resolve('./embeddables')); + loadTestFile(require.resolve('./stack_management_jobs')); + }); +} diff --git a/x-pack/test/functional/apps/ml/settings/calendar_creation.ts b/x-pack/test/functional/apps/ml/group3/settings/calendar_creation.ts similarity index 98% rename from x-pack/test/functional/apps/ml/settings/calendar_creation.ts rename to x-pack/test/functional/apps/ml/group3/settings/calendar_creation.ts index f0f5cd71cafe7..91121528d477a 100644 --- a/x-pack/test/functional/apps/ml/settings/calendar_creation.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/calendar_creation.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { asyncForEach, createJobConfig } from './common'; export default function ({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/apps/ml/settings/calendar_delete.ts b/x-pack/test/functional/apps/ml/group3/settings/calendar_delete.ts similarity index 96% rename from x-pack/test/functional/apps/ml/settings/calendar_delete.ts rename to x-pack/test/functional/apps/ml/group3/settings/calendar_delete.ts index ff417a32c1d7c..28b526147c96e 100644 --- a/x-pack/test/functional/apps/ml/settings/calendar_delete.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/calendar_delete.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { asyncForEach } from './common'; export default function ({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/apps/ml/settings/calendar_edit.ts b/x-pack/test/functional/apps/ml/group3/settings/calendar_edit.ts similarity index 98% rename from x-pack/test/functional/apps/ml/settings/calendar_edit.ts rename to x-pack/test/functional/apps/ml/group3/settings/calendar_edit.ts index 70c3e50ec309b..9f68ccc8a1196 100644 --- a/x-pack/test/functional/apps/ml/settings/calendar_edit.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/calendar_edit.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { asyncForEach, createJobConfig } from './common'; export default function ({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/apps/ml/settings/common.ts b/x-pack/test/functional/apps/ml/group3/settings/common.ts similarity index 89% rename from x-pack/test/functional/apps/ml/settings/common.ts rename to x-pack/test/functional/apps/ml/group3/settings/common.ts index f161ae637e3ad..77d798ecf241b 100644 --- a/x-pack/test/functional/apps/ml/settings/common.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/common.ts @@ -5,7 +5,10 @@ * 2.0. */ -export async function asyncForEach(array: T[], callback: (item: T, index: number) => void) { +export async function asyncForEach( + array: T[], + callback: (item: T, index: number) => Promise +) { for (let index = 0; index < array.length; index++) { await callback(array[index], index); } diff --git a/x-pack/test/functional/apps/ml/settings/filter_list_creation.ts b/x-pack/test/functional/apps/ml/group3/settings/filter_list_creation.ts similarity index 96% rename from x-pack/test/functional/apps/ml/settings/filter_list_creation.ts rename to x-pack/test/functional/apps/ml/group3/settings/filter_list_creation.ts index 3938b73a131f4..38ee8a3e6e4c2 100644 --- a/x-pack/test/functional/apps/ml/settings/filter_list_creation.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/filter_list_creation.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const ml = getService('ml'); diff --git a/x-pack/test/functional/apps/ml/settings/filter_list_delete.ts b/x-pack/test/functional/apps/ml/group3/settings/filter_list_delete.ts similarity index 96% rename from x-pack/test/functional/apps/ml/settings/filter_list_delete.ts rename to x-pack/test/functional/apps/ml/group3/settings/filter_list_delete.ts index aad56ffe55606..cdbf26ea12a03 100644 --- a/x-pack/test/functional/apps/ml/settings/filter_list_delete.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/filter_list_delete.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { asyncForEach } from './common'; export default function ({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/apps/ml/settings/filter_list_edit.ts b/x-pack/test/functional/apps/ml/group3/settings/filter_list_edit.ts similarity index 97% rename from x-pack/test/functional/apps/ml/settings/filter_list_edit.ts rename to x-pack/test/functional/apps/ml/group3/settings/filter_list_edit.ts index 7acd1b2bbc123..0a4c4f63ee741 100644 --- a/x-pack/test/functional/apps/ml/settings/filter_list_edit.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/filter_list_edit.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { asyncForEach } from './common'; export default function ({ getService }: FtrProviderContext) { diff --git a/x-pack/test/functional/apps/ml/settings/index.ts b/x-pack/test/functional/apps/ml/group3/settings/index.ts similarity index 91% rename from x-pack/test/functional/apps/ml/settings/index.ts rename to x-pack/test/functional/apps/ml/group3/settings/index.ts index e904eaedb8db0..9ac25b7fc9483 100644 --- a/x-pack/test/functional/apps/ml/settings/index.ts +++ b/x-pack/test/functional/apps/ml/group3/settings/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('settings', function () { diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/export_jobs.ts b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/export_jobs.ts similarity index 99% rename from x-pack/test/functional/apps/ml/stack_management_jobs/export_jobs.ts rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/export_jobs.ts index 85e249861378f..4ced89e35d608 100644 --- a/x-pack/test/functional/apps/ml/stack_management_jobs/export_jobs.ts +++ b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/export_jobs.ts @@ -7,7 +7,7 @@ import { Job, Datafeed } from '@kbn/ml-plugin/common/types/anomaly_detection_jobs'; import type { DataFrameAnalyticsConfig } from '@kbn/ml-plugin/public/application/data_frame_analytics/common'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; const testADJobs: Array<{ job: Job; datafeed: Datafeed }> = [ { diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/files_to_import/anomaly_detection_jobs_7.16.json b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/files_to_import/anomaly_detection_jobs_7.16.json similarity index 100% rename from x-pack/test/functional/apps/ml/stack_management_jobs/files_to_import/anomaly_detection_jobs_7.16.json rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/files_to_import/anomaly_detection_jobs_7.16.json diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/files_to_import/bad_data.json b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/files_to_import/bad_data.json similarity index 100% rename from x-pack/test/functional/apps/ml/stack_management_jobs/files_to_import/bad_data.json rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/files_to_import/bad_data.json diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/files_to_import/data_frame_analytics_jobs_7.16.json b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/files_to_import/data_frame_analytics_jobs_7.16.json similarity index 100% rename from x-pack/test/functional/apps/ml/stack_management_jobs/files_to_import/data_frame_analytics_jobs_7.16.json rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/files_to_import/data_frame_analytics_jobs_7.16.json diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/import_jobs.ts b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/import_jobs.ts similarity index 92% rename from x-pack/test/functional/apps/ml/stack_management_jobs/import_jobs.ts rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/import_jobs.ts index ef367797ef7e9..212bb029b6e0b 100644 --- a/x-pack/test/functional/apps/ml/stack_management_jobs/import_jobs.ts +++ b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/import_jobs.ts @@ -5,17 +5,15 @@ * 2.0. */ -import path from 'path'; - import { JobType } from '@kbn/ml-plugin/common/types/saved_objects'; -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); const testDataListPositive = [ { - filePath: path.join(__dirname, 'files_to_import', 'anomaly_detection_jobs_7.16.json'), + filePath: require.resolve('./files_to_import/anomaly_detection_jobs_7.16.json'), expected: { jobType: 'anomaly-detector' as JobType, jobIds: ['ad-test1', 'ad-test3'], @@ -23,7 +21,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, { - filePath: path.join(__dirname, 'files_to_import', 'data_frame_analytics_jobs_7.16.json'), + filePath: require.resolve('./files_to_import/data_frame_analytics_jobs_7.16.json'), expected: { jobType: 'data-frame-analytics' as JobType, jobIds: ['dfa-test1'], @@ -107,7 +105,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('selects job import'); await ml.stackManagementJobs.openImportFlyout(); await ml.stackManagementJobs.selectFileToImport( - path.join(__dirname, 'files_to_import', 'bad_data.json'), + require.resolve('./files_to_import/bad_data.json'), true ); }); diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/index.ts b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/index.ts similarity index 89% rename from x-pack/test/functional/apps/ml/stack_management_jobs/index.ts rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/index.ts index c5e0728266bab..4c4bedfeb9b76 100644 --- a/x-pack/test/functional/apps/ml/stack_management_jobs/index.ts +++ b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('stack management jobs', function () { diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/manage_spaces.ts b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/manage_spaces.ts similarity index 99% rename from x-pack/test/functional/apps/ml/stack_management_jobs/manage_spaces.ts rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/manage_spaces.ts index 4841fca9d74f7..5563bb9043c7f 100644 --- a/x-pack/test/functional/apps/ml/stack_management_jobs/manage_spaces.ts +++ b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/manage_spaces.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const browser = getService('browser'); diff --git a/x-pack/test/functional/apps/ml/stack_management_jobs/synchronize.ts b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/synchronize.ts similarity index 98% rename from x-pack/test/functional/apps/ml/stack_management_jobs/synchronize.ts rename to x-pack/test/functional/apps/ml/group3/stack_management_jobs/synchronize.ts index cf22f29bc277f..e760549b7a151 100644 --- a/x-pack/test/functional/apps/ml/stack_management_jobs/synchronize.ts +++ b/x-pack/test/functional/apps/ml/group3/stack_management_jobs/synchronize.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { FtrProviderContext } from '../../../ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); diff --git a/x-pack/test/functional/apps/monitoring/config.ts b/x-pack/test/functional/apps/monitoring/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/monitoring/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/monitoring/index.js b/x-pack/test/functional/apps/monitoring/index.js index b8f6f223092f6..cfa29d2f784e6 100644 --- a/x-pack/test/functional/apps/monitoring/index.js +++ b/x-pack/test/functional/apps/monitoring/index.js @@ -7,7 +7,6 @@ export default function ({ loadTestFile }) { describe('Monitoring app', function () { - this.tags('ciGroup28'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./cluster/list')); diff --git a/x-pack/test/functional/apps/remote_clusters/config.ts b/x-pack/test/functional/apps/remote_clusters/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/remote_clusters/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/remote_clusters/index.ts b/x-pack/test/functional/apps/remote_clusters/index.ts index a1cc660b6426a..74c4ce6e68bfc 100644 --- a/x-pack/test/functional/apps/remote_clusters/index.ts +++ b/x-pack/test/functional/apps/remote_clusters/index.ts @@ -12,7 +12,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; // https://www.elastic.co/guide/en/kibana/7.9/working-remote-clusters.html export default ({ loadTestFile }: FtrProviderContext) => { describe('Remote Clusters app', function () { - this.tags(['ciGroup4', 'skipCloud']); + this.tags('skipCloud'); loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./home_page')); }); diff --git a/x-pack/test/functional/apps/reporting/README.md b/x-pack/test/functional/apps/reporting/README.md index ec9bba8b88341..5d47804fef284 100644 --- a/x-pack/test/functional/apps/reporting/README.md +++ b/x-pack/test/functional/apps/reporting/README.md @@ -5,7 +5,7 @@ Functional tests on report generation are under the applications that use report **PDF/PNG Report testing:** - `x-pack/test/functional/apps/canvas/reports.ts` - `x-pack/test/functional/apps/dashboard/reporting/screenshots.ts` - - `x-pack/test/functional/apps/lens/lens_reporting.ts` + - `x-pack/test/functional/apps/lens/group3/lens_reporting.ts` - `x-pack/test/functional/apps/visualize/reporting.ts` **CSV Report testing:** diff --git a/x-pack/test/functional/apps/reporting_management/config.ts b/x-pack/test/functional/apps/reporting_management/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/reporting_management/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/reporting_management/index.js b/x-pack/test/functional/apps/reporting_management/index.js index 4e6abe85a4041..dcf5583eeb92a 100644 --- a/x-pack/test/functional/apps/reporting_management/index.js +++ b/x-pack/test/functional/apps/reporting_management/index.js @@ -7,7 +7,6 @@ export default ({ loadTestFile }) => { describe('reporting management app', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./report_listing')); }); }; diff --git a/x-pack/test/functional/apps/rollup_job/config.ts b/x-pack/test/functional/apps/rollup_job/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/rollup_job/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/rollup_job/index.js b/x-pack/test/functional/apps/rollup_job/index.js index 8fa9cd6f7aa72..943536539c5ad 100644 --- a/x-pack/test/functional/apps/rollup_job/index.js +++ b/x-pack/test/functional/apps/rollup_job/index.js @@ -7,8 +7,6 @@ export default function ({ loadTestFile }) { describe('rollup app', function () { - this.tags('ciGroup28'); - loadTestFile(require.resolve('./rollup_jobs')); loadTestFile(require.resolve('./hybrid_index_pattern')); loadTestFile(require.resolve('./tsvb')); diff --git a/x-pack/test/functional/apps/saved_objects_management/config.ts b/x-pack/test/functional/apps/saved_objects_management/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/saved_objects_management/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/saved_objects_management/index.ts b/x-pack/test/functional/apps/saved_objects_management/index.ts index 17cdae0707213..dc0dae5134f50 100644 --- a/x-pack/test/functional/apps/saved_objects_management/index.ts +++ b/x-pack/test/functional/apps/saved_objects_management/index.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function savedObjectsManagementApp({ loadTestFile }: FtrProviderContext) { describe('Saved objects management', function savedObjectsManagementAppTestSuite() { - this.tags(['ciGroup2', 'skipFirefox']); + this.tags('skipFirefox'); loadTestFile(require.resolve('./spaces_integration')); loadTestFile(require.resolve('./feature_controls/saved_objects_management_security')); diff --git a/x-pack/test/functional/apps/security/basic_license/index.ts b/x-pack/test/functional/apps/security/basic_license/index.ts index 771874f853de4..04e55abb9bac1 100644 --- a/x-pack/test/functional/apps/security/basic_license/index.ts +++ b/x-pack/test/functional/apps/security/basic_license/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security app - basic license', function () { - this.tags('ciGroup4'); - loadTestFile(require.resolve('./role_mappings')); }); } diff --git a/x-pack/test/functional/apps/security/config.ts b/x-pack/test/functional/apps/security/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/security/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/security/index.ts b/x-pack/test/functional/apps/security/index.ts index fc9caafbabb29..3260e61e67cbf 100644 --- a/x-pack/test/functional/apps/security/index.ts +++ b/x-pack/test/functional/apps/security/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security app', function () { - this.tags('ciGroup7'); - loadTestFile(require.resolve('./security')); loadTestFile(require.resolve('./doc_level_security_roles')); loadTestFile(require.resolve('./management')); diff --git a/x-pack/test/functional/apps/snapshot_restore/config.ts b/x-pack/test/functional/apps/snapshot_restore/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/snapshot_restore/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/snapshot_restore/index.ts b/x-pack/test/functional/apps/snapshot_restore/index.ts index 95fc0b80c2c91..0eefd3884cd31 100644 --- a/x-pack/test/functional/apps/snapshot_restore/index.ts +++ b/x-pack/test/functional/apps/snapshot_restore/index.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Snapshots app', function () { - this.tags(['ciGroup4', 'skipCloud']); + this.tags('skipCloud'); loadTestFile(require.resolve('./home_page')); }); }; diff --git a/x-pack/test/functional/apps/spaces/config.ts b/x-pack/test/functional/apps/spaces/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/spaces/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/spaces/index.ts b/x-pack/test/functional/apps/spaces/index.ts index 780d355e1f5c6..c951609d6a33f 100644 --- a/x-pack/test/functional/apps/spaces/index.ts +++ b/x-pack/test/functional/apps/spaces/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function spacesApp({ loadTestFile }: FtrProviderContext) { describe('Spaces app', function spacesAppTestSuite() { - this.tags('ciGroup9'); - loadTestFile(require.resolve('./copy_saved_objects')); loadTestFile(require.resolve('./feature_controls/spaces_security')); loadTestFile(require.resolve('./spaces_selection')); diff --git a/x-pack/test/functional/apps/status_page/config.ts b/x-pack/test/functional/apps/status_page/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/status_page/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/status_page/index.ts b/x-pack/test/functional/apps/status_page/index.ts index 69b18984f0ade..cdf6bb52ee605 100644 --- a/x-pack/test/functional/apps/status_page/index.ts +++ b/x-pack/test/functional/apps/status_page/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function statusPage({ loadTestFile }: FtrProviderContext) { describe('Status page', function statusPageTestSuite() { - this.tags('ciGroup4'); - loadTestFile(require.resolve('./status_page')); }); } diff --git a/x-pack/test/functional/apps/transform/config.ts b/x-pack/test/functional/apps/transform/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/transform/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/transform/index.ts b/x-pack/test/functional/apps/transform/index.ts index 181325e83b36b..0c5227ae2f472 100644 --- a/x-pack/test/functional/apps/transform/index.ts +++ b/x-pack/test/functional/apps/transform/index.ts @@ -16,7 +16,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const transform = getService('transform'); describe('transform', function () { - this.tags(['ciGroup21', 'transform']); + this.tags('transform'); before(async () => { await transform.securityCommon.createTransformRoles(); diff --git a/x-pack/test/functional/apps/upgrade_assistant/config.ts b/x-pack/test/functional/apps/upgrade_assistant/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/upgrade_assistant/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/upgrade_assistant/index.ts b/x-pack/test/functional/apps/upgrade_assistant/index.ts index d1ab46463e930..fcb9dd4ba7cca 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/index.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function upgradeCheckup({ loadTestFile }: FtrProviderContext) { describe('Upgrade Assistant', function upgradeAssistantTestSuite() { - this.tags('ciGroup4'); - loadTestFile(require.resolve('./feature_controls')); loadTestFile(require.resolve('./deprecation_pages')); loadTestFile(require.resolve('./overview_page')); diff --git a/x-pack/test/functional/apps/uptime/config.ts b/x-pack/test/functional/apps/uptime/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/uptime/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/uptime/index.ts b/x-pack/test/functional/apps/uptime/index.ts index cc0578602951a..99359ee126502 100644 --- a/x-pack/test/functional/apps/uptime/index.ts +++ b/x-pack/test/functional/apps/uptime/index.ts @@ -42,8 +42,6 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => { const uptime = getService('uptime'); describe('Uptime app', function () { - this.tags('ciGroup10'); - beforeEach('delete settings', async () => { await deleteUptimeSettingsObject(server); }); diff --git a/x-pack/test/functional/apps/visualize/config.ts b/x-pack/test/functional/apps/visualize/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/visualize/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/visualize/index.ts b/x-pack/test/functional/apps/visualize/index.ts index 105303aa1b537..c99182201eb5d 100644 --- a/x-pack/test/functional/apps/visualize/index.ts +++ b/x-pack/test/functional/apps/visualize/index.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function visualize({ loadTestFile }: FtrProviderContext) { describe('Visualize', function visualizeTestSuite() { - this.tags(['ciGroup30', 'skipFirefox']); + this.tags('skipFirefox'); loadTestFile(require.resolve('./feature_controls/visualize_security')); loadTestFile(require.resolve('./feature_controls/visualize_spaces')); diff --git a/x-pack/test/functional/apps/watcher/config.ts b/x-pack/test/functional/apps/watcher/config.ts new file mode 100644 index 0000000000000..d0d07ff200281 --- /dev/null +++ b/x-pack/test/functional/apps/watcher/config.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/x-pack/test/functional/apps/watcher/index.js b/x-pack/test/functional/apps/watcher/index.js index fb39fe4aa7b29..fab662b26e80c 100644 --- a/x-pack/test/functional/apps/watcher/index.js +++ b/x-pack/test/functional/apps/watcher/index.js @@ -7,7 +7,7 @@ export default function ({ loadTestFile }) { describe('watcher app', function () { - this.tags(['ciGroup28', 'includeFirefox']); + this.tags('includeFirefox'); loadTestFile(require.resolve('./watcher_test')); }); diff --git a/x-pack/test/functional/config.js b/x-pack/test/functional/config.base.js similarity index 88% rename from x-pack/test/functional/config.js rename to x-pack/test/functional/config.base.js index 8d39f26d4569d..b5b671a54744e 100644 --- a/x-pack/test/functional/config.js +++ b/x-pack/test/functional/config.base.js @@ -24,52 +24,10 @@ export default async function ({ readConfigFile }) { require.resolve('../../../test/common/config.js') ); const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); return { - // list paths to the files that contain your plugins tests - testFiles: [ - resolve(__dirname, './apps/home'), - resolve(__dirname, './apps/advanced_settings'), - resolve(__dirname, './apps/canvas'), - resolve(__dirname, './apps/graph'), - resolve(__dirname, './apps/monitoring'), - resolve(__dirname, './apps/watcher'), - resolve(__dirname, './apps/dashboard'), - resolve(__dirname, './apps/discover'), - resolve(__dirname, './apps/security'), - resolve(__dirname, './apps/spaces'), - resolve(__dirname, './apps/logstash'), - resolve(__dirname, './apps/grok_debugger'), - resolve(__dirname, './apps/infra'), - resolve(__dirname, './apps/ml'), - resolve(__dirname, './apps/rollup_job'), - resolve(__dirname, './apps/maps'), - resolve(__dirname, './apps/status_page'), - resolve(__dirname, './apps/upgrade_assistant'), - resolve(__dirname, './apps/visualize'), - resolve(__dirname, './apps/uptime'), - resolve(__dirname, './apps/saved_objects_management'), - resolve(__dirname, './apps/dev_tools'), - resolve(__dirname, './apps/apm'), - resolve(__dirname, './apps/api_keys'), - resolve(__dirname, './apps/data_views'), - resolve(__dirname, './apps/index_management'), - resolve(__dirname, './apps/index_lifecycle_management'), - resolve(__dirname, './apps/ingest_pipelines'), - resolve(__dirname, './apps/snapshot_restore'), - resolve(__dirname, './apps/cross_cluster_replication'), - resolve(__dirname, './apps/remote_clusters'), - resolve(__dirname, './apps/transform'), - resolve(__dirname, './apps/reporting_management'), - resolve(__dirname, './apps/management'), - resolve(__dirname, './apps/lens'), // smokescreen tests cause flakiness in other tests - - // This license_management file must be last because it is destructive. - resolve(__dirname, './apps/license_management'), - ], - services, pageObjects, diff --git a/x-pack/test/functional/config.ccs.ts b/x-pack/test/functional/config.ccs.ts index e6e0da5293190..87bdb17e736bd 100644 --- a/x-pack/test/functional/config.ccs.ts +++ b/x-pack/test/functional/config.ccs.ts @@ -10,12 +10,12 @@ import { RemoteEsArchiverProvider } from './services/remote_es/remote_es_archive import { RemoteEsProvider } from './services/remote_es/remote_es'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('./config')); + const functionalConfig = await readConfigFile(require.resolve('./config.base.js')); return { ...functionalConfig.getAll(), - testFiles: [require.resolve('./apps/lens')], + testFiles: [require.resolve('./apps/lens/group1')], junit: { reportName: 'X-Pack CCS Tests', diff --git a/x-pack/test/functional/config.coverage.js b/x-pack/test/functional/config.coverage.js deleted file mode 100644 index b403fe933c4a3..0000000000000 --- a/x-pack/test/functional/config.coverage.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export default async function ({ readConfigFile }) { - const chromeConfig = await readConfigFile(require.resolve('./config')); - - return { - ...chromeConfig.getAll(), - - suiteTags: { - exclude: ['skipCoverage'], - }, - - junit: { - reportName: 'Code Coverage for Functional Tests', - }, - }; -} diff --git a/x-pack/test/functional/config.edge.js b/x-pack/test/functional/config.edge.js index b51b09d0f4878..58f35e844e283 100644 --- a/x-pack/test/functional/config.edge.js +++ b/x-pack/test/functional/config.edge.js @@ -6,10 +6,10 @@ */ export default async function ({ readConfigFile }) { - const chromeConfig = await readConfigFile(require.resolve('./config')); + const firefoxConfig = await readConfigFile(require.resolve('./config.firefox.js')); return { - ...chromeConfig.getAll(), + ...firefoxConfig.getAll(), browser: { type: 'msedge', diff --git a/x-pack/test/functional/config.firefox.js b/x-pack/test/functional/config.firefox.js index 148f3c454a859..91249df789de8 100644 --- a/x-pack/test/functional/config.firefox.js +++ b/x-pack/test/functional/config.firefox.js @@ -6,16 +6,26 @@ */ export default async function ({ readConfigFile }) { - const chromeConfig = await readConfigFile(require.resolve('./config')); + const chromeConfig = await readConfigFile(require.resolve('./config.base.js')); return { ...chromeConfig.getAll(), + testFiles: [ + require.resolve('./apps/canvas'), + require.resolve('./apps/infra'), + require.resolve('./apps/security'), + require.resolve('./apps/spaces'), + require.resolve('./apps/status_page'), + require.resolve('./apps/watcher'), + ], + browser: { type: 'firefox', }, suiteTags: { + include: ['includeFirefox'], exclude: ['skipFirefox'], }, diff --git a/x-pack/test/functional/config_security_basic.ts b/x-pack/test/functional/config_security_basic.ts index dc4bfc437347e..d56b91d45a63e 100644 --- a/x-pack/test/functional/config_security_basic.ts +++ b/x-pack/test/functional/config_security_basic.ts @@ -20,7 +20,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); return { diff --git a/x-pack/test/functional/services/ml/common_data_grid.ts b/x-pack/test/functional/services/ml/common_data_grid.ts index c48cf92107dab..444b01cce902f 100644 --- a/x-pack/test/functional/services/ml/common_data_grid.ts +++ b/x-pack/test/functional/services/ml/common_data_grid.ts @@ -8,8 +8,8 @@ import expect from '@kbn/expect'; import { chunk } from 'lodash'; import type { ProvidedType } from '@kbn/test'; +import { asyncForEachWithLimit } from '@kbn/std'; import type { FtrProviderContext } from '../../ftr_provider_context'; -import { asyncForEach } from '../../apps/ml/settings/common'; export interface SetValueOptions { clearWithKeyboard?: boolean; @@ -154,7 +154,7 @@ export function MachineLearningCommonDataGridProvider({ getService }: FtrProvide await find.byClassName('euiDataGrid__controlScroll') ).findAllByCssSelector('[role="switch"]'); - await asyncForEach(visibilityToggles, async (toggle) => { + await asyncForEachWithLimit(visibilityToggles, 1, async (toggle) => { const checked = (await toggle.getAttribute('aria-checked')) === 'true'; expect(checked).to.eql( expectedState, diff --git a/x-pack/test/functional_basic/apps/ml/index.ts b/x-pack/test/functional_basic/apps/ml/index.ts index af2fdc8c45f29..0188aa0361d94 100644 --- a/x-pack/test/functional_basic/apps/ml/index.ts +++ b/x-pack/test/functional_basic/apps/ml/index.ts @@ -12,7 +12,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const ml = getService('ml'); describe('machine learning basic license', function () { - this.tags(['ciGroup14', 'skipFirefox', 'mlqa']); + this.tags(['skipFirefox', 'mlqa']); before(async () => { await ml.securityCommon.createMlRoles(); diff --git a/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts index b44c5f08bdbc6..b90b97ca87a57 100644 --- a/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts +++ b/x-pack/test/functional_basic/apps/ml/permissions/full_ml_access.ts @@ -5,8 +5,6 @@ * 2.0. */ -import path from 'path'; - import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/ml/security_common'; @@ -26,18 +24,8 @@ export default function ({ getService }: FtrProviderContext) { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - const uploadFilePath = path.join( - __dirname, - '..', - '..', - '..', - '..', - 'functional', - 'apps', - 'ml', - 'data_visualizer', - 'files_to_import', - 'artificial_server_log' + const uploadFilePath = require.resolve( + '../../../../functional/apps/ml/data_visualizer/files_to_import/artificial_server_log' ); const expectedUploadFileTitle = 'artificial_server_log'; diff --git a/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts index c1b13d6dc1f11..fc293defceb86 100644 --- a/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts +++ b/x-pack/test/functional_basic/apps/ml/permissions/read_ml_access.ts @@ -5,8 +5,6 @@ * 2.0. */ -import path from 'path'; - import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/ml/security_common'; @@ -26,18 +24,8 @@ export default function ({ getService }: FtrProviderContext) { const ecIndexPattern = 'ft_module_sample_ecommerce'; const ecExpectedTotalCount = '287'; - const uploadFilePath = path.join( - __dirname, - '..', - '..', - '..', - '..', - 'functional', - 'apps', - 'ml', - 'data_visualizer', - 'files_to_import', - 'artificial_server_log' + const uploadFilePath = require.resolve( + '../../../../functional/apps/ml/data_visualizer/files_to_import/artificial_server_log' ); const expectedUploadFileTitle = 'artificial_server_log'; diff --git a/x-pack/test/functional_basic/config.ts b/x-pack/test/functional_basic/config.ts index e1dac88436e4c..f35ece0ce5d16 100644 --- a/x-pack/test/functional_basic/config.ts +++ b/x-pack/test/functional_basic/config.ts @@ -8,7 +8,9 @@ import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); return { // default to the xpack functional config diff --git a/x-pack/test/functional_cors/config.ts b/x-pack/test/functional_cors/config.ts index 738285b4ff40f..364be1383ae94 100644 --- a/x-pack/test/functional_cors/config.ts +++ b/x-pack/test/functional_cors/config.ts @@ -16,7 +16,9 @@ const pluginPort = process.env.TEST_CORS_SERVER_PORT : 5699; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const kibanaFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const kibanaFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); const corsTestPlugin = Path.resolve(__dirname, './plugins/kibana_cors_test'); diff --git a/x-pack/test/functional_cors/tests/index.ts b/x-pack/test/functional_cors/tests/index.ts index 424dac86c4f1a..3ca455eccd339 100644 --- a/x-pack/test/functional_cors/tests/index.ts +++ b/x-pack/test/functional_cors/tests/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Kibana cors', function () { - this.tags('ciGroup12'); loadTestFile(require.resolve('./cors')); }); } diff --git a/x-pack/test/functional_embedded/config.ts b/x-pack/test/functional_embedded/config.ts index 868d53ee17ee9..cdbbffea0eab9 100644 --- a/x-pack/test/functional_embedded/config.ts +++ b/x-pack/test/functional_embedded/config.ts @@ -12,7 +12,9 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { pageObjects } from '../functional/page_objects'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const kibanaFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const kibanaFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); const iframeEmbeddedPlugin = resolve(__dirname, './plugins/iframe_embedded'); diff --git a/x-pack/test/functional_embedded/tests/index.ts b/x-pack/test/functional_embedded/tests/index.ts index aa210aff19728..1c3f01febd6d4 100644 --- a/x-pack/test/functional_embedded/tests/index.ts +++ b/x-pack/test/functional_embedded/tests/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Kibana embedded', function () { - this.tags('ciGroup2'); loadTestFile(require.resolve('./iframe_embedded')); }); } diff --git a/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/index.ts b/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/index.ts index 653f0842ef1bb..dda2e20745394 100644 --- a/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/index.ts +++ b/x-pack/test/functional_enterprise_search/apps/enterprise_search/without_host_configured/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Enterprise Search', function () { - this.tags('ciGroup10'); - loadTestFile(require.resolve('./app_search/setup_guide')); loadTestFile(require.resolve('./workplace_search/setup_guide')); }); diff --git a/x-pack/test/functional_enterprise_search/base_config.ts b/x-pack/test/functional_enterprise_search/base_config.ts index 2c21ccf5c5c39..8f72e1ebd6503 100644 --- a/x-pack/test/functional_enterprise_search/base_config.ts +++ b/x-pack/test/functional_enterprise_search/base_config.ts @@ -10,7 +10,9 @@ import { pageObjects } from './page_objects'; import { services } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xPackFunctionalConfig = await readConfigFile(require.resolve('../functional/config')); + const xPackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); return { // default to the xpack functional config diff --git a/x-pack/test/functional_execution_context/config.ts b/x-pack/test/functional_execution_context/config.ts index 6169df6adcef3..caf88769b6a06 100644 --- a/x-pack/test/functional_execution_context/config.ts +++ b/x-pack/test/functional_execution_context/config.ts @@ -12,7 +12,7 @@ import { logFilePath } from './test_utils'; const alertTestPlugin = Path.resolve(__dirname, './fixtures/plugins/alerts'); export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); const servers = { ...functionalConfig.get('servers'), diff --git a/x-pack/test/functional_execution_context/tests/index.ts b/x-pack/test/functional_execution_context/tests/index.ts index c092be9bd8bdb..2c34783a9bae3 100644 --- a/x-pack/test/functional_execution_context/tests/index.ts +++ b/x-pack/test/functional_execution_context/tests/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Execution context', function () { - this.tags('ciGroup1'); loadTestFile(require.resolve('./browser')); loadTestFile(require.resolve('./server')); loadTestFile(require.resolve('./log_correlation')); diff --git a/x-pack/test/functional_synthetics/apps/uptime/index.ts b/x-pack/test/functional_synthetics/apps/uptime/index.ts index 925731c769bfc..64a9da5c30ea3 100644 --- a/x-pack/test/functional_synthetics/apps/uptime/index.ts +++ b/x-pack/test/functional_synthetics/apps/uptime/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile, getService }: FtrProviderContext) => { describe('Uptime app', function () { - this.tags('ciGroup8'); describe('with generated data', () => { loadTestFile(require.resolve('./synthetics_integration')); }); diff --git a/x-pack/test/functional_synthetics/config.js b/x-pack/test/functional_synthetics/config.js index 20488e3c52b2c..f5db09a5d60d9 100644 --- a/x-pack/test/functional_synthetics/config.js +++ b/x-pack/test/functional_synthetics/config.js @@ -28,7 +28,7 @@ export default async function ({ readConfigFile }) { require.resolve('../../../test/common/config.js') ); const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); // mount the config file for the package registry as well as diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/index.ts b/x-pack/test/functional_with_es_ssl/apps/cases/index.ts index 53d2c2d9767f1..04cceba32c8a7 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/index.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile }: FtrProviderContext) => { describe('Cases', function () { - this.tags('ciGroup27'); loadTestFile(require.resolve('./create_case_form')); loadTestFile(require.resolve('./view_case')); loadTestFile(require.resolve('./list_view')); diff --git a/x-pack/test/functional_with_es_ssl/apps/discover/index.ts b/x-pack/test/functional_with_es_ssl/apps/discover/index.ts index 708da2f02da74..f876140dbc92a 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover/index.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover/index.ts @@ -8,7 +8,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile, getService }: FtrProviderContext) => { describe('Discover alerting', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./search_source_alert')); }); }; diff --git a/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts index 9a486d4983d9c..4676004d9eb89 100644 --- a/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts @@ -68,8 +68,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { let testJobId = ''; describe('anomaly detection alert', function () { - this.tags('ciGroup13'); - before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/ecommerce'); await ml.testResources.createIndexPatternIfNeeded('ft_ecommerce', 'order_date'); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts index 9c57f29c6f707..73b084c2ce0e4 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default ({ loadTestFile, getService }: FtrProviderContext) => { describe('Actions and Triggers app', function () { - this.tags('ciGroup10'); loadTestFile(require.resolve('./home_page')); loadTestFile(require.resolve('./alerts_list')); loadTestFile(require.resolve('./alert_create_flyout')); diff --git a/x-pack/test/functional_with_es_ssl/apps/uptime/index.ts b/x-pack/test/functional_with_es_ssl/apps/uptime/index.ts index d2078267bde85..2c39ef045972f 100644 --- a/x-pack/test/functional_with_es_ssl/apps/uptime/index.ts +++ b/x-pack/test/functional_with_es_ssl/apps/uptime/index.ts @@ -14,8 +14,6 @@ export default ({ getService, loadTestFile }: FtrProviderContext) => { const kibanaServer = getService('kibanaServer'); describe('Uptime app', function () { - this.tags('ciGroup6'); - describe('with real-world data', () => { before(async () => { await esArchiver.load(ARCHIVE); diff --git a/x-pack/test/functional_with_es_ssl/config.ts b/x-pack/test/functional_with_es_ssl/config.ts index 4783ad683c0cf..4872d2fd6fa38 100644 --- a/x-pack/test/functional_with_es_ssl/config.ts +++ b/x-pack/test/functional_with_es_ssl/config.ts @@ -31,7 +31,9 @@ const enabledActionTypes = [ ]; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); const servers = { ...xpackFunctionalConfig.get('servers'), diff --git a/x-pack/test/licensing_plugin/config.ts b/x-pack/test/licensing_plugin/config.ts index 155d761020b29..c4b197c10a824 100644 --- a/x-pack/test/licensing_plugin/config.ts +++ b/x-pack/test/licensing_plugin/config.ts @@ -11,7 +11,9 @@ import { services, pageObjects } from './services'; const license = 'basic'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalTestsConfig = await readConfigFile(require.resolve('../functional/config.js')); + const functionalTestsConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); const servers = { ...functionalTestsConfig.get('servers'), diff --git a/x-pack/test/licensing_plugin/public/index.ts b/x-pack/test/licensing_plugin/public/index.ts index 194db6266b510..904b9eaecd757 100644 --- a/x-pack/test/licensing_plugin/public/index.ts +++ b/x-pack/test/licensing_plugin/public/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../services'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile }: FtrProviderContext) { describe('Licensing plugin public client', function () { - this.tags('ciGroup5'); loadTestFile(require.resolve('./feature_usage')); // MUST BE LAST! CHANGES LICENSE TYPE! loadTestFile(require.resolve('./updates')); diff --git a/x-pack/test/licensing_plugin/server/index.ts b/x-pack/test/licensing_plugin/server/index.ts index 619d29a4a2fd2..28426eba962b8 100644 --- a/x-pack/test/licensing_plugin/server/index.ts +++ b/x-pack/test/licensing_plugin/server/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../services'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile }: FtrProviderContext) { describe('Licensing plugin server client', function () { - this.tags('ciGroup13'); loadTestFile(require.resolve('./info')); loadTestFile(require.resolve('./header')); diff --git a/x-pack/test/lists_api_integration/security_and_spaces/tests/index.ts b/x-pack/test/lists_api_integration/security_and_spaces/tests/index.ts index c28447ef0ac18..95cce7e7fb85f 100644 --- a/x-pack/test/lists_api_integration/security_and_spaces/tests/index.ts +++ b/x-pack/test/lists_api_integration/security_and_spaces/tests/index.ts @@ -10,8 +10,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile }: FtrProviderContext): void => { describe('lists api security and spaces enabled', function () { - this.tags('ciGroup1'); - loadTestFile(require.resolve('./create_lists')); loadTestFile(require.resolve('./create_list_items')); loadTestFile(require.resolve('./read_lists')); diff --git a/x-pack/test/load/config.ts b/x-pack/test/load/config.ts index 2d20806f3e9e8..dcaa2031c9c02 100644 --- a/x-pack/test/load/config.ts +++ b/x-pack/test/load/config.ts @@ -21,7 +21,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('../functional/config.js') + require.resolve('../functional/config.base.js') ); return { diff --git a/x-pack/test/observability_api_integration/basic/tests/index.ts b/x-pack/test/observability_api_integration/basic/tests/index.ts index c62cf4be0d7c7..a1ea41e2b7c36 100644 --- a/x-pack/test/observability_api_integration/basic/tests/index.ts +++ b/x-pack/test/observability_api_integration/basic/tests/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) { describe('Observability specs (basic)', function () { - this.tags('ciGroup1'); loadTestFile(require.resolve('./annotations')); }); } diff --git a/x-pack/test/observability_api_integration/trial/tests/index.ts b/x-pack/test/observability_api_integration/trial/tests/index.ts index 037cf48275de2..e426efd90188c 100644 --- a/x-pack/test/observability_api_integration/trial/tests/index.ts +++ b/x-pack/test/observability_api_integration/trial/tests/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderContext) { describe('Observability specs (trial)', function () { - this.tags('ciGroup1'); loadTestFile(require.resolve('./annotations')); }); } diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index 9ec3791aef35f..d60f93f1285ad 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('ObservabilityApp', function () { - this.tags('ciGroup22'); - loadTestFile(require.resolve('./alerts')); loadTestFile(require.resolve('./alerts/add_to_case')); loadTestFile(require.resolve('./alerts/alert_disclaimer')); diff --git a/x-pack/test/observability_functional/with_rac_write.config.ts b/x-pack/test/observability_functional/with_rac_write.config.ts index 71a1de1df6a77..bc5b39358fedb 100644 --- a/x-pack/test/observability_functional/with_rac_write.config.ts +++ b/x-pack/test/observability_functional/with_rac_write.config.ts @@ -27,7 +27,9 @@ const enabledActionTypes = [ ]; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); const servers = { ...xpackFunctionalConfig.get('servers'), diff --git a/x-pack/test/osquery_cypress/config.ts b/x-pack/test/osquery_cypress/config.ts index 2bd39acfa1359..37f7b3f63b36c 100644 --- a/x-pack/test/osquery_cypress/config.ts +++ b/x-pack/test/osquery_cypress/config.ts @@ -14,7 +14,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('../functional/config.js') + require.resolve('../functional/config.base.js') ); return { diff --git a/x-pack/test/performance/config.playwright.ts b/x-pack/test/performance/config.playwright.ts index 9077c58a30e15..0b404d5c03bdb 100644 --- a/x-pack/test/performance/config.playwright.ts +++ b/x-pack/test/performance/config.playwright.ts @@ -15,7 +15,7 @@ const APM_SERVER_URL = 'https://kibana-ops-e2e-perf.apm.us-central1.gcp.cloud.es const APM_PUBLIC_TOKEN = 'CTs9y3cvcfq13bQqsB'; export default async function ({ readConfigFile, log }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); const testFiles = [require.resolve('./tests/playwright')]; diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/index.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/index.ts index c29367fb852ab..0901c96f522cc 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/index.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('event_log', function taskManagerSuite() { - this.tags('ciGroup6'); loadTestFile(require.resolve('./public_api_integration')); loadTestFile(require.resolve('./service_api_integration')); }); diff --git a/x-pack/test/plugin_api_integration/test_suites/licensed_feature_usage/index.ts b/x-pack/test/plugin_api_integration/test_suites/licensed_feature_usage/index.ts index 7f2a4c12a26eb..6ee46b58c4bcd 100644 --- a/x-pack/test/plugin_api_integration/test_suites/licensed_feature_usage/index.ts +++ b/x-pack/test/plugin_api_integration/test_suites/licensed_feature_usage/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Licensed feature usage APIs', function () { - this.tags('ciGroup13'); loadTestFile(require.resolve('./feature_usage')); }); } diff --git a/x-pack/test/plugin_api_integration/test_suites/platform/index.ts b/x-pack/test/plugin_api_integration/test_suites/platform/index.ts index 46c468e9b6d78..907ebfe6bdf79 100644 --- a/x-pack/test/plugin_api_integration/test_suites/platform/index.ts +++ b/x-pack/test/plugin_api_integration/test_suites/platform/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('platform', function taskManagerSuite() { - this.tags('ciGroup13'); loadTestFile(require.resolve('./elasticsearch_client')); }); } diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/index.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/index.ts index fe494ac33d461..2712069008598 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/index.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('task_manager', function taskManagerSuite() { - this.tags('ciGroup12'); loadTestFile(require.resolve('./health_route')); loadTestFile(require.resolve('./task_management')); loadTestFile(require.resolve('./task_management_scheduled_at')); diff --git a/x-pack/test/plugin_api_perf/README.md b/x-pack/test/plugin_api_perf/README.md index f47a2aeb7878a..2ae7c7d201328 100644 --- a/x-pack/test/plugin_api_perf/README.md +++ b/x-pack/test/plugin_api_perf/README.md @@ -71,7 +71,7 @@ Ideally we can clean this up and make it easier and less hacky in the future, bu 1. You can run the FTS in the main clone of your fork by running `node scripts/functional_tests_server.js --config=test/plugin_api_perf/config.js` in the `x-pack` folder. 1. Once you've began running the default FTS, you want your second FTS to run such that it is referencing the Elasticsearch instance started by that first FTS. You achieve this by exporting a `TEST_ES_URL` Environment variable that points at it. By default, you should be able to run this: `export TEST_ES_URL=http://elastic:changeme@localhost:9220`. Do this in a terminal window opened in your **second** clone of Kibana (in my case, the `./elastic/_kibana` folder). 1. One issue I encountered with FTS is that I can't tell it _not to start its own ES instance at all_. To achieve this, in `packages/kbn-test/src/functional_tests/tasks.js` you need to comment out the line that starts up its own ES (`const es = await runElasticsearch({ config, options: opts });` [line 85] and `await es.cleanup();` shortly after) -1. Next you want each instance of Kibana to run with its own UUID as that is used to identify each Kibana's owned tasks. In the file `x-pack/test/functional/config.js` simple change the uuid on the line `--server.uuid=` into any random UUID. +1. Next you want each instance of Kibana to run with its own UUID as that is used to identify each Kibana's owned tasks. In the file `x-pack/test/functional/config.base.js` simple change the uuid on the line `--server.uuid=` into any random UUID. 1. Now that you've made these changes you can kick off your second Kibana FTS by running ths following in the second clone's `x-pack` folder: `TEST_KIBANA_PORT=5621 node scripts/functional_tests_server.js --config=test/plugin_api_perf/config.js`. This runs Kibana on a different port than the first FTS (`5621` instead of `5620`). 1. With two FTS Kibana running and both pointing at the same Elasticsearch. Now, you can run the actual perf test by running `node scripts/functional_test_runner.js --config=test/plugin_api_perf/config.js` in a third terminal diff --git a/x-pack/test/plugin_api_perf/test_suites/task_manager/index.ts b/x-pack/test/plugin_api_perf/test_suites/task_manager/index.ts index 703c97e4f2c63..9055a2d9e023c 100644 --- a/x-pack/test/plugin_api_perf/test_suites/task_manager/index.ts +++ b/x-pack/test/plugin_api_perf/test_suites/task_manager/index.ts @@ -15,7 +15,6 @@ export default function ({ loadTestFile }: { loadTestFile: (file: string) => voi * worth keeping around for future use, rather than being rewritten time and time again. */ describe.skip('task_manager_perf', function taskManagerSuite() { - this.tags('ciGroup12'); loadTestFile(require.resolve('./task_manager_perf_integration')); }); } diff --git a/x-pack/test/plugin_functional/config.ts b/x-pack/test/plugin_functional/config.ts index 8f3c5be04a8bc..a21b8f406e506 100644 --- a/x-pack/test/plugin_functional/config.ts +++ b/x-pack/test/plugin_functional/config.ts @@ -17,7 +17,9 @@ import { pageObjects } from './page_objects'; // that returns an object with the projects config values export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); // Find all folders in ./plugins since we treat all them as plugin folder const allFiles = fs.readdirSync(resolve(__dirname, 'plugins')); diff --git a/x-pack/test/plugin_functional/test_suites/global_search/index.ts b/x-pack/test/plugin_functional/test_suites/global_search/index.ts index a87d9c5e4d503..651bb2b903924 100644 --- a/x-pack/test/plugin_functional/test_suites/global_search/index.ts +++ b/x-pack/test/plugin_functional/test_suites/global_search/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('GlobalSearch API', function () { - this.tags('ciGroup7'); loadTestFile(require.resolve('./global_search_providers')); loadTestFile(require.resolve('./global_search_bar')); }); diff --git a/x-pack/test/plugin_functional/test_suites/resolver/index.ts b/x-pack/test/plugin_functional/test_suites/resolver/index.ts index 688ba536b1232..3c43683b6bf7a 100644 --- a/x-pack/test/plugin_functional/test_suites/resolver/index.ts +++ b/x-pack/test/plugin_functional/test_suites/resolver/index.ts @@ -29,8 +29,6 @@ export default function ({ // FLAKY: https://github.com/elastic/kibana/issues/87425 describe('Resolver test app', function () { - this.tags('ciGroup7'); - // Note: these tests are intended to run on the same page in serial. before(async function () { await pageObjects.common.navigateToApp('resolverTest'); diff --git a/x-pack/test/plugin_functional/test_suites/timelines/index.ts b/x-pack/test/plugin_functional/test_suites/timelines/index.ts index 2ca8d81132ab3..955966eab12c0 100644 --- a/x-pack/test/plugin_functional/test_suites/timelines/index.ts +++ b/x-pack/test/plugin_functional/test_suites/timelines/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getPageObjects, getService }: FtrProviderContext) { describe('Timelines plugin API', function () { - this.tags('ciGroup7'); const pageObjects = getPageObjects(['common']); const testSubjects = getService('testSubjects'); diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/index.ts b/x-pack/test/reporting_api_integration/reporting_and_security/index.ts index 4cff15dc9f444..808c813145b84 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/index.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/index.ts @@ -10,8 +10,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ getService, loadTestFile }: FtrProviderContext) { describe('Reporting APIs', function () { - this.tags('ciGroup2'); - before(async () => { const reportingAPI = getService('reportingAPI'); await reportingAPI.logTaskManagerHealth(); diff --git a/x-pack/test/reporting_api_integration/reporting_without_security/index.ts b/x-pack/test/reporting_api_integration/reporting_without_security/index.ts index 72cfc36947517..19f96aa5d2869 100644 --- a/x-pack/test/reporting_api_integration/reporting_without_security/index.ts +++ b/x-pack/test/reporting_api_integration/reporting_without_security/index.ts @@ -14,7 +14,7 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) { const reportingAPI = getService('reportingAPI'); await reportingAPI.logTaskManagerHealth(); }); - this.tags('ciGroup13'); + loadTestFile(require.resolve('./job_apis_csv')); }); } diff --git a/x-pack/test/reporting_functional/reporting_and_deprecated_security/index.ts b/x-pack/test/reporting_functional/reporting_and_deprecated_security/index.ts index 4725cb1eae82e..722b6545115cd 100644 --- a/x-pack/test/reporting_functional/reporting_and_deprecated_security/index.ts +++ b/x-pack/test/reporting_functional/reporting_and_deprecated_security/index.ts @@ -43,8 +43,6 @@ export default function (context: FtrProviderContext) { }; describe('Reporting Functional Tests with Deprecated Security configuration enabled', function () { - this.tags('ciGroup20'); - before(async () => { const reportingAPI = context.getService('reportingAPI'); await reportingAPI.logTaskManagerHealth(); diff --git a/x-pack/test/reporting_functional/reporting_and_security.config.ts b/x-pack/test/reporting_functional/reporting_and_security.config.ts index 3037aeacde033..7d8c3ed696696 100644 --- a/x-pack/test/reporting_functional/reporting_and_security.config.ts +++ b/x-pack/test/reporting_functional/reporting_and_security.config.ts @@ -11,7 +11,7 @@ import { ReportingAPIProvider } from '../reporting_api_integration/services'; import { ReportingFunctionalProvider } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); // Reporting API tests need a fully working UI + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); // Reporting API tests need a fully working UI const apiConfig = await readConfigFile(require.resolve('../api_integration/config')); return { diff --git a/x-pack/test/reporting_functional/reporting_and_security/index.ts b/x-pack/test/reporting_functional/reporting_and_security/index.ts index 4b06eb426389e..ec7afea96f194 100644 --- a/x-pack/test/reporting_functional/reporting_and_security/index.ts +++ b/x-pack/test/reporting_functional/reporting_and_security/index.ts @@ -10,8 +10,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ getService, loadTestFile }: FtrProviderContext) { describe('Reporting Functional Tests with Security enabled', function () { - this.tags('ciGroup20'); - before(async () => { const reportingFunctional = getService('reportingFunctional'); await reportingFunctional.logTaskManagerHealth(); diff --git a/x-pack/test/reporting_functional/reporting_without_security/index.ts b/x-pack/test/reporting_functional/reporting_without_security/index.ts index fecc0e97daac0..cc07e97a9c3a7 100644 --- a/x-pack/test/reporting_functional/reporting_without_security/index.ts +++ b/x-pack/test/reporting_functional/reporting_without_security/index.ts @@ -10,8 +10,6 @@ import { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile, getService }: FtrProviderContext) { describe('Reporting Functional Tests with Security disabled', function () { - this.tags('ciGroup2'); - before(async () => { const reportingAPI = getService('reportingAPI'); await reportingAPI.logTaskManagerHealth(); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts index ad63d6d1c7ef5..d010cbfce9150 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/index.ts @@ -11,9 +11,6 @@ import { createSpacesAndUsers, deleteSpacesAndUsers } from '../../../common/lib/ // eslint-disable-next-line import/no-default-export export default ({ loadTestFile, getService }: FtrProviderContext): void => { describe('rules security and spaces enabled: basic', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup5'); - before(async () => { await createSpacesAndUsers(getService); }); diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts index 1f5ec04cb8ffb..dfda18b5a0c05 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/basic/search_strategy.ts @@ -19,7 +19,7 @@ import { waitForSignalsToBePresent, waitForRuleSuccessOrStatus, } from '../../../../detection_engine_api_integration/utils'; -import { ID } from '../../../../detection_engine_api_integration/security_and_spaces/tests/generating_signals'; +import { ID } from '../../../../detection_engine_api_integration/security_and_spaces/group1/generating_signals'; import { obsOnlySpacesAllEsRead, obsOnlySpacesAll, diff --git a/x-pack/test/rule_registry/security_and_spaces/tests/trial/index.ts b/x-pack/test/rule_registry/security_and_spaces/tests/trial/index.ts index 3e13d64b936a4..53a788f6c7829 100644 --- a/x-pack/test/rule_registry/security_and_spaces/tests/trial/index.ts +++ b/x-pack/test/rule_registry/security_and_spaces/tests/trial/index.ts @@ -39,9 +39,6 @@ import { export default ({ loadTestFile, getService }: FtrProviderContext): void => { // FAILING: https://github.com/elastic/kibana/issues/110153 describe.skip('rules security and spaces enabled: trial', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup5'); - before(async () => { await createSpaces(getService); await createUsersAndRoles( diff --git a/x-pack/test/rule_registry/spaces_only/tests/basic/index.ts b/x-pack/test/rule_registry/spaces_only/tests/basic/index.ts index aeb2b085ad379..f47b4b6254ff2 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/basic/index.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/basic/index.ts @@ -11,9 +11,6 @@ import { createSpaces, deleteSpaces } from '../../../common/lib/authentication'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile, getService }: FtrProviderContext): void => { describe('rule registry spaces only: trial', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup5'); - before(async () => { await createSpaces(getService); }); diff --git a/x-pack/test/rule_registry/spaces_only/tests/trial/index.ts b/x-pack/test/rule_registry/spaces_only/tests/trial/index.ts index 19e35019eb50a..d519dd16dab45 100644 --- a/x-pack/test/rule_registry/spaces_only/tests/trial/index.ts +++ b/x-pack/test/rule_registry/spaces_only/tests/trial/index.ts @@ -11,9 +11,6 @@ import { createSpaces, deleteSpaces } from '../../../common/lib/authentication'; // eslint-disable-next-line import/no-default-export export default ({ loadTestFile, getService }: FtrProviderContext): void => { describe('rule registry spaces only: trial', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup5'); - before(async () => { await createSpaces(getService); }); diff --git a/x-pack/test/saved_object_api_integration/common/config.ts b/x-pack/test/saved_object_api_integration/common/config.ts index 8ca74c7fcea49..32d2d73d5cebc 100644 --- a/x-pack/test/saved_object_api_integration/common/config.ts +++ b/x-pack/test/saved_object_api_integration/common/config.ts @@ -24,7 +24,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) const config = { kibana: { api: await readConfigFile(path.resolve(REPO_ROOT, 'test/api_integration/config.js')), - functional: await readConfigFile(require.resolve('../../../../test/functional/config.js')), + functional: await readConfigFile( + require.resolve('../../../../test/functional/config.base.js') + ), }, xpack: { api: await readConfigFile(require.resolve('../../api_integration/config.ts')), diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts index 740b9d91927bf..4eb0b90480314 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/index.ts @@ -13,8 +13,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { const supertest = getService('supertest'); describe('saved objects security and spaces enabled', function () { - this.tags('ciGroup20'); - before(async () => { await createUsersAndRoles(es, supertest); }); diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts index c6bdbde07fc02..1be7ed754a971 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('saved objects spaces only enabled', function () { - this.tags('ciGroup5'); - loadTestFile(require.resolve('./bulk_create')); loadTestFile(require.resolve('./bulk_get')); loadTestFile(require.resolve('./bulk_resolve')); diff --git a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/index.ts b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/index.ts index 54740e73aba65..f28b3cd615887 100644 --- a/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/saved_object_tagging/api_integration/security_and_spaces/apis/index.ts @@ -11,8 +11,6 @@ import { createUsersAndRoles } from '../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function ({ getService, loadTestFile }: FtrProviderContext) { describe('saved objects tagging API - security and spaces integration', function () { - this.tags('ciGroup10'); - before(async () => { await createUsersAndRoles(getService); }); diff --git a/x-pack/test/saved_object_tagging/api_integration/tagging_api/apis/index.ts b/x-pack/test/saved_object_tagging/api_integration/tagging_api/apis/index.ts index 3d5b0b9c3b989..f291d2537ed02 100644 --- a/x-pack/test/saved_object_tagging/api_integration/tagging_api/apis/index.ts +++ b/x-pack/test/saved_object_tagging/api_integration/tagging_api/apis/index.ts @@ -10,8 +10,6 @@ import { FtrProviderContext } from '../services'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile }: FtrProviderContext) { describe('saved objects tagging API', function () { - this.tags('ciGroup12'); - loadTestFile(require.resolve('./delete')); loadTestFile(require.resolve('./create')); loadTestFile(require.resolve('./update')); diff --git a/x-pack/test/saved_object_tagging/functional/config.ts b/x-pack/test/saved_object_tagging/functional/config.ts index 6ad1f05e2be5b..1c40864f2fa02 100644 --- a/x-pack/test/saved_object_tagging/functional/config.ts +++ b/x-pack/test/saved_object_tagging/functional/config.ts @@ -11,7 +11,7 @@ import { services, pageObjects } from './ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default async function ({ readConfigFile }: FtrConfigProviderContext) { const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../functional/config.js') + require.resolve('../../functional/config.base.js') ); return { diff --git a/x-pack/test/saved_object_tagging/functional/tests/index.ts b/x-pack/test/saved_object_tagging/functional/tests/index.ts index fbf0954382dd1..2d79d0a7a45ec 100644 --- a/x-pack/test/saved_object_tagging/functional/tests/index.ts +++ b/x-pack/test/saved_object_tagging/functional/tests/index.ts @@ -11,8 +11,6 @@ import { createUsersAndRoles } from '../../common/lib'; // eslint-disable-next-line import/no-default-export export default function ({ loadTestFile, getService }: FtrProviderContext) { describe('saved objects tagging - functional tests', function () { - this.tags('ciGroup14'); - before(async () => { await createUsersAndRoles(getService); }); diff --git a/x-pack/test/saved_objects_field_count/config.ts b/x-pack/test/saved_objects_field_count/config.ts index 7967b6c4f3b9c..ab5154adb8d59 100644 --- a/x-pack/test/saved_objects_field_count/config.ts +++ b/x-pack/test/saved_objects_field_count/config.ts @@ -6,7 +6,6 @@ */ import { FtrConfigProviderContext } from '@kbn/test'; -import { testRunner } from './runner'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const kibanaCommonTestsConfig = await readConfigFile( @@ -16,7 +15,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { return { ...kibanaCommonTestsConfig.getAll(), - testRunner, + testFiles: [require.resolve('./test')], esTestCluster: { license: 'trial', @@ -28,5 +27,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...kibanaCommonTestsConfig.get('kbnTestServer'), serverArgs: [...kibanaCommonTestsConfig.get('kbnTestServer.serverArgs')], }, + + junit: { + reportName: 'Saved Object Field Count', + }, }; } diff --git a/x-pack/test/saved_objects_field_count/runner.ts b/x-pack/test/saved_objects_field_count/runner.ts deleted file mode 100644 index b88f2129ba64d..0000000000000 --- a/x-pack/test/saved_objects_field_count/runner.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CiStatsReporter } from '@kbn/ci-stats-reporter'; -import { FtrProviderContext } from '../functional/ftr_provider_context'; - -const IGNORED_FIELDS = [ - // The following fields are returned by the _field_caps API but aren't counted - // towards the index field limit. - '_seq_no', - '_id', - '_version', - '_field_names', - '_ignored', - '_feature', - '_index', - '_routing', - '_source', - '_type', - '_nested_path', - '_timestamp', - // migrationVersion is dynamic so will be anywhere between 1..type count - // depending on which objects are present in the index when querying the - // field caps API. See https://github.com/elastic/kibana/issues/70815 - 'migrationVersion', -]; - -export async function testRunner({ getService }: FtrProviderContext) { - const log = getService('log'); - const es = getService('es'); - - const reporter = CiStatsReporter.fromEnv(log); - - log.debug('Saved Objects field count metrics starting'); - - const { fields } = await es.fieldCaps({ - index: '.kibana', - fields: '*', - }); - - const fieldCountPerTypeMap: Map = Object.keys(fields) - .map((f) => f.split('.')[0]) - .filter((f) => !IGNORED_FIELDS.includes(f)) - .reduce((accumulator, f) => { - accumulator.set(f, accumulator.get(f) + 1 || 1); - return accumulator; - }, new Map()); - - const metrics = Array.from(fieldCountPerTypeMap.entries()) - .sort((a, b) => a[0].localeCompare(b[0])) - .map(([fieldType, count]) => ({ - group: 'Saved Objects .kibana field count', - id: fieldType, - value: count, - })); - - log.debug( - 'Saved Objects field count metrics:\n', - metrics.map(({ id, value }) => `${id}:${value}`).join('\n') - ); - await reporter.metrics(metrics); - log.debug('Saved Objects field count metrics done'); -} diff --git a/x-pack/test/saved_objects_field_count/test.ts b/x-pack/test/saved_objects_field_count/test.ts new file mode 100644 index 0000000000000..e931b1aa5ef26 --- /dev/null +++ b/x-pack/test/saved_objects_field_count/test.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CiStatsReporter } from '@kbn/ci-stats-reporter'; +import { FtrProviderContext } from '../functional/ftr_provider_context'; + +const IGNORED_FIELDS = [ + // The following fields are returned by the _field_caps API but aren't counted + // towards the index field limit. + '_seq_no', + '_id', + '_version', + '_field_names', + '_ignored', + '_feature', + '_index', + '_routing', + '_source', + '_type', + '_nested_path', + '_timestamp', + // migrationVersion is dynamic so will be anywhere between 1..type count + // depending on which objects are present in the index when querying the + // field caps API. See https://github.com/elastic/kibana/issues/70815 + 'migrationVersion', +]; + +// eslint-disable-next-line import/no-default-export +export default function ({ getService }: FtrProviderContext) { + const log = getService('log'); + const es = getService('es'); + + describe('Saved Objects Field Count', () => { + it('capture', async () => { + const reporter = CiStatsReporter.fromEnv(log); + + log.debug('Saved Objects field count metrics starting'); + + const { fields } = await es.fieldCaps({ + index: '.kibana', + fields: '*', + }); + + const fieldCountPerTypeMap: Map = Object.keys(fields) + .map((f) => f.split('.')[0]) + .filter((f) => !IGNORED_FIELDS.includes(f)) + .reduce((accumulator, f) => { + accumulator.set(f, accumulator.get(f) + 1 || 1); + return accumulator; + }, new Map()); + + const metrics = Array.from(fieldCountPerTypeMap.entries()) + .sort((a, b) => a[0].localeCompare(b[0])) + .map(([fieldType, count]) => ({ + group: 'Saved Objects .kibana field count', + id: fieldType, + value: count, + })); + + log.debug( + 'Saved Objects field count metrics:\n', + metrics.map(({ id, value }) => `${id}:${value}`).join('\n') + ); + + await reporter.metrics(metrics); + log.debug('Saved Objects field count metrics done'); + }); + }); +} diff --git a/x-pack/test/screenshot_creation/config.ts b/x-pack/test/screenshot_creation/config.ts index 659034e9fbe8b..18dda361ac2cd 100644 --- a/x-pack/test/screenshot_creation/config.ts +++ b/x-pack/test/screenshot_creation/config.ts @@ -9,7 +9,9 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { services } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); return { // default to the xpack functional config diff --git a/x-pack/test/search_sessions_integration/config.ts b/x-pack/test/search_sessions_integration/config.ts index 9dc542038a48a..2d570a607c746 100644 --- a/x-pack/test/search_sessions_integration/config.ts +++ b/x-pack/test/search_sessions_integration/config.ts @@ -10,7 +10,9 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { services } from '../functional/services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); return { // default to the xpack functional config diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/index.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/index.ts index b87f43f73ed2e..9465de1de5922 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/index.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/index.ts @@ -14,8 +14,6 @@ export default function ({ loadTestFile, getService, getPageObjects }: FtrProvid const searchSessions = getService('searchSessions'); describe('Dashboard', function () { - this.tags('ciGroup5'); - before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await esArchiver.load('x-pack/test/functional/es_archives/dashboard/async_search'); diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/session_sharing/index.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/session_sharing/index.ts index 6a13dc268b705..1ff11eb988456 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/session_sharing/index.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/session_sharing/index.ts @@ -13,8 +13,6 @@ export default function ({ loadTestFile, getService, getPageObjects }: FtrProvid const PageObjects = getPageObjects(['common']); describe('Search session sharing', function () { - this.tags('ciGroup5'); - before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); diff --git a/x-pack/test/search_sessions_integration/tests/apps/discover/index.ts b/x-pack/test/search_sessions_integration/tests/apps/discover/index.ts index 1f8d219674428..2af94730ff918 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/discover/index.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/discover/index.ts @@ -14,8 +14,6 @@ export default function ({ loadTestFile, getService, getPageObjects }: FtrProvid const searchSessions = getService('searchSessions'); describe('Discover', function () { - this.tags('ciGroup5'); - before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); diff --git a/x-pack/test/search_sessions_integration/tests/apps/lens/index.ts b/x-pack/test/search_sessions_integration/tests/apps/lens/index.ts index 5e45db7bd7233..978c5bdec0df5 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/lens/index.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/lens/index.ts @@ -12,8 +12,6 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); describe('lens search sessions', function () { - this.tags('ciGroup5'); - before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await kibanaServer.uiSettings.replace({ defaultIndex: 'logstash-*' }); diff --git a/x-pack/test/search_sessions_integration/tests/apps/management/search_sessions/index.ts b/x-pack/test/search_sessions_integration/tests/apps/management/search_sessions/index.ts index b72d8db06a1d8..60e4ea1b3bfbb 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/management/search_sessions/index.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/management/search_sessions/index.ts @@ -12,8 +12,6 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); describe('search sessions management', function () { - this.tags('ciGroup5'); - before(async () => { await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/logstash_functional'); await esArchiver.load('x-pack/test/functional/es_archives/dashboard/async_search'); diff --git a/x-pack/test/security_api_integration/tests/anonymous/index.ts b/x-pack/test/security_api_integration/tests/anonymous/index.ts index 08f075950a57f..0f976589483a8 100644 --- a/x-pack/test/security_api_integration/tests/anonymous/index.ts +++ b/x-pack/test/security_api_integration/tests/anonymous/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Anonymous access', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./login')); loadTestFile(require.resolve('./capabilities')); }); diff --git a/x-pack/test/security_api_integration/tests/audit/index.ts b/x-pack/test/security_api_integration/tests/audit/index.ts index 14628bbc51e89..96b2ceb5ae3a7 100644 --- a/x-pack/test/security_api_integration/tests/audit/index.ts +++ b/x-pack/test/security_api_integration/tests/audit/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Audit Log', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./audit_log')); }); } diff --git a/x-pack/test/security_api_integration/tests/http_bearer/index.ts b/x-pack/test/security_api_integration/tests/http_bearer/index.ts index 4dbad2660ebaa..c796c0be9befb 100644 --- a/x-pack/test/security_api_integration/tests/http_bearer/index.ts +++ b/x-pack/test/security_api_integration/tests/http_bearer/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - HTTP Bearer', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./header')); }); } diff --git a/x-pack/test/security_api_integration/tests/http_no_auth_providers/index.ts b/x-pack/test/security_api_integration/tests/http_no_auth_providers/index.ts index 652bcc419e243..23096b2449c9f 100644 --- a/x-pack/test/security_api_integration/tests/http_no_auth_providers/index.ts +++ b/x-pack/test/security_api_integration/tests/http_no_auth_providers/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - HTTP no authentication providers are enabled', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./authentication')); }); } diff --git a/x-pack/test/security_api_integration/tests/kerberos/index.ts b/x-pack/test/security_api_integration/tests/kerberos/index.ts index cec92939a5194..828ce7220458f 100644 --- a/x-pack/test/security_api_integration/tests/kerberos/index.ts +++ b/x-pack/test/security_api_integration/tests/kerberos/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Kerberos', function () { - this.tags('ciGroup31'); - loadTestFile(require.resolve('./kerberos_login')); }); } diff --git a/x-pack/test/security_api_integration/tests/login_selector/index.ts b/x-pack/test/security_api_integration/tests/login_selector/index.ts index a38a0acc68cca..e3698340d3967 100644 --- a/x-pack/test/security_api_integration/tests/login_selector/index.ts +++ b/x-pack/test/security_api_integration/tests/login_selector/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Login Selector', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./basic_functionality')); }); } diff --git a/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/index.ts b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/index.ts index 858b8e2fbb750..2c8edc1569bd2 100644 --- a/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/index.ts +++ b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - OIDC (Authorization Code Flow)', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./oidc_auth')); }); } diff --git a/x-pack/test/security_api_integration/tests/oidc/implicit_flow/index.ts b/x-pack/test/security_api_integration/tests/oidc/implicit_flow/index.ts index c42014661b915..7479ba8e7bd81 100644 --- a/x-pack/test/security_api_integration/tests/oidc/implicit_flow/index.ts +++ b/x-pack/test/security_api_integration/tests/oidc/implicit_flow/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - OIDC (Implicit Flow)', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./oidc_auth')); }); } diff --git a/x-pack/test/security_api_integration/tests/pki/index.ts b/x-pack/test/security_api_integration/tests/pki/index.ts index c3b733d0b31f8..9926f16619898 100644 --- a/x-pack/test/security_api_integration/tests/pki/index.ts +++ b/x-pack/test/security_api_integration/tests/pki/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - PKI', function () { - this.tags('ciGroup22'); - loadTestFile(require.resolve('./pki_auth')); }); } diff --git a/x-pack/test/security_api_integration/tests/saml/index.ts b/x-pack/test/security_api_integration/tests/saml/index.ts index e7ffdbd410de3..3597f1a6104ec 100644 --- a/x-pack/test/security_api_integration/tests/saml/index.ts +++ b/x-pack/test/security_api_integration/tests/saml/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - SAML', function () { - this.tags('ciGroup27'); - loadTestFile(require.resolve('./saml_login')); }); } diff --git a/x-pack/test/security_api_integration/tests/session_idle/index.ts b/x-pack/test/security_api_integration/tests/session_idle/index.ts index 76457ee7ad0c7..6966b9f2ed2c7 100644 --- a/x-pack/test/security_api_integration/tests/session_idle/index.ts +++ b/x-pack/test/security_api_integration/tests/session_idle/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Session Idle', function () { - this.tags('ciGroup18'); - loadTestFile(require.resolve('./cleanup')); loadTestFile(require.resolve('./extension')); }); diff --git a/x-pack/test/security_api_integration/tests/session_invalidate/index.ts b/x-pack/test/security_api_integration/tests/session_invalidate/index.ts index 6408e4cfbd43d..dcfb3d7fc5259 100644 --- a/x-pack/test/security_api_integration/tests/session_invalidate/index.ts +++ b/x-pack/test/security_api_integration/tests/session_invalidate/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Session Invalidate', function () { - this.tags('ciGroup6'); - loadTestFile(require.resolve('./invalidate')); }); } diff --git a/x-pack/test/security_api_integration/tests/session_lifespan/index.ts b/x-pack/test/security_api_integration/tests/session_lifespan/index.ts index 15522da907958..e297805b4ab3c 100644 --- a/x-pack/test/security_api_integration/tests/session_lifespan/index.ts +++ b/x-pack/test/security_api_integration/tests/session_lifespan/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Session Lifespan', function () { - this.tags('ciGroup6'); - loadTestFile(require.resolve('./cleanup')); }); } diff --git a/x-pack/test/security_api_integration/tests/token/index.ts b/x-pack/test/security_api_integration/tests/token/index.ts index 88c82125ee1d9..54717dc1c8617 100644 --- a/x-pack/test/security_api_integration/tests/token/index.ts +++ b/x-pack/test/security_api_integration/tests/token/index.ts @@ -9,7 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security APIs - Token', function () { - this.tags('ciGroup6'); loadTestFile(require.resolve('./login')); loadTestFile(require.resolve('./logout')); loadTestFile(require.resolve('./header')); diff --git a/x-pack/test/security_functional/login_selector.config.ts b/x-pack/test/security_functional/login_selector.config.ts index aa145e2ec6216..d2035a9b228e8 100644 --- a/x-pack/test/security_functional/login_selector.config.ts +++ b/x-pack/test/security_functional/login_selector.config.ts @@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); const kibanaPort = kibanaFunctionalConfig.get('servers.kibana.port'); diff --git a/x-pack/test/security_functional/oidc.config.ts b/x-pack/test/security_functional/oidc.config.ts index 9c00960671e03..6476bbb501b77 100644 --- a/x-pack/test/security_functional/oidc.config.ts +++ b/x-pack/test/security_functional/oidc.config.ts @@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); const kibanaPort = kibanaFunctionalConfig.get('servers.kibana.port'); diff --git a/x-pack/test/security_functional/saml.config.ts b/x-pack/test/security_functional/saml.config.ts index 264197c961123..60a934a712bbf 100644 --- a/x-pack/test/security_functional/saml.config.ts +++ b/x-pack/test/security_functional/saml.config.ts @@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const kibanaFunctionalConfig = await readConfigFile( - require.resolve('../../../test/functional/config.js') + require.resolve('../../../test/functional/config.base.js') ); const kibanaPort = kibanaFunctionalConfig.get('servers.kibana.port'); diff --git a/x-pack/test/security_functional/tests/login_selector/index.ts b/x-pack/test/security_functional/tests/login_selector/index.ts index 1a34fc5eac6d9..bf3cc557f0bd7 100644 --- a/x-pack/test/security_functional/tests/login_selector/index.ts +++ b/x-pack/test/security_functional/tests/login_selector/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security app - login selector', function () { - this.tags('ciGroup13'); - loadTestFile(require.resolve('./basic_functionality')); loadTestFile(require.resolve('./auth_provider_hint')); }); diff --git a/x-pack/test/security_functional/tests/oidc/index.ts b/x-pack/test/security_functional/tests/oidc/index.ts index cd328384febd3..37490a0193089 100644 --- a/x-pack/test/security_functional/tests/oidc/index.ts +++ b/x-pack/test/security_functional/tests/oidc/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security app - OIDC interactions', function () { - this.tags('ciGroup13'); - loadTestFile(require.resolve('./url_capture')); }); } diff --git a/x-pack/test/security_functional/tests/saml/index.ts b/x-pack/test/security_functional/tests/saml/index.ts index 66a497db8af40..ebf97ebf8edfb 100644 --- a/x-pack/test/security_functional/tests/saml/index.ts +++ b/x-pack/test/security_functional/tests/saml/index.ts @@ -9,8 +9,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('security app - SAML interactions', function () { - this.tags('ciGroup13'); - loadTestFile(require.resolve('./url_capture')); }); } diff --git a/x-pack/test/security_solution_cypress/config.firefox.ts b/x-pack/test/security_solution_cypress/config.firefox.ts index 2a2ce410850ff..c29f47708a170 100644 --- a/x-pack/test/security_solution_cypress/config.firefox.ts +++ b/x-pack/test/security_solution_cypress/config.firefox.ts @@ -16,7 +16,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('../functional/config.js') + require.resolve('../functional/config.base.js') ); return { diff --git a/x-pack/test/security_solution_cypress/config.ts b/x-pack/test/security_solution_cypress/config.ts index 7f196880e8fca..4b5b2c361c1b9 100644 --- a/x-pack/test/security_solution_cypress/config.ts +++ b/x-pack/test/security_solution_cypress/config.ts @@ -14,7 +14,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { require.resolve('../../../test/common/config.js') ); const xpackFunctionalTestsConfig = await readConfigFile( - require.resolve('../functional/config.js') + require.resolve('../functional/config.base.js') ); return { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts index e57895f4f32b7..c776dcf91602f 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts @@ -16,7 +16,6 @@ export default function (providerContext: FtrProviderContext) { const { loadTestFile, getService } = providerContext; describe('endpoint', function () { - this.tags('ciGroup7'); const ingestManager = getService('ingestManager'); const log = getService('log'); const endpointTestResources = getService('endpointTestResources'); diff --git a/x-pack/test/security_solution_endpoint/config.ts b/x-pack/test/security_solution_endpoint/config.ts index b00df7732ea4f..b5b52b7bc5cd5 100644 --- a/x-pack/test/security_solution_endpoint/config.ts +++ b/x-pack/test/security_solution_endpoint/config.ts @@ -15,7 +15,9 @@ import { } from '../security_solution_endpoint_api_int/registry'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); return { ...xpackFunctionalConfig.getAll(), diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/index.ts b/x-pack/test/security_solution_endpoint_api_int/apis/index.ts index 3c98b703aed55..7be4ce2243303 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/index.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/index.ts @@ -13,8 +13,6 @@ export default function endpointAPIIntegrationTests(providerContext: FtrProvider const { loadTestFile, getService } = providerContext; describe('Endpoint plugin', function () { - this.tags('ciGroup9'); - const ingestManager = getService('ingestManager'); const log = getService('log'); diff --git a/x-pack/test/spaces_api_integration/common/config.ts b/x-pack/test/spaces_api_integration/common/config.ts index 5d135cd05605c..15a63fec6d309 100644 --- a/x-pack/test/spaces_api_integration/common/config.ts +++ b/x-pack/test/spaces_api_integration/common/config.ts @@ -21,7 +21,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) const config = { kibana: { api: await readConfigFile(path.resolve(REPO_ROOT, 'test/api_integration/config.js')), - functional: await readConfigFile(require.resolve('../../../../test/functional/config.js')), + functional: await readConfigFile( + require.resolve('../../../../test/functional/config.base.js') + ), }, xpack: { api: await readConfigFile(require.resolve('../../api_integration/config.ts')), diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts index a86fef0d758fc..75381f35dacd3 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/index.ts @@ -14,8 +14,6 @@ export default function ({ loadTestFile, getService }: FtrProviderContext) { const supertest = getService('supertest'); describe('spaces api with security', function () { - this.tags('ciGroup8'); - before(async () => { await createUsersAndRoles(es, supertest); }); diff --git a/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts b/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts index f64336b2b4908..6a8148efaa1d6 100644 --- a/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts +++ b/x-pack/test/spaces_api_integration/spaces_only/apis/index.ts @@ -10,8 +10,6 @@ import { FtrProviderContext } from '../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function spacesOnlyTestSuite({ loadTestFile }: FtrProviderContext) { describe('spaces api without security', function () { - this.tags('ciGroup5'); - loadTestFile(require.resolve('./copy_to_space')); loadTestFile(require.resolve('./resolve_copy_to_space_conflicts')); loadTestFile(require.resolve('./create')); diff --git a/x-pack/test/stack_functional_integration/apps/telemetry/index.js b/x-pack/test/stack_functional_integration/apps/telemetry/index.js index 80cffcfaf70a7..3d1dffb3a442f 100644 --- a/x-pack/test/stack_functional_integration/apps/telemetry/index.js +++ b/x-pack/test/stack_functional_integration/apps/telemetry/index.js @@ -7,7 +7,6 @@ export default function ({ loadTestFile }) { describe('telemetry feature', function () { - this.tags('ciGroup1'); loadTestFile(require.resolve('./_telemetry')); }); } diff --git a/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js b/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js index 9b768ab61baec..1658bcbf6cd35 100644 --- a/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js +++ b/x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js @@ -25,7 +25,9 @@ const testsFolder = '../apps'; const prepend = (testFile) => require.resolve(`${testsFolder}/${testFile}`); export default async ({ readConfigFile }) => { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../../functional/config')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../../functional/config.base.js') + ); const externalConf = consumeState(resolve(__dirname, stateFilePath)); process.env.stack_functional_integration = true; logAll(log); diff --git a/x-pack/test/timeline/security_and_spaces/tests/basic/index.ts b/x-pack/test/timeline/security_and_spaces/tests/basic/index.ts index 4672a8e2e7f65..248c5ece3641d 100644 --- a/x-pack/test/timeline/security_and_spaces/tests/basic/index.ts +++ b/x-pack/test/timeline/security_and_spaces/tests/basic/index.ts @@ -14,9 +14,6 @@ import { // eslint-disable-next-line import/no-default-export export default ({ loadTestFile, getService }: FtrProviderContext): void => { describe('timeline security and spaces enabled: basic', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup5'); - before(async () => { await createSpacesAndUsers(getService); }); diff --git a/x-pack/test/timeline/security_and_spaces/tests/trial/index.ts b/x-pack/test/timeline/security_and_spaces/tests/trial/index.ts index 736fb6619c82d..2103097891a31 100644 --- a/x-pack/test/timeline/security_and_spaces/tests/trial/index.ts +++ b/x-pack/test/timeline/security_and_spaces/tests/trial/index.ts @@ -38,9 +38,6 @@ import { // eslint-disable-next-line import/no-default-export export default ({ loadTestFile, getService }: FtrProviderContext): void => { describe('timeline security and spaces enabled: trial', function () { - // Fastest ciGroup for the moment. - this.tags('ciGroup5'); - before(async () => { await createSpaces(getService); await createUsersAndRoles( diff --git a/x-pack/test/ui_capabilities/common/config.ts b/x-pack/test/ui_capabilities/common/config.ts index f676a5eeccee1..32e7538ecbbe7 100644 --- a/x-pack/test/ui_capabilities/common/config.ts +++ b/x-pack/test/ui_capabilities/common/config.ts @@ -20,7 +20,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) return async ({ readConfigFile }: FtrConfigProviderContext) => { const xPackFunctionalTestsConfig = await readConfigFile( - require.resolve('../../functional/config.js') + require.resolve('../../functional/config.base.js') ); return { diff --git a/x-pack/test/ui_capabilities/security_and_spaces/tests/index.ts b/x-pack/test/ui_capabilities/security_and_spaces/tests/index.ts index a257f8fcabb8e..77619157c615f 100644 --- a/x-pack/test/ui_capabilities/security_and_spaces/tests/index.ts +++ b/x-pack/test/ui_capabilities/security_and_spaces/tests/index.ts @@ -16,8 +16,6 @@ export default function uiCapabilitiesTests({ loadTestFile, getService }: FtrPro const featuresService: FeaturesService = getService('features'); describe('ui capabilities', function () { - this.tags('ciGroup9'); - before(async () => { const features = await featuresService.get(); for (const space of Spaces) { diff --git a/x-pack/test/ui_capabilities/spaces_only/tests/index.ts b/x-pack/test/ui_capabilities/spaces_only/tests/index.ts index 73a068cf9ec6b..02ed1533b56ad 100644 --- a/x-pack/test/ui_capabilities/spaces_only/tests/index.ts +++ b/x-pack/test/ui_capabilities/spaces_only/tests/index.ts @@ -14,8 +14,6 @@ export default function uiCapabilitesTests({ loadTestFile, getService }: FtrProv const featuresService: FeaturesService = getService('features'); describe('ui capabilities', function () { - this.tags('ciGroup9'); - before(async () => { // we're using a basic license, so if we want to disable all features, we have to ignore the valid licenses const features = await featuresService.get({ ignoreValidLicenses: true }); diff --git a/x-pack/test/upgrade/config.ts b/x-pack/test/upgrade/config.ts index 78d61d5239556..181abe8ca408f 100644 --- a/x-pack/test/upgrade/config.ts +++ b/x-pack/test/upgrade/config.ts @@ -12,7 +12,7 @@ import { MapsHelper } from './services/maps_upgrade_services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const apiConfig = await readConfigFile(require.resolve('../api_integration/config')); - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { ...functionalConfig.getAll(), diff --git a/x-pack/test/upgrade_assistant_integration/config.js b/x-pack/test/upgrade_assistant_integration/config.js index 8152b5790fc40..e1248c717b216 100644 --- a/x-pack/test/upgrade_assistant_integration/config.js +++ b/x-pack/test/upgrade_assistant_integration/config.js @@ -11,7 +11,7 @@ export default async function ({ readConfigFile }) { require.resolve('../../../test/api_integration/config.js') ); const xPackFunctionalTestsConfig = await readConfigFile( - require.resolve('../functional/config.js') + require.resolve('../functional/config.base.js') ); const kibanaCommonConfig = await readConfigFile( require.resolve('../../../test/common/config.js') diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/index.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/index.js index 1a7090a3cbdfb..eb09d24b79b6a 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/index.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/index.js @@ -7,8 +7,6 @@ export default function ({ loadTestFile }) { describe('upgrade assistant', function () { - this.tags('ciGroup7'); - loadTestFile(require.resolve('./reindexing')); }); } diff --git a/x-pack/test/usage_collection/config.ts b/x-pack/test/usage_collection/config.ts index beb934219422a..248f00ff81233 100644 --- a/x-pack/test/usage_collection/config.ts +++ b/x-pack/test/usage_collection/config.ts @@ -15,7 +15,9 @@ import { pageObjects } from './page_objects'; // that returns an object with the projects config values export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js')); + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); // Find all folders in ./plugins since we treat all them as plugin folder const allFiles = fs.readdirSync(resolve(__dirname, 'plugins')); diff --git a/x-pack/test/usage_collection/test_suites/application_usage/index.ts b/x-pack/test/usage_collection/test_suites/application_usage/index.ts index 4b41aada9ad29..754ae98997c16 100644 --- a/x-pack/test/usage_collection/test_suites/application_usage/index.ts +++ b/x-pack/test/usage_collection/test_suites/application_usage/index.ts @@ -11,7 +11,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('Application Usage', function () { - this.tags('ciGroup1'); const { common } = getPageObjects(['common']); const browser = getService('browser'); diff --git a/x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts b/x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts index dac552220f7c1..a595c2662d451 100644 --- a/x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts +++ b/x-pack/test/usage_collection/test_suites/stack_management_usage/index.ts @@ -12,7 +12,6 @@ import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { // FLAKY: https://github.com/elastic/kibana/issues/119038 describe.skip('Stack Management', function () { - this.tags('ciGroup1'); const { common } = getPageObjects(['common']); const browser = getService('browser'); diff --git a/x-pack/test/visual_regression/config.ts b/x-pack/test/visual_regression/config.ts index c211918ef8e52..c7f0d8203833e 100644 --- a/x-pack/test/visual_regression/config.ts +++ b/x-pack/test/visual_regression/config.ts @@ -10,7 +10,7 @@ import { FtrConfigProviderContext } from '@kbn/test'; import { services } from './services'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { - const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + const functionalConfig = await readConfigFile(require.resolve('../functional/config.base.js')); return { ...functionalConfig.getAll(), diff --git a/x-pack/test/visual_regression/tests/canvas/index.js b/x-pack/test/visual_regression/tests/canvas/index.js index 099c96e6eaf01..20a262fef10fe 100644 --- a/x-pack/test/visual_regression/tests/canvas/index.js +++ b/x-pack/test/visual_regression/tests/canvas/index.js @@ -25,7 +25,6 @@ export default function ({ loadTestFile, getService }) { await esArchiver.unload('x-pack/test/functional/es_archives/canvas/default'); }); - this.tags('ciGroup10'); loadTestFile(require.resolve('./fullscreen')); }); } diff --git a/x-pack/test/visual_regression/tests/infra/index.js b/x-pack/test/visual_regression/tests/infra/index.js index b624c6ec848f2..13669c50953f9 100644 --- a/x-pack/test/visual_regression/tests/infra/index.js +++ b/x-pack/test/visual_regression/tests/infra/index.js @@ -13,7 +13,6 @@ export default function ({ loadTestFile, getService }) { await browser.setWindowSize(1600, 1000); }); - this.tags('ciGroup10'); loadTestFile(require.resolve('./waffle_map')); loadTestFile(require.resolve('./saved_views')); }); diff --git a/x-pack/test/visual_regression/tests/maps/index.js b/x-pack/test/visual_regression/tests/maps/index.js index 3459896baacd6..9d53d70ad2abc 100644 --- a/x-pack/test/visual_regression/tests/maps/index.js +++ b/x-pack/test/visual_regression/tests/maps/index.js @@ -56,7 +56,6 @@ export default function ({ loadTestFile, getService }) { ); }); - this.tags('ciGroup10'); loadTestFile(require.resolve('./vector_styling')); }); } From 1591bfba2404f1b645002bb642842f7297a0c010 Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Wed, 4 May 2022 15:11:53 -0700 Subject: [PATCH 56/68] [DOCS] Replace execution terminology in Alerting (#131357) --- docs/settings/alert-action-settings.asciidoc | 10 +++-- .../alerting-getting-started.asciidoc | 4 +- docs/user/alerting/alerting-setup.asciidoc | 2 +- .../alerting-troubleshooting.asciidoc | 8 ++-- .../alerting/create-and-manage-rules.asciidoc | 6 +-- .../alerting/rule-types/es-query.asciidoc | 24 ++++++------ .../rule-types/index-threshold.asciidoc | 2 +- .../alerting-common-issues.asciidoc | 39 +++++++++---------- .../troubleshooting/event-log-index.asciidoc | 25 +++++++----- .../testing-connectors.asciidoc | 8 ++-- 10 files changed, 69 insertions(+), 59 deletions(-) diff --git a/docs/settings/alert-action-settings.asciidoc b/docs/settings/alert-action-settings.asciidoc index f3fa027cb186e..aa5d9f53359b7 100644 --- a/docs/settings/alert-action-settings.asciidoc +++ b/docs/settings/alert-action-settings.asciidoc @@ -92,7 +92,7 @@ URLs can use both the `ssl` and `smtp` options. + No other URL values should be part of this URL, including paths, query strings, and authentication information. When an http or smtp request -is made as part of executing an action, only the protocol, hostname, and +is made as part of running an action, only the protocol, hostname, and port of the URL for that request are used to look up these configuration values. @@ -188,10 +188,14 @@ For example, `20m`, `24h`, `7d`, `1w`. Default: `60s`. ==== Alerting settings `xpack.alerting.maxEphemeralActionsPerAlert`:: -Sets the number of actions that will be executed ephemerally. To use this, enable ephemeral tasks in task manager first with <> +Sets the number of actions that will run ephemerally. To use this, enable +ephemeral tasks in task manager first with +<> `xpack.alerting.cancelAlertsOnRuleTimeout`:: -Specifies whether to skip writing alerts and scheduling actions if rule execution is cancelled due to timeout. Default: `true`. This setting can be overridden by individual rule types. +Specifies whether to skip writing alerts and scheduling actions if rule +processing was cancelled due to a timeout. Default: `true`. This setting can be +overridden by individual rule types. `xpack.alerting.rules.minimumScheduleInterval.value`:: Specifies the minimum schedule interval for rules. This minimum is applied to all rules created or updated after you set this value. The time is formatted as: diff --git a/docs/user/alerting/alerting-getting-started.asciidoc b/docs/user/alerting/alerting-getting-started.asciidoc index 584d45dc088fd..ca0b8ff8ee111 100644 --- a/docs/user/alerting/alerting-getting-started.asciidoc +++ b/docs/user/alerting/alerting-getting-started.asciidoc @@ -63,7 +63,7 @@ Rule schedules are defined as an interval between subsequent checks, and can ran [IMPORTANT] ============================================== -The intervals of rule checks in {kib} are approximate. The timing of their execution is affected by factors such as the frequency at which tasks are claimed and the task load on the system. See <> for more information. +The intervals of rule checks in {kib} are approximate. Their timing is affected by factors such as the frequency at which tasks are claimed and the task load on the system. Refer to <> for more information. ============================================== [float] @@ -82,7 +82,7 @@ The result is a template: all the parameters needed to invoke a service are supp In the server monitoring example, the `email` connector type is used, and `server` is mapped to the body of the email, using the template string `CPU on {{server}} is high`. -When the rule detects the condition, it creates an <> containing the details of the condition, renders the template with these details such as server name, and executes the action on the {kib} server by invoking the `email` connector type. +When the rule detects the condition, it creates an <> containing the details of the condition, renders the template with these details such as server name, and runs the action on the {kib} server by invoking the `email` connector type. image::images/what-is-an-action.svg[Actions are like templates that are rendered when an alert detects a condition] diff --git a/docs/user/alerting/alerting-setup.asciidoc b/docs/user/alerting/alerting-setup.asciidoc index 6f8caedde3e18..2b92e8caa7ef9 100644 --- a/docs/user/alerting/alerting-setup.asciidoc +++ b/docs/user/alerting/alerting-setup.asciidoc @@ -62,7 +62,7 @@ Rules and connectors are isolated to the {kib} space in which they were created. [[alerting-authorization]] === Authorization -Rules are authorized using an <> associated with the last user to edit the rule. This API key captures a snapshot of the user's privileges at the time of edit and is subsequently used to run all background tasks associated with the rule, including condition checks, like {es} queries, and action executions. The following rule actions will re-generate the API key: +Rules are authorized using an <> associated with the last user to edit the rule. This API key captures a snapshot of the user's privileges at the time of edit and is subsequently used to run all background tasks associated with the rule, including condition checks like {es} queries and triggered actions. The following rule actions will re-generate the API key: * Creating a rule * Enabling a disabled rule diff --git a/docs/user/alerting/alerting-troubleshooting.asciidoc b/docs/user/alerting/alerting-troubleshooting.asciidoc index 5978d0f903145..32c77d7fa57a7 100644 --- a/docs/user/alerting/alerting-troubleshooting.asciidoc +++ b/docs/user/alerting/alerting-troubleshooting.asciidoc @@ -52,7 +52,7 @@ Diagnosing these may be difficult - but there may be log messages for error cond === Use the REST APIs There is a rich set of HTTP endpoints to introspect and manage rules and connectors. -One of the http endpoints available for actions is the POST <>. You can use this to “test” an action. For instance, if you have a server log action created, you can execute it via curling the endpoint: +One of the http endpoints available for actions is the POST <>. You can use this to “test” an action. For instance, if you have a server log action created, you can run it via curling the endpoint: [source, txt] -------------------------------------------------- curl -X POST -k \ @@ -75,7 +75,7 @@ The same REST POST _execute API command will be: kbn-action execute a692dc89-15b9-4a3c-9e47-9fb6872e49ce ‘{"params":{"subject":"hallo","message":"hallo!","to":["me@example.com"]}}’ -------------------------------------------------- -The result of this http request (and printed to stdout by https://github.com/pmuellr/kbn-action[kbn-action]) will be data returned by the action execution, along with error messages if errors were encountered. +The result of this http request (and printed to stdout by https://github.com/pmuellr/kbn-action[kbn-action]) will be data returned by the action, along with error messages if errors were encountered. [float] [[alerting-error-banners]] @@ -92,8 +92,8 @@ image::images/rules-details-health.png[Rule details page with the errors banner] [[task-manager-diagnostics]] === Task Manager diagnostics -Under the hood, *Rules and Connectors* uses a plugin called Task Manager, which handles the scheduling, execution, and error handling of the tasks. -This means that failure cases in Rules or Connectors will, at times, be revealed by the Task Manager mechanism, rather than the Rules mechanism. +Under the hood, {rules-ui} uses a plugin called Task Manager, which handles the scheduling, running, and error handling of the tasks. +This means that failure cases in {rules-ui} will, at times, be revealed by the Task Manager mechanism, rather than the Rules mechanism. Task Manager provides a visible status which can be used to diagnose issues and is very well documented <> and <>. Task Manager uses the `.kibana_task_manager` index, an internal index that contains all the saved objects that represent the tasks in the system. diff --git a/docs/user/alerting/create-and-manage-rules.asciidoc b/docs/user/alerting/create-and-manage-rules.asciidoc index ba1629abd9c86..52db2ed51217e 100644 --- a/docs/user/alerting/create-and-manage-rules.asciidoc +++ b/docs/user/alerting/create-and-manage-rules.asciidoc @@ -44,7 +44,7 @@ Notify:: This value limits how often actions are repeated when an alert rem [[alerting-concepts-suppressing-duplicate-notifications]] [NOTE] ============================================== -Since actions are executed per alert, a rule can end up generating a large number of actions. Take the following example where a rule is monitoring three servers every minute for CPU usage > 0.9, and the rule is set to notify **Every time alert is active**: +Since actions are triggered per alert, a rule can end up generating a large number of actions. Take the following example where a rule is monitoring three servers every minute for CPU usage > 0.9, and the rule is set to notify **Every time alert is active**: * Minute 1: server X123 > 0.9. *One email* is sent for server X123. * Minute 2: X123 and Y456 > 0.9. *Two emails* are sent, one for X123 and one for Y456. @@ -163,8 +163,8 @@ A rule can have one of the following statuses: `active`:: The conditions for the rule have been met, and the associated actions should be invoked. `ok`:: The conditions for the rule have not been met, and the associated actions are not invoked. -`error`:: An error was encountered during rule execution. -`pending`:: The rule has not yet executed. The rule was either just created, or enabled after being disabled. +`error`:: An error was encountered by the rule. +`pending`:: The rule has not yet run. The rule was either just created, or enabled after being disabled. `unknown`:: A problem occurred when calculating the status. Most likely, something went wrong with the alerting code. [float] diff --git a/docs/user/alerting/rule-types/es-query.asciidoc b/docs/user/alerting/rule-types/es-query.asciidoc index dba8a4878cb26..c8f98808ca552 100644 --- a/docs/user/alerting/rule-types/es-query.asciidoc +++ b/docs/user/alerting/rule-types/es-query.asciidoc @@ -26,7 +26,7 @@ Index:: Specifies an *index or data view* and a *time field* that is used for the *time window*. Size:: Specifies the number of documents to pass to the configured actions when the threshold condition is met. -{es} query:: Specifies the ES DSL query to execute. The number of documents that +{es} query:: Specifies the ES DSL query. The number of documents that match this query is evaluated against the threshold condition. Only the `query` field is used, other DSL fields are not considered. Threshold:: Defines a threshold value and a comparison operator (`is above`, @@ -81,7 +81,7 @@ image::images/rule-types-es-query-example-action-variable.png[Iterate over hits Use the *Test query* feature to verify that your query DSL is valid. -* Valid queries are executed against the configured *index* using the configured +* Valid queries are run against the configured *index* using the configured *time window*. The number of documents that match the query is displayed. + [role="screenshot"] @@ -95,16 +95,14 @@ image::user/alerting/images/rule-types-es-query-invalid.png[Test {es} query show [float] ==== Handling multiple matches of the same document -This rule type checks for duplication of document matches across rule -executions. If you configure the rule with a schedule interval smaller than the -time window, and a document matches a query in multiple rule executions, it is -alerted on only once. +This rule type checks for duplication of document matches across multiple runs. +If you configure the rule with a schedule interval smaller than the time window, +and a document matches a query in multiple runs, it is alerted on only once. The rule uses the timestamp of the matches to avoid alerting on the same match multiple times. The timestamp of the latest match is used for evaluating the -rule conditions when the rule is executed. Only matches between the latest -timestamp from the previous execution and the actual rule execution are -considered. +rule conditions when the rule runs. Only matches between the latest timestamp +from the previous run and the current run are considered. Suppose you have a rule configured to run every minute. The rule uses a time window of 1 hour and checks if there are more than 99 matches for the query. The @@ -112,16 +110,16 @@ window of 1 hour and checks if there are more than 99 matches for the query. The [cols="3*<"] |=== -| `Execution 1 (0:00)` +| `Run 1 (0:00)` | Rule finds 113 matches in the last hour: `113 > 99` | Rule is active and user is alerted. -| `Execution 2 (0:01)` +| `Run 2 (0:01)` | Rule finds 127 matches in the last hour. 105 of the matches are duplicates that were already alerted on previously, so you actually have 22 matches: `22 !> 99` | No alert. -| `Execution 3 (0:02)` +| `Run 3 (0:02)` | Rule finds 159 matches in the last hour. 88 of the matches are duplicates that were already alerted on previously, so you actually have 71 matches: `71 !> 99` | No alert. -| `Execution 4 (0:03)` +| `Run 4 (0:03)` | Rule finds 190 matches in the last hour. 71 of them are duplicates that were already alerted on previously, so you actually have 119 matches: `119 > 99` | Rule is active and user is alerted. |=== \ No newline at end of file diff --git a/docs/user/alerting/rule-types/index-threshold.asciidoc b/docs/user/alerting/rule-types/index-threshold.asciidoc index c65b0f66b1b63..03f855a861022 100644 --- a/docs/user/alerting/rule-types/index-threshold.asciidoc +++ b/docs/user/alerting/rule-types/index-threshold.asciidoc @@ -52,7 +52,7 @@ In this example, you will use the {kib} < Rules and Connectors**. -. Create a new rule that is checked every four hours and executes actions when the rule status changes. +. Create a new rule that is checked every four hours and triggers actions when the rule status changes. + [role="screenshot"] image::user/alerting/images/rule-types-index-threshold-select.png[Choosing an index threshold rule type] diff --git a/docs/user/alerting/troubleshooting/alerting-common-issues.asciidoc b/docs/user/alerting/troubleshooting/alerting-common-issues.asciidoc index 7ab34dacacd98..75a158e6d364f 100644 --- a/docs/user/alerting/troubleshooting/alerting-common-issues.asciidoc +++ b/docs/user/alerting/troubleshooting/alerting-common-issues.asciidoc @@ -40,35 +40,34 @@ When diagnosing issues related to alerting, focus on the tasks that begin with ` Alerting tasks always begin with `alerting:`. For example, the `alerting:.index-threshold` tasks back the <>. Action tasks always begin with `actions:`. For example, the `actions:.index` tasks back the <>. -For more details on monitoring and diagnosing task execution in Task Manager, see <>. +For more details on monitoring and diagnosing tasks in Task Manager, refer to <>. [float] [[connector-tls-settings]] -==== Connectors have TLS errors when executing actions +==== Connectors have TLS errors when running actions *Problem* -When executing actions, a connector gets a TLS socket error when connecting to -the server. +A connector gets a TLS socket error when connecting to the server to run an action. *Solution* Configuration options are available to specialize connections to TLS servers, -including ignoring server certificate validation, and providing certificate -authority data to verify servers using custom certificates. For more details, -see <>. +including ignoring server certificate validation and providing certificate +authority data to verify servers using custom certificates. For more details, +see <>. [float] -[[rules-long-execution-time]] +[[rules-long-run-time]] ==== Rules take a long time to run *Problem* -Rules are taking a long time to execute and are impacting the overall health of your deployment. +Rules are taking a long time to run and are impacting the overall health of your deployment. [IMPORTANT] ============================================== -By default, only users with a `superuser` role can query the experimental[] {kib} event log because it is a system index. To enable additional users to execute this query, assign `read` privileges to the `.kibana-event-log*` index. +By default, only users with a `superuser` role can query the experimental[] {kib} event log because it is a system index. To enable additional users to run this query, assign `read` privileges to the `.kibana-event-log*` index. ============================================== *Solution* @@ -87,9 +86,9 @@ image::images/rule-details-timeout-error.png[Rule details page with timeout erro If you want your rules to run longer, update the `xpack.alerting.rules.run.timeout` configuration in your <>. You can also target a specific rule type by using `xpack.alerting.rules.run.ruleTypeOverrides`. -Rules that consistently run longer than their <> may produce unexpected results. If the average run duration, visible on the <>, is greater than the check interval, consider increasing the check interval. +Rules that consistently run longer than their <> may produce unexpected results. If the average run duration, visible on the <>, is greater than the check interval, consider increasing the check interval. -To get all long-running rules, you can query for a list of rule ids, bucketed by their execution times: +To get all long-running rules, you can query for a list of rule ids, bucketed by their run times: [source,console] -------------------------------------------------- @@ -160,9 +159,9 @@ GET /.kibana-event-log*/_search -------------------------------------------------- // TEST -<1> This queries for rules executed in the last day. Update the values of `lte` and `gte` to query over a different time range. -<2> Use `event.provider: actions` to query for long-running action executions. -<3> Execution durations are stored as nanoseconds. This adds a runtime field to convert that duration into seconds. +<1> This queries for rules run in the last day. Update the values of `lte` and `gte` to query over a different time range. +<2> Use `event.provider: actions` to query for long-running actions. +<3> Run durations are stored as nanoseconds. This adds a runtime field to convert that duration into seconds. <4> This interval buckets the `event.duration_in_seconds` runtime field into 1 second intervals. Update this value to change the granularity of the buckets. If you are unable to use runtime fields, make sure this aggregation targets `event.duration` and use nanoseconds for the interval. <5> This retrieves the top 10 rule ids for this duration interval. Update this value to retrieve more rule ids. @@ -237,10 +236,10 @@ This query returns the following: } } -------------------------------------------------- -<1> Most rule execution durations fall within the first bucket (0 - 1 seconds). -<2> A single rule with id `41893910-6bca-11eb-9e0d-85d233e3ee35` took between 30 and 31 seconds to execute. +<1> Most run durations fall within the first bucket (0 - 1 seconds). +<2> A single rule with id `41893910-6bca-11eb-9e0d-85d233e3ee35` took between 30 and 31 seconds to run. -Use the <> to retrieve additional information about rules that take a long time to execute. +Use the <> to retrieve additional information about rules that take a long time to run. [float] [[rule-cannot-decrypt-api-key]] @@ -248,11 +247,11 @@ Use the <> to retrieve additional information about r *Problem*: -The rule fails to execute and has an `Unable to decrypt attribute "apiKey"` error. +The rule fails to run and has an `Unable to decrypt attribute "apiKey"` error. *Solution*: -This error happens when the `xpack.encryptedSavedObjects.encryptionKey` value used to create the rule does not match the value used during rule execution. Depending on the scenario, there are different ways to solve this problem: +This error happens when the `xpack.encryptedSavedObjects.encryptionKey` value used to create the rule does not match the value used when the rule runs. Depending on the scenario, there are different ways to solve this problem: [cols="2*<"] |=== diff --git a/docs/user/alerting/troubleshooting/event-log-index.asciidoc b/docs/user/alerting/troubleshooting/event-log-index.asciidoc index 5016b6d6f19c9..a0e6cd11ed184 100644 --- a/docs/user/alerting/troubleshooting/event-log-index.asciidoc +++ b/docs/user/alerting/troubleshooting/event-log-index.asciidoc @@ -6,15 +6,16 @@ experimental[] Use the event log index to determine: -* Whether a rule successfully ran but its associated actions did not +* Whether a rule ran successfully but its associated actions did not * Whether a rule was ever activated -* Additional information about rule execution errors -* Duration times for rule and action executions +* Additional information about errors when the rule ran +* Run durations for the rules and actions [float] -==== Example Event Log Queries +==== Example event log queries + +The following event log query looks at all events related to a specific rule id: -Event log query to look at all event related to a specific rule id: [source, txt] -------------------------------------------------- GET /.kibana-event-log*/_search @@ -77,7 +78,9 @@ GET /.kibana-event-log*/_search } -------------------------------------------------- -Event log query to look at all events related to executing a rule or action. These events include duration. +The following event log query looks at all events related to running a rule or +action. These events include duration: + [source, txt] -------------------------------------------------- GET /.kibana-event-log*/_search @@ -124,8 +127,10 @@ GET /.kibana-event-log*/_search } -------------------------------------------------- -Event log query to look at the errors. -You should see an `error.message` property in that event, with a message from the action executor that might provide more detail on why the action encountered an error: +The following event log query looks at the errors. You should see an +`error.message` property in that event, with a message that might provide more +details about why the action encountered an error: + [source, txt] -------------------------------------------------- { @@ -150,7 +155,9 @@ You should see an `error.message` property in that event, with a message from th } -------------------------------------------------- -And see the errors for the rules you might provide the next search query: +You might also see the errors for the rules, which can use in the next search +query. For example: + [source, txt] -------------------------------------------------- { diff --git a/docs/user/alerting/troubleshooting/testing-connectors.asciidoc b/docs/user/alerting/troubleshooting/testing-connectors.asciidoc index 64ba106655321..fd5a897dfd4c3 100644 --- a/docs/user/alerting/troubleshooting/testing-connectors.asciidoc +++ b/docs/user/alerting/troubleshooting/testing-connectors.asciidoc @@ -15,9 +15,10 @@ image::user/alerting/images/email-connector-test.png[Rule management page with t image::user/alerting/images/teams-connector-test.png[Five clauses define the condition to detect] [float] -==== experimental[] Troubleshooting Connectors with `kbn-action` tool +==== experimental[] Troubleshooting connectors with the `kbn-action` tool -Executing an Email action via https://github.com/pmuellr/kbn-action[kbn-action]. In this example, is using a cloud deployment of the stack: +You can run an email action via https://github.com/pmuellr/kbn-action[kbn-action]. +In this example, it is a Cloud deployment of the {stack}: [source, txt] -------------------------------------------------- @@ -44,7 +45,8 @@ $ kbn-action ls } ] -------------------------------------------------- -and then execute this: + +You can then run the following test: [source, txt] -------------------------------------------------- From ec2062ae4e38d96441b61227a3711faee8a37465 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Wed, 4 May 2022 15:24:56 -0700 Subject: [PATCH 57/68] [Reporting] Update docs to use screenshotting config properties (#127518) * [Reporting] Update docs to use screenshotting config properties * add the remaining capture settings moved from reporting Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- docs/settings/reporting-settings.asciidoc | 42 +++++++++---------- ...porting-production-considerations.asciidoc | 4 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/settings/reporting-settings.asciidoc b/docs/settings/reporting-settings.asciidoc index b5e0af7e188a1..d706526730459 100644 --- a/docs/settings/reporting-settings.asciidoc +++ b/docs/settings/reporting-settings.asciidoc @@ -63,6 +63,9 @@ Reporting generates reports in the background and jobs are coordinated using doc in {es}. Depending on how often you generate reports and the overall number of reports, you might need to change the following settings. +`xpack.reporting.capture.maxAttempts` {ess-icon}:: +If capturing a report fails for any reason, {kib} will re-queue the report job for retry, as many times as this setting. Defaults to `3`. + `xpack.reporting.queue.indexInterval`:: How often the index that stores reporting jobs rolls over to a new index. Valid values are `year`, `month`, `week`, `day`, and `hour`. Defaults to `week`. @@ -86,26 +89,23 @@ Specifies the {time-units}[time] that the reporting poller waits between polling [[reporting-capture-settings]] ==== Capture settings -Reporting works by capturing screenshots from {kib}. The following settings control the capturing process. +Reporting uses an internal "screenshotting" plugin to capture screenshots from {kib}. The following settings control the capturing process. -`xpack.reporting.capture.timeouts.openUrl` {ess-icon}:: +`xpack.screenshotting.capture.timeouts.openUrl` {ess-icon}:: Specify the {time-units}[time] to allow the Reporting browser to wait for the "Loading..." screen to dismiss and find the initial data for the page. If the time is exceeded, a screenshot is captured showing the current page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `1m`. -`xpack.reporting.capture.timeouts.waitForElements` {ess-icon}:: +`xpack.screenshotting.capture.timeouts.waitForElements` {ess-icon}:: Specify the {time-units}[time] to allow the Reporting browser to wait for all visualization panels to load on the page. If the time is exceeded, a screenshot is captured showing the current page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `30s`. -`xpack.reporting.capture.timeouts.renderComplete` {ess-icon}:: +`xpack.screenshotting.capture.timeouts.renderComplete` {ess-icon}:: Specify the {time-units}[time] to allow the Reporting browser to wait for all visualizations to fetch and render the data. If the time is exceeded, a screenshot is captured showing the current page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `30s`. -NOTE: If any timeouts from `xpack.reporting.capture.timeouts.*` settings occur when +NOTE: If any timeouts from `xpack.screenshotting.capture.timeouts.*` settings occur when running a report job, Reporting will log the error and try to continue capturing the page with a screenshot. As a result, a download will be available, but there will likely be errors in the visualizations in the report. -`xpack.reporting.capture.maxAttempts` {ess-icon}:: -If capturing a report fails for any reason, {kib} will re-attempt other reporting job, as many times as this setting. Defaults to `3`. - -`xpack.reporting.capture.loadDelay`:: +`xpack.screenshotting.capture.loadDelay`:: deprecated:[8.0.0,This setting has no effect.] Specify the {time-units}[amount of time] before taking a screenshot when visualizations are not evented. All visualizations that ship with {kib} are evented, so this setting should not have much effect. If you are seeing empty images instead of visualizations, try increasing this value. Defaults to `3s`. *NOTE*: This setting exists for backwards compatibility, but is unused and therefore does not have an affect on reporting performance. [float] @@ -114,16 +114,16 @@ deprecated:[8.0.0,This setting has no effect.] Specify the {time-units}[amount o For PDF and PNG reports, Reporting spawns a headless Chromium browser process on the server to load and capture a screenshot of the {kib} app. When installing {kib} on Linux and Windows platforms, the Chromium binary comes bundled with the {kib} download. For Mac platforms, the Chromium binary is downloaded the first time {kib} is started. -`xpack.reporting.capture.browser.chromium.disableSandbox`:: +`xpack.screenshotting.browser.chromium.disableSandbox`:: It is recommended that you research the feasibility of enabling unprivileged user namespaces. An exception is if you are running {kib} in Docker because the container runs in a user namespace with the built-in seccomp/bpf filters. For more information, refer to <>. Defaults to `false` for all operating systems except Debian and Red Hat Linux, which use `true`. -`xpack.reporting.capture.browser.chromium.proxy.enabled`:: -Enables the proxy for Chromium to use. When set to `true`, you must also specify the `xpack.reporting.capture.browser.chromium.proxy.server` setting. Defaults to `false`. +`xpack.screenshotting.browser.chromium.proxy.enabled`:: +Enables the proxy for Chromium to use. When set to `true`, you must also specify the `xpack.screenshotting.browser.chromium.proxy.server` setting. Defaults to `false`. -`xpack.reporting.capture.browser.chromium.proxy.server`:: +`xpack.screenshotting.browser.chromium.proxy.server`:: The uri for the proxy server. Providing the username and password for the proxy server via the uri is not supported. -`xpack.reporting.capture.browser.chromium.proxy.bypass`:: +`xpack.screenshotting.browser.chromium.proxy.bypass`:: An array of hosts that should not go through the proxy server and should use a direct connection instead. Examples of valid entries are "elastic.co", "*.elastic.co", ".elastic.co", ".elastic.co:5601". [float] @@ -136,13 +136,13 @@ If the Chromium browser is asked to send a request that violates the network pol NOTE: {kib} installations are not designed to be publicly accessible over the internet. The Reporting network policy and other capabilities of the Elastic Stack security features do not change this condition. -`xpack.reporting.capture.networkPolicy`:: +`xpack.screenshotting.networkPolicy`:: Capturing a screenshot from a {kib} page involves sending out requests for all the linked web assets. For example, a Markdown visualization can show an image from a remote server. -`xpack.reporting.capture.networkPolicy.enabled`:: +`xpack.screenshotting.networkPolicy.enabled`:: When `false`, disables the *Reporting* network policy. Defaults to `true`. -`xpack.reporting.capture.networkPolicy.rules`:: +`xpack.screenshotting.networkPolicy.rules`:: A policy is specified as an array of objects that describe what to allow or deny based on a host or protocol. If a host or protocol is not specified, the rule matches any host or protocol. The rule objects are evaluated sequentially from the beginning to the end of the array, and continue until there is a matching rule. If no rules allow a request, the request is denied. @@ -150,14 +150,14 @@ The rule objects are evaluated sequentially from the beginning to the end of the [source,yaml] ------------------------------------------------------- # Only allow requests to placeholder.com -xpack.reporting.capture.networkPolicy: +xpack.screenshotting.networkPolicy: rules: [ { allow: true, host: "placeholder.com" } ] ------------------------------------------------------- [source,yaml] ------------------------------------------------------- # Only allow requests to https://placeholder.com -xpack.reporting.capture.networkPolicy: +xpack.screenshotting.networkPolicy: rules: [ { allow: true, host: "placeholder.com", protocol: "https:" } ] ------------------------------------------------------- @@ -166,7 +166,7 @@ A final `allow` rule with no host or protocol allows all requests that are not e [source,yaml] ------------------------------------------------------- # Denies requests from http://placeholder.com, but anything else is allowed. -xpack.reporting.capture.networkPolicy: +xpack.screenshotting.networkPolicy: rules: [{ allow: false, host: "placeholder.com", protocol: "http:" }, { allow: true }]; ------------------------------------------------------- @@ -175,7 +175,7 @@ A network policy can be composed of multiple rules: [source,yaml] ------------------------------------------------------- # Allow any request to http://placeholder.com but for any other host, https is required -xpack.reporting.capture.networkPolicy +xpack.screenshotting.networkPolicy rules: [ { allow: true, host: "placeholder.com", protocol: "http:" }, { allow: true, protocol: "https:" }, diff --git a/docs/user/production-considerations/reporting-production-considerations.asciidoc b/docs/user/production-considerations/reporting-production-considerations.asciidoc index f673c4538f443..20ea82be9c6e4 100644 --- a/docs/user/production-considerations/reporting-production-considerations.asciidoc +++ b/docs/user/production-considerations/reporting-production-considerations.asciidoc @@ -31,10 +31,10 @@ distributions don't have user namespaces enabled by default, or they require the automatically disable the sandbox when it is running on Debian because additional steps are required to enable unprivileged usernamespaces. In these situations, you'll see the following message in your {kib} startup logs: `Chromium sandbox provides an additional layer of protection, but is not supported for your OS. -Automatically setting 'xpack.reporting.capture.browser.chromium.disableSandbox: true'.` +Automatically setting 'xpack.screenshotting.browser.chromium.disableSandbox: true'.` Reporting automatically enables the Chromium sandbox at startup when a supported OS is detected. However, if your kernel is 3.8 or newer, it's -recommended to set `xpack.reporting.capture.browser.chromium.disableSandbox: false` in your `kibana.yml` to explicitly enable usernamespaces. +recommended to set `xpack.screenshotting.browser.chromium.disableSandbox: false` in your `kibana.yml` to explicitly enable usernamespaces. [float] [[reporting-docker-sandbox]] From 0ea637477785a287505ac25775f7c941a6850bdf Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 4 May 2022 17:42:04 -0500 Subject: [PATCH 58/68] fix "Default Saved Object Field Metrics" task in main on-merge job --- .buildkite/scripts/saved_object_field_metrics.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.buildkite/scripts/saved_object_field_metrics.sh b/.buildkite/scripts/saved_object_field_metrics.sh index 3b6c63eeff3b0..4cc249db20edc 100755 --- a/.buildkite/scripts/saved_object_field_metrics.sh +++ b/.buildkite/scripts/saved_object_field_metrics.sh @@ -5,9 +5,8 @@ set -euo pipefail source .buildkite/scripts/common/util.sh echo '--- Default Saved Object Field Metrics' -cd "$XPACK_DIR" checks-reporter-with-killswitch "Capture Kibana Saved Objects field count metrics" \ node scripts/functional_tests \ --debug --bail \ --kibana-install-dir "$KIBANA_BUILD_LOCATION" \ - --config test/saved_objects_field_count/config.ts + --config x-pack/test/saved_objects_field_count/config.ts From 8d54b1547b409af31fff568690d08e9d28cc2732 Mon Sep 17 00:00:00 2001 From: spalger Date: Wed, 4 May 2022 18:00:03 -0500 Subject: [PATCH 59/68] include test_group_env when running saved_object_field_metrics.sh --- .buildkite/scripts/steps/on_merge_build_and_metrics.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.buildkite/scripts/steps/on_merge_build_and_metrics.sh b/.buildkite/scripts/steps/on_merge_build_and_metrics.sh index fb05bb99b0c54..de46ba58e9d52 100755 --- a/.buildkite/scripts/steps/on_merge_build_and_metrics.sh +++ b/.buildkite/scripts/steps/on_merge_build_and_metrics.sh @@ -7,4 +7,6 @@ set -euo pipefail .buildkite/scripts/build_kibana_plugins.sh .buildkite/scripts/post_build_kibana_plugins.sh .buildkite/scripts/post_build_kibana.sh + +source ".buildkite/scripts/steps/test/test_group_env.sh" .buildkite/scripts/saved_object_field_metrics.sh From 99c659c58a094fbd60ced483807d783b965e28c7 Mon Sep 17 00:00:00 2001 From: Irina Truong Date: Wed, 4 May 2022 16:49:13 -0700 Subject: [PATCH 60/68] Fix for Insufficient permissions error in Enterprise Search plugin when filtering traffic or Enterprise Search is down (#131472) * Fix tests. * Remove debug code. * Force CI to rerun. * Review feedback. * Well this didn't work. * Nope, didn't work either. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/lib/check_access.test.ts | 11 +++++++++++ .../enterprise_search/server/lib/check_access.ts | 4 ++-- .../lib/enterprise_search_config_api.test.ts | 13 ++++++++++++- .../server/lib/enterprise_search_config_api.ts | 14 +++++++++++++- .../server/routes/enterprise_search/config_data.ts | 7 ++++++- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts b/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts index 28d9fe363ff0f..3da63a63828ae 100644 --- a/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/check_access.test.ts @@ -196,6 +196,17 @@ describe('checkAccess', () => { hasWorkplaceSearchAccess: false, }); }); + + it('falls back to no access if response error', async () => { + (callEnterpriseSearchConfigAPI as jest.Mock).mockImplementationOnce(() => ({ + responseStatus: 500, + responseStatusText: 'failed', + })); + expect(await checkAccess(mockDependencies)).toEqual({ + hasAppSearchAccess: false, + hasWorkplaceSearchAccess: false, + }); + }); }); }); }); diff --git a/x-pack/plugins/enterprise_search/server/lib/check_access.ts b/x-pack/plugins/enterprise_search/server/lib/check_access.ts index a77415f2c2f12..444fa9d4fdb29 100644 --- a/x-pack/plugins/enterprise_search/server/lib/check_access.ts +++ b/x-pack/plugins/enterprise_search/server/lib/check_access.ts @@ -98,6 +98,6 @@ export const checkAccess = async ({ // When enterpriseSearch.host is defined in kibana.yml, // make a HTTP call which returns product access - const { access } = (await callEnterpriseSearchConfigAPI({ request, config, log })) || {}; - return access || DENY_ALL_PLUGINS; + const response = (await callEnterpriseSearchConfigAPI({ request, config, log })) || {}; + return 'access' in response ? response.access || DENY_ALL_PLUGINS : DENY_ALL_PLUGINS; }; diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts index 5f8b261f82f16..ad55b41c02cee 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.test.ts @@ -207,8 +207,19 @@ describe('callEnterpriseSearchConfigAPI', () => { (fetch as unknown as jest.Mock).mockReturnValueOnce(Promise.resolve('Bad Data')); expect(await callEnterpriseSearchConfigAPI(mockDependencies)).toEqual({}); expect(mockDependencies.log.error).toHaveBeenCalledWith( - 'Could not perform access check to Enterprise Search: TypeError: response.json is not a function' + 'Could not perform access check to Enterprise Search: 500' + ); + + (fetch as unknown as jest.Mock).mockReturnValueOnce( + Promise.resolve( + new Response('{}', { + status: 500, + statusText: 'I failed', + }) + ) ); + const expected = { responseStatus: 500, responseStatusText: 'I failed' }; + expect(await callEnterpriseSearchConfigAPI(mockDependencies)).toEqual(expected); }); it('handles timeouts', async () => { diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts index 7e27480426525..361a5613ab67e 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts @@ -26,6 +26,10 @@ interface Params { interface Return extends InitialAppData { publicUrl?: string; } +interface ResponseError { + responseStatus: number; + responseStatusText: string; +} /** * Calls an internal Enterprise Search API endpoint which returns @@ -38,7 +42,7 @@ export const callEnterpriseSearchConfigAPI = async ({ config, log, request, -}: Params): Promise => { +}: Params): Promise => { if (!config.host) return {}; const TIMEOUT_WARNING = `Enterprise Search access check took over ${config.accessCheckTimeoutWarning}ms. Please ensure your Enterprise Search server is responding normally and not adversely impacting Kibana load speeds.`; @@ -63,6 +67,14 @@ export const callEnterpriseSearchConfigAPI = async ({ }; const response = await fetch(enterpriseSearchUrl, options); + + if (!response.ok) { + return { + responseStatus: response.status, + responseStatusText: response.statusText, + }; + } + const data = await response.json(); warnMismatchedVersions(data?.version?.number, log); diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts index 95ab8e3c3a5a9..5be5bf8cc0373 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/config_data.ts @@ -17,7 +17,12 @@ export function registerConfigDataRoute({ router, config, log }: RouteDependenci async (context, request, response) => { const data = await callEnterpriseSearchConfigAPI({ request, config, log }); - if (!Object.keys(data).length) { + if ('responseStatus' in data) { + return response.customError({ + statusCode: data.responseStatus, + body: 'Error fetching data from Enterprise Search', + }); + } else if (!Object.keys(data).length) { return response.customError({ statusCode: 502, body: 'Error fetching data from Enterprise Search', From 79fc3815a4295edcfc895d83564ba90f6acfda04 Mon Sep 17 00:00:00 2001 From: jbyroads <45469917+jbyroads@users.noreply.github.com> Date: Wed, 4 May 2022 22:30:45 -0400 Subject: [PATCH 61/68] [ui] enhanced management landing text to update (#130426) index patterns to data views Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Spencer --- src/plugins/management/public/components/landing/landing.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/management/public/components/landing/landing.tsx b/src/plugins/management/public/components/landing/landing.tsx index 6ebf980420918..0851ba3343eee 100644 --- a/src/plugins/management/public/components/landing/landing.tsx +++ b/src/plugins/management/public/components/landing/landing.tsx @@ -46,7 +46,7 @@ export const ManagementLandingPage = ({

From fe92ccfbc411f2055ea29e0cb4805f3710659f72 Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Thu, 5 May 2022 01:19:46 -0400 Subject: [PATCH 62/68] [Security Solution][Admin][Policy] Adds policy list functional tests (#129786) --- .../view/components/policy_endpoint_count.tsx | 10 +- .../pages/policy/view/policy_list.test.tsx | 12 +- .../pages/policy/view/policy_list.tsx | 8 +- .../apps/endpoint/endpoint_list.ts | 5 +- .../apps/endpoint/index.ts | 1 + .../apps/endpoint/policy_details.ts | 2 + .../apps/endpoint/policy_list.ts | 111 ++++++++++++++++++ .../page_objects/endpoint_page.ts | 4 + .../page_objects/policy_page.ts | 18 ++- 9 files changed, 161 insertions(+), 10 deletions(-) create mode 100644 x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/components/policy_endpoint_count.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/components/policy_endpoint_count.tsx index 08c2f1909339d..b8b2f98173f21 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/components/policy_endpoint_count.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/components/policy_endpoint_count.tsx @@ -25,7 +25,7 @@ export const PolicyEndpointCount = memo< policyId: string; nonLinkCondition: boolean; } ->(({ policyId, nonLinkCondition, children, ...otherProps }) => { +>(({ policyId, nonLinkCondition, 'data-test-subj': dataTestSubj, children, ...otherProps }) => { const filterByPolicyQuery = `(language:kuery,query:'united.endpoint.Endpoint.policy.applied.id : "${policyId}"')`; const { search } = useLocation(); const { getAppUrl } = useAppUrl(); @@ -59,11 +59,15 @@ export const PolicyEndpointCount = memo< const clickHandler = useNavigateByRouterEventHandler(toRoutePathWithBackOptions); if (nonLinkCondition) { - return {children}; + return ( + + {children} + + ); } return ( // eslint-disable-next-line @elastic/eui/href-or-on-click - + {children} ); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx index 482fe0ba064bd..3ea50af79a9c3 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.test.tsx @@ -99,15 +99,23 @@ describe('When on the policy list page', () => { expect(policyNameCells).toBeTruthy(); expect(policyNameCells.length).toBe(5); }); - it('should show a avatar for the Created by column', () => { + it('should show an avatar and name for the Created by column', () => { + const expectedAvatarName = policies.items[0].created_by; const createdByCells = renderResult.getAllByTestId('created-by-avatar'); + const firstCreatedByName = renderResult.getAllByTestId('created-by-name')[0]; expect(createdByCells).toBeTruthy(); expect(createdByCells.length).toBe(5); + expect(createdByCells[0].textContent).toEqual(expectedAvatarName.charAt(0)); + expect(firstCreatedByName.textContent).toEqual(expectedAvatarName); }); - it('should show a avatar for the Updated by column', () => { + it('should show an avatar and name for the Updated by column', () => { + const expectedAvatarName = policies.items[0].updated_by; const updatedByCells = renderResult.getAllByTestId('updated-by-avatar'); + const firstUpdatedByName = renderResult.getAllByTestId('updated-by-name')[0]; expect(updatedByCells).toBeTruthy(); expect(updatedByCells.length).toBe(5); + expect(updatedByCells[0].textContent).toEqual(expectedAvatarName.charAt(0)); + expect(firstUpdatedByName.textContent).toEqual(expectedAvatarName); }); it('should show the correct endpoint count', () => { const endpointCount = renderResult.getAllByTestId('policyEndpointCountLink'); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx index 884a8572ecfe2..67398cbe39a44 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_list.tsx @@ -189,7 +189,9 @@ export const PolicyList = memo(() => { - {name} + + {name} + ); @@ -222,7 +224,9 @@ export const PolicyList = memo(() => { - {name} + + {name} + ); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index 48dc450737229..0168a15f21b6e 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -82,7 +82,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await deleteAllDocsFromMetadataUnitedIndex(getService); await pageObjects.endpoint.navigateToEndpointList(); }); - it('finds no data in list and prompts onboarding to add policy', async () => { await testSubjects.exists('emptyPolicyTable'); }); @@ -99,7 +98,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { after(async () => { await deleteAllDocsFromMetadataCurrentIndex(getService); await deleteAllDocsFromMetadataUnitedIndex(getService); - await endpointTestResources.unloadEndpointData(indexedData); + if (indexedData) { + await endpointTestResources.unloadEndpointData(indexedData); + } }); it('finds page title', async () => { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts index c776dcf91602f..f74bd3b91cfce 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts @@ -35,6 +35,7 @@ export default function (providerContext: FtrProviderContext) { await endpointTestResources.installOrUpgradeEndpointFleetPackage(); }); loadTestFile(require.resolve('./endpoint_list')); + loadTestFile(require.resolve('./policy_list')); loadTestFile(require.resolve('./policy_details')); loadTestFile(require.resolve('./endpoint_telemetry')); loadTestFile(require.resolve('./trusted_apps_list')); 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 9bf6a19b4a589..c95afc743c839 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 @@ -331,6 +331,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); it('should show event filters card and link should go back to policy', async () => { await testSubjects.existOrFail('eventFilters-fleet-integration-card'); + const eventFiltersCard = await testSubjects.find('eventFilters-fleet-integration-card'); + await pageObjects.ingestManagerCreatePackagePolicy.scrollToCenterOfWindow(eventFiltersCard); await (await testSubjects.find('eventFilters-link-to-exceptions')).click(); await testSubjects.existOrFail('policyDetailsPage'); await (await testSubjects.find('policyDetailsBackLink')).click(); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts new file mode 100644 index 0000000000000..7020babc4520b --- /dev/null +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts @@ -0,0 +1,111 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { PolicyTestResourceInfo } from '../../services/endpoint_policy'; + +export default function ({ getPageObjects, getService }: FtrProviderContext) { + const browser = getService('browser'); + const pageObjects = getPageObjects([ + 'common', + 'endpoint', + 'policy', + 'endpointPageUtils', + 'ingestManagerCreatePackagePolicy', + 'trustedApps', + ]); + const testSubjects = getService('testSubjects'); + const policyTestResources = getService('policyTestResources'); + const endpointTestResources = getService('endpointTestResources'); + + describe('When on the Endpoint Policy List Page', () => { + before(async () => { + const endpointPackage = await policyTestResources.getEndpointPackage(); + await endpointTestResources.setMetadataTransformFrequency('1s', endpointPackage.version); + await browser.refresh(); + }); + + describe('with no policies', () => { + it('shows the empty page', async () => { + await pageObjects.policy.navigateToPolicyList(); + await testSubjects.existOrFail('emptyPolicyTable'); + }); + it('navigates to Fleet and ensures the integration page is loaded correctly', async () => { + const fleetButton = await testSubjects.find('onboardingStartButton'); + await fleetButton.click(); + await testSubjects.existOrFail('createPackagePolicy_pageTitle'); + expect(await testSubjects.getVisibleText('createPackagePolicy_pageTitle')).to.equal( + 'Add Endpoint Security integration' + ); + }); + it('navigates back to the policy list page', async () => { + const cancelButton = await testSubjects.find('createPackagePolicy_cancelBackLink'); + cancelButton.click(); + await pageObjects.policy.ensureIsOnListPage(); + }); + }); + describe('with policies', () => { + let indexedData: IndexedHostsAndAlertsResponse; + let policyInfo: PolicyTestResourceInfo; + before(async () => { + indexedData = await endpointTestResources.loadEndpointData(); + policyInfo = await policyTestResources.createPolicy(); + await browser.refresh(); + }); + after(async () => { + if (indexedData) { + await endpointTestResources.unloadEndpointData(indexedData); + } + if (policyInfo) { + await policyInfo.cleanup(); + } + }); + it('shows the policy list table', async () => { + await pageObjects.policy.navigateToPolicyList(); + await testSubjects.existOrFail('policyListTable'); + }); + it('navigates to the policy details page when the policy name is clicked and returns back to the policy list page using the header back button', async () => { + const policyName = (await testSubjects.findAll('policyNameCellLink'))[0]; + await policyName.click(); + await pageObjects.policy.ensureIsOnDetailsPage(); + const backButton = await testSubjects.find('policyDetailsBackLink'); + await backButton.click(); + await pageObjects.policy.ensureIsOnListPage(); + }); + describe('when the endpoint count link is clicked', () => { + it('navigates to the endpoint list page filtered by policy', async () => { + const endpointCount = (await testSubjects.findAll('policyEndpointCountLink'))[0]; + await endpointCount.click(); + await pageObjects.endpoint.ensureIsOnEndpointListPage(); + }); + it('admin searchbar contains the selected policy id', async () => { + const expectedPolicyId = indexedData.integrationPolicies[0].id; + await pageObjects.endpoint.ensureIsOnEndpointListPage(); + expect(await testSubjects.getVisibleText('adminSearchBar')).to.equal( + `united.endpoint.Endpoint.policy.applied.id : "${expectedPolicyId}"` + ); + }); + it('endpoint table shows the endpoints associated with selected policy', async () => { + const expectedPolicyName = indexedData.integrationPolicies[0].name; + await pageObjects.endpoint.ensureIsOnEndpointListPage(); + const policyName = (await testSubjects.findAll('policyNameCellLink'))[0]; + expect(await policyName.getVisibleText()).to.be.equal( + expectedPolicyName.substring(0, expectedPolicyName.indexOf('-')) + ); + }); + it('returns back to the policy list page when the header back button is clicked', async () => { + await pageObjects.endpoint.ensureIsOnEndpointListPage(); + const backButton = await testSubjects.find('endpointListBackLink'); + await backButton.click(); + await pageObjects.policy.ensureIsOnListPage(); + }); + }); + }); + }); +} diff --git a/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts b/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts index d4e2479d24bc7..21d7b25cabb34 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/endpoint_page.ts @@ -25,6 +25,10 @@ export function EndpointPageProvider({ getService, getPageObjects }: FtrProvider await pageObjects.header.waitUntilLoadingHasFinished(); }, + async ensureIsOnEndpointListPage() { + await testSubjects.existOrFail('endpointPage'); + }, + async waitForTableToHaveData(dataTestSubj: string, timeout = 2000) { await retry.waitForWithTimeout('table to have data', timeout, async () => { const tableData = await pageObjects.endpointPageUtils.tableData(dataTestSubj); diff --git a/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts b/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts index b5eccd0ef1147..da4fb936d6655 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/policy_page.ts @@ -14,6 +14,16 @@ export function EndpointPolicyPageProvider({ getService, getPageObjects }: FtrPr const retryService = getService('retry'); return { + /** + * Navigates to the Endpoint Policy List page + */ + async navigateToPolicyList() { + await pageObjects.common.navigateToUrlWithBrowserHistory( + 'securitySolutionManagement', + `/policy` + ); + await pageObjects.header.waitUntilLoadingHasFinished(); + }, /** * Navigates to the Endpoint Policy Details page * @@ -27,6 +37,12 @@ export function EndpointPolicyPageProvider({ getService, getPageObjects }: FtrPr await pageObjects.header.waitUntilLoadingHasFinished(); }, + /** + * Ensures the current page is the policy list page + */ + async ensureIsOnListPage() { + await testSubjects.existOrFail('policyListPage'); + }, /** * Finds and returns the Policy Details Page Save button */ @@ -127,7 +143,7 @@ export function EndpointPolicyPageProvider({ getService, getPageObjects }: FtrPr /** * Used when looking a the Ingest create/edit package policy pages. Finds the endpoint - * custom configuaration component + * custom configuration component * @param onEditPage */ async findPackagePolicyEndpointCustomConfiguration(onEditPage: boolean = false) { From 880c3218b418187e79d2e7f3294ac4fb96588504 Mon Sep 17 00:00:00 2001 From: Hrant Muradyan <69071631+hro-maker@users.noreply.github.com> Date: Thu, 5 May 2022 10:18:27 +0400 Subject: [PATCH 63/68] [Console] Fix Kibana DevTool Copy as CURL does not url encode special chars in indice date math. (#130970) * Fix cURL encoding for ES and Kibana requests. Add unit tests * move changing global object in beforeEach Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__fixtures__/editor_input1.txt | 4 +++ .../models/sense_editor/sense_editor.test.js | 30 +++++++++++++++++++ src/plugins/console/public/lib/es/es.ts | 22 ++++++++++---- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/plugins/console/public/application/models/sense_editor/__fixtures__/editor_input1.txt b/src/plugins/console/public/application/models/sense_editor/__fixtures__/editor_input1.txt index 398a0fdeab61f..517f22bd8ad6a 100644 --- a/src/plugins/console/public/application/models/sense_editor/__fixtures__/editor_input1.txt +++ b/src/plugins/console/public/application/models/sense_editor/__fixtures__/editor_input1.txt @@ -31,3 +31,7 @@ POST /_sql?format=txt "query": "SELECT prenom FROM claude_index WHERE prenom = 'claude' ", "fetch_size": 1 } + +GET ,,/_search?pretty + +GET kbn:/api/spaces/space \ No newline at end of file diff --git a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js index ff9d245f61275..4751d3ca29863 100644 --- a/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js +++ b/src/plugins/console/public/application/models/sense_editor/sense_editor.test.js @@ -10,6 +10,7 @@ import './sense_editor.test.mocks'; import $ from 'jquery'; import _ from 'lodash'; +import { URL } from 'url'; import { create } from './create'; import { XJson } from '@kbn/es-ui-shared-plugin/public'; @@ -19,6 +20,8 @@ const { collapseLiteralStrings } = XJson; describe('Editor', () => { let input; + let oldUrl; + let olldWindow; beforeEach(function () { // Set up our document body @@ -31,8 +34,19 @@ describe('Editor', () => { input = create(document.querySelector('#ConAppEditor')); $(input.getCoreEditor().getContainer()).show(); input.autocomplete._test.removeChangeListener(); + oldUrl = global.URL; + olldWindow = { ...global.window }; + global.URL = URL; + global.window = Object.create(window); + Object.defineProperty(window, 'location', { + value: { + origin: 'http://localhost:5620', + }, + }); }); afterEach(function () { + global.URL = oldUrl; + global.window = olldWindow; $(input.getCoreEditor().getContainer()).hide(); input.autocomplete._test.addChangeListener(); }); @@ -476,4 +490,20 @@ curl -XPOST "http://localhost:9200/_sql?format=txt" -H "kbn-xsrf: reporting" -H "fetch_size": 1 }'`.trim() ); + + multiReqCopyAsCurlTest( + 'with date math index', + editorInput1, + { start: { lineNumber: 35 }, end: { lineNumber: 35 } }, + ` + curl -XGET "http://localhost:9200/%3Cindex_1-%7Bnow%2Fd-2d%7D%3E%2C%3Cindex_1-%7Bnow%2Fd-1d%7D%3E%2C%3Cindex_1-%7Bnow%2Fd%7D%3E%2F_search?pretty" -H "kbn-xsrf: reporting"`.trim() + ); + + multiReqCopyAsCurlTest( + 'with Kibana API request', + editorInput1, + { start: { lineNumber: 37 }, end: { lineNumber: 37 } }, + ` +curl -XGET "http://localhost:5620/api/spaces/space" -H \"kbn-xsrf: reporting\"`.trim() + ); }); diff --git a/src/plugins/console/public/lib/es/es.ts b/src/plugins/console/public/lib/es/es.ts index 10d0ad95b0496..5e22c78547b96 100644 --- a/src/plugins/console/public/lib/es/es.ts +++ b/src/plugins/console/public/lib/es/es.ts @@ -7,7 +7,7 @@ */ import type { HttpResponse, HttpSetup } from '@kbn/core/public'; -import { trimStart } from 'lodash'; +import { trimStart, trimEnd } from 'lodash'; import { API_BASE_PATH, KIBANA_API_PREFIX } from '../../../common/constants'; const esVersion: string[] = []; @@ -79,11 +79,23 @@ function getKibanaRequestUrl(path: string) { export function constructUrl(baseUri: string, path: string) { const kibanaRequestUrl = getKibanaRequestUrl(path); + let url = `${trimEnd(baseUri, '/')}/${trimStart(path, '/')}`; if (kibanaRequestUrl) { - return kibanaRequestUrl; + url = kibanaRequestUrl; } - baseUri = baseUri.replace(/\/+$/, ''); - path = path.replace(/^\/+/, ''); - return baseUri + '/' + path; + + const { origin, pathname, search } = new URL(url); + return `${origin}${encodePathname(pathname)}${search ?? ''}`; } + +const encodePathname = (path: string) => { + const decodedPath = new URLSearchParams(`path=${path}`).get('path') ?? ''; + + // Skip if it is valid + if (path === decodedPath) { + return path; + } + + return `/${encodeURIComponent(trimStart(decodedPath, '/'))}`; +}; From 1d1e1f6430f5a39063181da9c6b5069afdb18aa8 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 5 May 2022 09:44:11 +0200 Subject: [PATCH 64/68] [ci] extract apm traces after in single user benchmarking pipeline (#130777) * [ci] extract apm traces after in single user benchmarking pipeline * add performance-testing-dataset-extractor dependency * use BUILD_ID for queries * bump version for extractor, update script * bump extractor version * fix path * upload artifacts to the public bucket --- .buildkite/pipelines/performance/daily.yml | 7 +++ .../scalability_dataset_extraction.sh | 36 +++++++++++ package.json | 1 + x-pack/test/performance/config.playwright.ts | 1 + yarn.lock | 59 ++++++++++++++++++- 5 files changed, 102 insertions(+), 2 deletions(-) create mode 100755 .buildkite/scripts/steps/functional/scalability_dataset_extraction.sh diff --git a/.buildkite/pipelines/performance/daily.yml b/.buildkite/pipelines/performance/daily.yml index 658ab3a72f186..07e73c27508a6 100644 --- a/.buildkite/pipelines/performance/daily.yml +++ b/.buildkite/pipelines/performance/daily.yml @@ -17,6 +17,13 @@ steps: agents: queue: kb-static-ubuntu depends_on: build + key: tests + + - label: ':shipit: Performance Tests dataset extraction for scalability benchmarking' + command: .buildkite/scripts/steps/functional/scalability_dataset_extraction.sh + agents: + queue: n2-2 + depends_on: tests - wait: ~ continue_on_failure: true diff --git a/.buildkite/scripts/steps/functional/scalability_dataset_extraction.sh b/.buildkite/scripts/steps/functional/scalability_dataset_extraction.sh new file mode 100755 index 0000000000000..b2ce23db38fdb --- /dev/null +++ b/.buildkite/scripts/steps/functional/scalability_dataset_extraction.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh + +USER_FROM_VAULT="$(retry 5 5 vault read -field=username secret/kibana-issues/dev/apm_parser_performance)" +PASS_FROM_VAULT="$(retry 5 5 vault read -field=password secret/kibana-issues/dev/apm_parser_performance)" +ES_SERVER_URL="https://kibana-ops-e2e-perf.es.us-central1.gcp.cloud.es.io:9243" +BUILD_ID=${BUILDKITE_BUILD_ID} +GCS_BUCKET="gs://kibana-performance/scalability-tests" + +.buildkite/scripts/bootstrap.sh + +echo "--- Extract APM metrics" +journeys=("login" "ecommerce_dashboard" "flight_dashboard" "web_logs_dashboard" "promotion_tracking_dashboard" "many_fields_discover") + +for i in "${journeys[@]}"; do + JOURNEY_NAME="${i}" + echo "Looking for JOURNEY=${JOURNEY_NAME} and BUILD_ID=${BUILD_ID} in APM traces" + + ./node_modules/.bin/performance-testing-dataset-extractor -u "${USER_FROM_VAULT}" -p "${PASS_FROM_VAULT}" -c "${ES_SERVER_URL}" -b "${BUILD_ID}" -n "${JOURNEY_NAME}" +done + +# archive json files with traces and upload as build artifacts +echo "--- Upload Kibana build, plugins and scalability traces to the public bucket" +mkdir "${BUILD_ID}" +tar -czf "${BUILD_ID}/scalability_traces.tar.gz" output +buildkite-agent artifact upload "${BUILD_ID}/scalability_traces.tar.gz" +buildkite-agent artifact download kibana-default.tar.gz ./"${BUILD_ID}" +buildkite-agent artifact download kibana-default-plugins.tar.gz ./"${BUILD_ID}" +echo "${BUILDKITE_COMMIT}" > "${BUILD_ID}/KIBANA_COMMIT_HASH" +gsutil -m cp -r "${BUILD_ID}" "${GCS_BUCKET}" +echo "--- Update reference to the latest CI build" +echo "${BUILD_ID}" > LATEST +gsutil cp LATEST "${GCS_BUCKET}" \ No newline at end of file diff --git a/package.json b/package.json index 2659301131a7a..a896137ee34b2 100644 --- a/package.json +++ b/package.json @@ -474,6 +474,7 @@ "@elastic/eslint-plugin-eui": "0.0.2", "@elastic/github-checks-reporter": "0.0.20b3", "@elastic/makelogs": "^6.0.0", + "@elastic/performance-testing-dataset-extractor": "^0.0.3", "@elastic/synthetics": "^1.0.0-beta.22", "@emotion/babel-preset-css-prop": "^11.2.0", "@emotion/jest": "^11.9.0", diff --git a/x-pack/test/performance/config.playwright.ts b/x-pack/test/performance/config.playwright.ts index 0b404d5c03bdb..44a53d7be80a1 100644 --- a/x-pack/test/performance/config.playwright.ts +++ b/x-pack/test/performance/config.playwright.ts @@ -63,6 +63,7 @@ export default async function ({ readConfigFile, log }: FtrConfigProviderContext performancePhase: process.env.TEST_PERFORMANCE_PHASE, journeyName: process.env.JOURNEY_NAME, testJobId, + testBuildId, }) .filter(([, v]) => !!v) .reduce((acc, [k, v]) => (acc ? `${acc},${k}=${v}` : `${k}=${v}`), ''), diff --git a/yarn.lock b/yarn.lock index 2b4a4c4cebaa6..5b1d85c282b2b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1496,6 +1496,16 @@ dependencies: "@elastic/ecs-helpers" "^1.1.0" +"@elastic/elasticsearch@7.17.0": + version "7.17.0" + resolved "https://registry.yarnpkg.com/@elastic/elasticsearch/-/elasticsearch-7.17.0.tgz#589fb219234cf1b0da23744e82b1d25e2fe9a797" + integrity sha512-5QLPCjd0uLmLj1lSuKSThjNpq39f6NmlTy9ROLFwG5gjyTgpwSqufDeYG/Fm43Xs05uF7WcscoO7eguI3HuuYA== + dependencies: + debug "^4.3.1" + hpagent "^0.1.1" + ms "^2.1.3" + secure-json-parse "^2.4.0" + "@elastic/elasticsearch@npm:@elastic/elasticsearch-canary@8.2.0-canary.2": version "8.2.0-canary.2" resolved "https://registry.yarnpkg.com/@elastic/elasticsearch-canary/-/elasticsearch-canary-8.2.0-canary.2.tgz#2513926cdbfe7c070e1fa6926f7829171b27cdba" @@ -1618,6 +1628,19 @@ resolved "https://registry.yarnpkg.com/@elastic/numeral/-/numeral-2.5.1.tgz#96acf39c3d599950646ef8ccfd24a3f057cf4932" integrity sha512-Tby6TKjixRFY+atVNeYUdGr9m0iaOq8230KTwn8BbUhkh7LwozfgKq0U98HRX7n63ZL62szl+cDKTYzh5WPCFQ== +"@elastic/performance-testing-dataset-extractor@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@elastic/performance-testing-dataset-extractor/-/performance-testing-dataset-extractor-0.0.3.tgz#c9823154c1d23c0dfec86f7183a5e2327999d0ca" + integrity sha512-ND33m4P1yOLPqnKnwWTcwDNB5dCw5NK9503e2WaZzljoy75RN9Lg5+YsQM7RFZKDs/+yNp7XRCJszeiUOcMFvg== + dependencies: + "@elastic/elasticsearch" "7.17.0" + axios "^0.26.1" + axios-curlirize "1.3.7" + lodash "^4.17.21" + qs "^6.10.3" + tslib "^2.3.1" + yargs "^17.4.0" + "@elastic/react-search-ui-views@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@elastic/react-search-ui-views/-/react-search-ui-views-1.6.0.tgz#7211d47c29ef0636c853721491b9905ac7ae58da" @@ -8691,6 +8714,11 @@ axe-core@^4.2.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.5.tgz#78d6911ba317a8262bfee292aeafcc1e04b49cc5" integrity sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA== +axios-curlirize@1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/axios-curlirize/-/axios-curlirize-1.3.7.tgz#0153c51a5af0e92370169daea33f234d588baad1" + integrity sha512-csSsuMyZj1dv1fL0zRPnDAHWrmlISMvK+wx9WJI/igRVDT4VMgbf2AVenaHghFLfI1nQijXUevYEguYV6u5hjA== + axios@^0.21.1: version "0.21.1" resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" @@ -8712,6 +8740,13 @@ axios@^0.25.0: dependencies: follow-redirects "^1.14.7" +axios@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== + dependencies: + follow-redirects "^1.14.8" + axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -14758,7 +14793,7 @@ follow-redirects@1.12.1: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6" integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg== -follow-redirects@^1.0.0, follow-redirects@^1.10.0, follow-redirects@^1.14.4, follow-redirects@^1.14.7: +follow-redirects@^1.0.0, follow-redirects@^1.10.0, follow-redirects@^1.14.4, follow-redirects@^1.14.7, follow-redirects@^1.14.8: version "1.14.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7" integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w== @@ -16219,7 +16254,7 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -hpagent@^0.1.2: +hpagent@^0.1.1, hpagent@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-0.1.2.tgz#cab39c66d4df2d4377dbd212295d878deb9bdaa9" integrity sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ== @@ -23481,6 +23516,13 @@ qs@^6.10.0: dependencies: side-channel "^1.0.4" +qs@^6.10.3: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + qs@^6.7.0: version "6.9.4" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" @@ -30656,6 +30698,19 @@ yargs@^17.0.1, yargs@^17.2.1, yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.0.0" +yargs@^17.4.0: + version "17.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.4.1.tgz#ebe23284207bb75cee7c408c33e722bfb27b5284" + integrity sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + yargs@^3.15.0: version "3.32.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" From a0294e59f1c712cd0e46c56e4aa667c9bc4b4f9d Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Thu, 5 May 2022 10:53:03 +0200 Subject: [PATCH 65/68] [Cases] Add the severity field to the cases API (#131394) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add severity field to create API and migration * Adds integration test for severity field migration * remove exclusive test * Change severity levels * Update integration tests for post case * Add more integration tests * Fix all cases list test * Fix some server test * Fix util server test * Fix client util test * Convert event log's duration from number to string in Kibana (keep as "long" in Elasticsearch) (#130819) * Convert event.duration to string in TypeScript, keep as long in Elasticsearch * Fix jest test * Fix functional tests * Add ecsStringOrNumber to event log schema * Fix jest test * Add utility functions to event log plugin * Use new event log utility functions * PR fixes Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * filter o11y rule aggregations (#131301) * [Cloud Posture] Display and save rules per benchmark (#131412) * Adding aria-label for discover data grid select document checkbox (#131277) * Update API docs (#130999) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * [CI] Use GCS buckets for bazel remote caching (#131345) * [Actionable Observability] Add license modal to rules table (#131232) * Add fix license link * fix localization * fix CI error * fix more translation issues Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * [RAM] Add shareable rule status filter (#130705) * rule state filter * turn off experiment * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Status filter API call * Fix tests * rename state to status, added tests * Address comments and fix tests * Revert experiment flag * Remove unused translations * Addressed comments Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> * [storybook] Watch for changes in packages (#131467) * [storybook] Watch for changes in packages * Update default_config.ts * Improve saved objects migrations failure errors and logs (#131359) * [Unified observability] Add tour step to guided setup (#131149) * [Lens] Improved interval input (#131372) * [Vega] Adjust vega doc for usage of ems files (#130948) * adjust vega doc * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl * Update docs/user/dashboard/vega-reference.asciidoc Co-authored-by: Nick Peihl Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Nick Peihl * Excess intersections * Create severity user action * Add severity to create_case user action * Fix and add integration tests * Minor improvements Co-authored-by: Mike Côté Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: mgiota Co-authored-by: Jordan <51442161+JordanSh@users.noreply.github.com> Co-authored-by: Bhavya RM Co-authored-by: Thomas Neirynck Co-authored-by: Brian Seeders Co-authored-by: Jiawei Wu <74562234+JiaweiWu@users.noreply.github.com> Co-authored-by: Clint Andrew Hall Co-authored-by: Christiane (Tina) Heiligers Co-authored-by: Alejandro Fernández Gómez Co-authored-by: Joe Reuter Co-authored-by: Nick Peihl Co-authored-by: Christos Nasikas --- x-pack/plugins/cases/common/api/cases/case.ts | 81 +++++++---- .../common/api/cases/user_actions/common.ts | 1 + .../api/cases/user_actions/create_case.ts | 1 + .../common/api/cases/user_actions/index.ts | 2 + .../common/api/cases/user_actions/severity.ts | 19 +++ .../plugins/cases/common/api/runtime_types.ts | 94 +++++++----- .../all_cases/all_cases_list.test.tsx | 3 +- .../components/user_actions/builder.tsx | 4 + .../plugins/cases/public/containers/mock.ts | 4 + .../cases/server/client/cases/create.ts | 5 +- .../plugins/cases/server/client/cases/mock.ts | 1 + .../plugins/cases/server/client/utils.test.ts | 71 --------- .../plugins/cases/server/common/utils.test.ts | 135 ++++++++++++++++++ x-pack/plugins/cases/server/common/utils.ts | 2 + .../api/__fixtures__/mock_saved_objects.ts | 5 + .../cases/server/saved_object_types/cases.ts | 3 + .../migrations/cases.test.ts | 44 +++++- .../saved_object_types/migrations/cases.ts | 12 +- .../saved_object_types/migrations/utils.ts | 9 +- .../cases/server/services/cases/index.test.ts | 2 + .../cases/server/services/test_utils.ts | 8 +- .../user_actions/builder_factory.test.ts | 36 +++++ .../services/user_actions/builder_factory.ts | 2 + .../user_actions/builders/severity.ts | 22 +++ .../services/user_actions/index.test.ts | 55 +++++++ .../server/services/user_actions/mocks.ts | 4 +- .../server/services/user_actions/types.ts | 4 + .../cases_api_integration/common/lib/mock.ts | 2 + .../tests/common/cases/import_export.ts | 6 + .../tests/common/cases/migrations.ts | 56 +++++--- .../tests/common/cases/patch_cases.ts | 45 ++++++ .../tests/common/cases/post_case.ts | 33 +++++ .../user_actions/get_all_user_actions.ts | 25 ++++ 33 files changed, 629 insertions(+), 167 deletions(-) create mode 100644 x-pack/plugins/cases/common/api/cases/user_actions/severity.ts create mode 100644 x-pack/plugins/cases/server/services/user_actions/builders/severity.ts diff --git a/x-pack/plugins/cases/common/api/cases/case.ts b/x-pack/plugins/cases/common/api/cases/case.ts index 3f42e5b5c875c..b3dbe4801f544 100644 --- a/x-pack/plugins/cases/common/api/cases/case.ts +++ b/x-pack/plugins/cases/common/api/cases/case.ts @@ -39,6 +39,20 @@ export const SettingsRt = rt.type({ syncAlerts: rt.boolean, }); +export enum CaseSeverity { + LOW = 'low', + MEDIUM = 'medium', + HIGH = 'high', + CRITICAL = 'critical', +} + +export const CaseSeverityRt = rt.union([ + rt.literal(CaseSeverity.LOW), + rt.literal(CaseSeverity.MEDIUM), + rt.literal(CaseSeverity.HIGH), + rt.literal(CaseSeverity.CRITICAL), +]); + const CaseBasicRt = rt.type({ /** * The description of the case @@ -68,6 +82,10 @@ const CaseBasicRt = rt.type({ * The plugin owner of the case */ owner: rt.string, + /** + * The severity of the case + */ + severity: CaseSeverityRt, }); /** @@ -106,33 +124,42 @@ export const CaseAttributesRt = rt.intersection([ }), ]); -export const CasePostRequestRt = rt.type({ - /** - * Description of the case - */ - description: rt.string, - /** - * Identifiers for the case. - */ - tags: rt.array(rt.string), - /** - * Title of the case - */ - title: rt.string, - /** - * The external configuration for the case - */ - connector: CaseConnectorRt, - /** - * Sync settings for alerts - */ - settings: SettingsRt, - /** - * The owner here must match the string used when a plugin registers a feature with access to the cases plugin. The user - * creating this case must also be granted access to that plugin's feature. - */ - owner: rt.string, -}); +export const CasePostRequestRt = rt.intersection([ + rt.type({ + /** + * Description of the case + */ + description: rt.string, + /** + * Identifiers for the case. + */ + tags: rt.array(rt.string), + /** + * Title of the case + */ + title: rt.string, + /** + * The external configuration for the case + */ + connector: CaseConnectorRt, + /** + * Sync settings for alerts + */ + settings: SettingsRt, + /** + * The owner here must match the string used when a plugin registers a feature with access to the cases plugin. The user + * creating this case must also be granted access to that plugin's feature. + */ + owner: rt.string, + }), + rt.partial({ + /** + * The severity of the case. The severity is + * default it to "low" if not provided. + */ + severity: CaseSeverityRt, + }), +]); export const CasesFindRequestRt = rt.partial({ /** diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/common.ts b/x-pack/plugins/cases/common/api/cases/user_actions/common.ts index a6d12d135c142..5665ab524071a 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/common.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/common.ts @@ -17,6 +17,7 @@ export const ActionTypes = { title: 'title', status: 'status', settings: 'settings', + severity: 'severity', create_case: 'create_case', delete_case: 'delete_case', } as const; diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts b/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts index c491cc519132f..53d2320b5afd4 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/create_case.ts @@ -23,6 +23,7 @@ export const CommonFieldsRt = rt.type({ const CommonPayloadAttributesRt = rt.type({ description: DescriptionUserActionPayloadRt.props.description, status: rt.string, + severity: rt.string, tags: TagsUserActionPayloadRt.props.tags, title: TitleUserActionPayloadRt.props.title, settings: SettingsUserActionPayloadRt.props.settings, diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/index.ts b/x-pack/plugins/cases/common/api/cases/user_actions/index.ts index 3f974d89fc79a..d19ee5fcbe9f8 100644 --- a/x-pack/plugins/cases/common/api/cases/user_actions/index.ts +++ b/x-pack/plugins/cases/common/api/cases/user_actions/index.ts @@ -23,6 +23,7 @@ import { TitleUserActionRt } from './title'; import { SettingsUserActionRt } from './settings'; import { StatusUserActionRt } from './status'; import { DeleteCaseUserActionRt } from './delete_case'; +import { SeverityUserActionRt } from './severity'; export * from './common'; export * from './comment'; @@ -43,6 +44,7 @@ const CommonUserActionsRt = rt.union([ TitleUserActionRt, SettingsUserActionRt, StatusUserActionRt, + SeverityUserActionRt, ]); export const UserActionsRt = rt.union([ diff --git a/x-pack/plugins/cases/common/api/cases/user_actions/severity.ts b/x-pack/plugins/cases/common/api/cases/user_actions/severity.ts new file mode 100644 index 0000000000000..2db5a0880dc09 --- /dev/null +++ b/x-pack/plugins/cases/common/api/cases/user_actions/severity.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as rt from 'io-ts'; +import { CaseSeverityRt } from '../case'; +import { ActionTypes, UserActionWithAttributes } from './common'; + +export const SeverityUserActionPayloadRt = rt.type({ severity: CaseSeverityRt }); + +export const SeverityUserActionRt = rt.type({ + type: rt.literal(ActionTypes.severity), + payload: SeverityUserActionPayloadRt, +}); + +export type SeverityUserAction = UserActionWithAttributes>; diff --git a/x-pack/plugins/cases/common/api/runtime_types.ts b/x-pack/plugins/cases/common/api/runtime_types.ts index c807d4b31b751..0a31479b29da8 100644 --- a/x-pack/plugins/cases/common/api/runtime_types.ts +++ b/x-pack/plugins/cases/common/api/runtime_types.ts @@ -9,42 +9,18 @@ import { either, fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import * as rt from 'io-ts'; -import { isObject } from 'lodash/fp'; +import { formatErrors } from '@kbn/securitysolution-io-ts-utils'; type ErrorFactory = (message: string) => Error; - -/** - * @deprecated Use packages/kbn-securitysolution-io-ts-utils/src/format_errors/index.ts - * Bug fix for the TODO is in the format_errors package - */ -export const formatErrors = (errors: rt.Errors): string[] => { - const err = errors.map((error) => { - if (error.message != null) { - return error.message; - } else { - const keyContext = error.context - .filter( - (entry) => entry.key != null && !Number.isInteger(+entry.key) && entry.key.trim() !== '' - ) - .map((entry) => entry.key) - .join(','); - - const nameContext = error.context.find((entry) => { - // TODO: Put in fix for optional chaining https://github.com/cypress-io/cypress/issues/9298 - if (entry.type && entry.type.name) { - return entry.type.name.length > 0; - } - return false; - }); - const suppliedValue = - keyContext !== '' ? keyContext : nameContext != null ? nameContext.type.name : ''; - const value = isObject(error.value) ? JSON.stringify(error.value) : error.value; - return `Invalid value "${value}" supplied to "${suppliedValue}"`; - } - }); - - return [...new Set(err)]; -}; +export type GenericIntersectionC = + // eslint-disable-next-line @typescript-eslint/no-explicit-any + | rt.IntersectionC<[any, any]> + // eslint-disable-next-line @typescript-eslint/no-explicit-any + | rt.IntersectionC<[any, any, any]> + // eslint-disable-next-line @typescript-eslint/no-explicit-any + | rt.IntersectionC<[any, any, any, any]> + // eslint-disable-next-line @typescript-eslint/no-explicit-any + | rt.IntersectionC<[any, any, any, any, any]>; export const createPlainError = (message: string) => new Error(message); @@ -57,6 +33,40 @@ export const decodeOrThrow = (inputValue: I) => pipe(runtimeType.decode(inputValue), fold(throwErrors(createError), identity)); +const getProps = ( + codec: + | rt.HasProps + // eslint-disable-next-line @typescript-eslint/no-explicit-any + | rt.RecordC + | GenericIntersectionC +): rt.Props | null => { + if (codec == null) { + return null; + } + switch (codec._tag) { + case 'DictionaryType': + if (codec.codomain.props != null) { + return codec.codomain.props; + } + const dTypes: rt.HasProps[] = codec.codomain.types; + return dTypes.reduce((props, type) => Object.assign(props, getProps(type)), {}); + case 'RefinementType': + case 'ReadonlyType': + return getProps(codec.type); + case 'InterfaceType': + case 'StrictType': + case 'PartialType': + return codec.props; + case 'IntersectionType': + const iTypes = codec.types as rt.HasProps[]; + return iTypes.reduce((props, type) => { + return Object.assign(props, getProps(type) as rt.Props); + }, {} as rt.Props) as rt.Props; + default: + return null; + } +}; + const getExcessProps = (props: rt.Props, r: Record): string[] => { const ex: string[] = []; for (const k of Object.keys(r)) { @@ -67,15 +77,21 @@ const getExcessProps = (props: rt.Props, r: Record): string[] = return ex; }; -export function excess | rt.PartialType>( - codec: C -): C { +export function excess< + C extends rt.InterfaceType | GenericIntersectionC | rt.PartialType +>(codec: C): C { + const codecProps = getProps(codec); + const r = new rt.InterfaceType( codec.name, codec.is, (i, c) => either.chain(rt.UnknownRecord.validate(i, c), (s: Record) => { - const ex = getExcessProps(codec.props, s); + if (codecProps == null) { + return rt.failure(i, c, 'unknown codec'); + } + + const ex = getExcessProps(codecProps, s); return ex.length > 0 ? rt.failure( i, @@ -87,7 +103,7 @@ export function excess | rt.PartialType { username: 'lknope', }, description: 'Security banana Issue', + severity: CaseSeverity.LOW, duration: null, externalService: { connectorId: '123', diff --git a/x-pack/plugins/cases/public/components/user_actions/builder.tsx b/x-pack/plugins/cases/public/components/user_actions/builder.tsx index 5e1c11fbdd2df..019e37396a7ce 100644 --- a/x-pack/plugins/cases/public/components/user_actions/builder.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/builder.tsx @@ -20,6 +20,10 @@ export const builderMap: UserActionBuilderMap = { tags: createTagsUserActionBuilder, title: createTitleUserActionBuilder, status: createStatusUserActionBuilder, + // TODO: Build severity user action + severity: () => ({ + build: () => [], + }), pushed: createPushedUserActionBuilder, comment: createCommentUserActionBuilder, description: createDescriptionUserActionBuilder, diff --git a/x-pack/plugins/cases/public/containers/mock.ts b/x-pack/plugins/cases/public/containers/mock.ts index 8a31d8cac2b1e..ed9e9ebd1ff8f 100644 --- a/x-pack/plugins/cases/public/containers/mock.ts +++ b/x-pack/plugins/cases/public/containers/mock.ts @@ -31,6 +31,7 @@ import { UserActionTypes, UserActionWithResponse, CommentUserAction, + CaseSeverity, } from '../../common/api'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { UseGetCasesState, DEFAULT_FILTER_OPTIONS, DEFAULT_QUERY_PARAMS } from './use_get_cases'; @@ -154,6 +155,7 @@ export const basicCase: Case = { fields: null, }, description: 'Security banana Issue', + severity: CaseSeverity.LOW, duration: null, externalService: null, status: CaseStatuses.open, @@ -247,6 +249,7 @@ export const mockCase: Case = { fields: null, }, duration: null, + severity: CaseSeverity.LOW, description: 'Security banana Issue', externalService: null, status: CaseStatuses.open, @@ -512,6 +515,7 @@ export const getUserAction = ( description: 'a desc', connector: { ...getJiraConnector() }, status: CaseStatuses.open, + severity: CaseSeverity.LOW, title: 'a title', tags: ['a tag'], settings: { syncAlerts: true }, diff --git a/x-pack/plugins/cases/server/client/cases/create.ts b/x-pack/plugins/cases/server/client/cases/create.ts index ab9f6a4305800..714c8199d11a5 100644 --- a/x-pack/plugins/cases/server/client/cases/create.ts +++ b/x-pack/plugins/cases/server/client/cases/create.ts @@ -14,12 +14,13 @@ import { SavedObjectsUtils } from '@kbn/core/server'; import { throwErrors, - excess, CaseResponseRt, CaseResponse, CasePostRequest, ActionTypes, CasePostRequestRt, + excess, + CaseSeverity, } from '../../../common/api'; import { MAX_TITLE_LENGTH } from '../../../common/constants'; import { isInvalidTag } from '../../../common/utils/validators'; @@ -85,7 +86,7 @@ export const create = async ( unsecuredSavedObjectsClient, caseId: newCase.id, user, - payload: query, + payload: { ...query, severity: query.severity ?? CaseSeverity.LOW }, owner: newCase.attributes.owner, }); diff --git a/x-pack/plugins/cases/server/client/cases/mock.ts b/x-pack/plugins/cases/server/client/cases/mock.ts index 69a5f2d3a587b..4c0698b209bef 100644 --- a/x-pack/plugins/cases/server/client/cases/mock.ts +++ b/x-pack/plugins/cases/server/client/cases/mock.ts @@ -240,6 +240,7 @@ export const userActions: CaseUserActionsResponse = [ }, settings: { syncAlerts: true }, status: 'open', + severity: 'low', owner: SECURITY_SOLUTION_OWNER, }, action_id: 'fd830c60-6646-11eb-a291-51bf6b175a53', diff --git a/x-pack/plugins/cases/server/client/utils.test.ts b/x-pack/plugins/cases/server/client/utils.test.ts index 24e1135020a88..88140658c2b2b 100644 --- a/x-pack/plugins/cases/server/client/utils.test.ts +++ b/x-pack/plugins/cases/server/client/utils.test.ts @@ -5,9 +5,6 @@ * 2.0. */ -import { CaseConnector, ConnectorTypes } from '../../common/api'; -import { newCase } from '../routes/api/__mocks__/request_responses'; -import { transformNewCase } from '../common/utils'; import { buildRangeFilter, sortToSnake } from './utils'; import { toElasticsearchQuery } from '@kbn/es-query'; @@ -38,74 +35,6 @@ describe('utils', () => { }); }); - describe('transformNewCase', () => { - beforeAll(() => { - jest.useFakeTimers('modern'); - jest.setSystemTime(new Date('2020-04-09T09:43:51.778Z')); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - - const connector: CaseConnector = { - id: '123', - name: 'My connector', - type: ConnectorTypes.jira, - fields: { issueType: 'Task', priority: 'High', parent: null }, - }; - it('transform correctly', () => { - const myCase = { - newCase: { ...newCase, connector }, - user: { - email: 'elastic@elastic.co', - full_name: 'Elastic', - username: 'elastic', - }, - }; - - const res = transformNewCase(myCase); - - expect(res).toMatchInlineSnapshot(` - Object { - "closed_at": null, - "closed_by": null, - "connector": Object { - "fields": Object { - "issueType": "Task", - "parent": null, - "priority": "High", - }, - "id": "123", - "name": "My connector", - "type": ".jira", - }, - "created_at": "2020-04-09T09:43:51.778Z", - "created_by": Object { - "email": "elastic@elastic.co", - "full_name": "Elastic", - "username": "elastic", - }, - "description": "A description", - "duration": null, - "external_service": null, - "owner": "securitySolution", - "settings": Object { - "syncAlerts": true, - }, - "status": "open", - "tags": Array [ - "new", - "case", - ], - "title": "My new case", - "updated_at": null, - "updated_by": null, - } - `); - }); - }); - describe('buildRangeFilter', () => { it('returns undefined if both the from and or are undefined', () => { const node = buildRangeFilter({}); diff --git a/x-pack/plugins/cases/server/common/utils.test.ts b/x-pack/plugins/cases/server/common/utils.test.ts index 974c36bd0d8a6..918a48863cac0 100644 --- a/x-pack/plugins/cases/server/common/utils.test.ts +++ b/x-pack/plugins/cases/server/common/utils.test.ts @@ -9,11 +9,14 @@ import { SavedObject, SavedObjectsFindResponse } from '@kbn/core/server'; import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory'; import { SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { + CaseConnector, CaseResponse, + CaseSeverity, CommentAttributes, CommentRequest, CommentRequestUserType, CommentType, + ConnectorTypes, } from '../../common/api'; import { mockCaseComments, mockCases } from '../routes/api/__fixtures__/mock_saved_objects'; import { @@ -29,7 +32,9 @@ import { extractLensReferencesFromCommentString, getOrUpdateLensReferences, asArray, + transformNewCase, } from './utils'; +import { newCase } from '../routes/api/__mocks__/request_responses'; interface CommentReference { ids: string[]; @@ -67,6 +72,128 @@ function createCommentFindResponse( } describe('common utils', () => { + describe('transformNewCase', () => { + beforeAll(() => { + jest.useFakeTimers('modern'); + jest.setSystemTime(new Date('2020-04-09T09:43:51.778Z')); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + const connector: CaseConnector = { + id: '123', + name: 'My connector', + type: ConnectorTypes.jira, + fields: { issueType: 'Task', priority: 'High', parent: null }, + }; + + it('transform correctly', () => { + const myCase = { + newCase: { ...newCase, connector }, + user: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + }; + + const res = transformNewCase(myCase); + + expect(res).toMatchInlineSnapshot(` + Object { + "closed_at": null, + "closed_by": null, + "connector": Object { + "fields": Object { + "issueType": "Task", + "parent": null, + "priority": "High", + }, + "id": "123", + "name": "My connector", + "type": ".jira", + }, + "created_at": "2020-04-09T09:43:51.778Z", + "created_by": Object { + "email": "elastic@elastic.co", + "full_name": "Elastic", + "username": "elastic", + }, + "description": "A description", + "duration": null, + "external_service": null, + "owner": "securitySolution", + "settings": Object { + "syncAlerts": true, + }, + "severity": "low", + "status": "open", + "tags": Array [ + "new", + "case", + ], + "title": "My new case", + "updated_at": null, + "updated_by": null, + } + `); + }); + + it('transform correctly with severity provided', () => { + const myCase = { + newCase: { ...newCase, connector, severity: CaseSeverity.MEDIUM }, + user: { + email: 'elastic@elastic.co', + full_name: 'Elastic', + username: 'elastic', + }, + }; + + const res = transformNewCase(myCase); + + expect(res).toMatchInlineSnapshot(` + Object { + "closed_at": null, + "closed_by": null, + "connector": Object { + "fields": Object { + "issueType": "Task", + "parent": null, + "priority": "High", + }, + "id": "123", + "name": "My connector", + "type": ".jira", + }, + "created_at": "2020-04-09T09:43:51.778Z", + "created_by": Object { + "email": "elastic@elastic.co", + "full_name": "Elastic", + "username": "elastic", + }, + "description": "A description", + "duration": null, + "external_service": null, + "owner": "securitySolution", + "settings": Object { + "syncAlerts": true, + }, + "severity": "medium", + "status": "open", + "tags": Array [ + "new", + "case", + ], + "title": "My new case", + "updated_at": null, + "updated_by": null, + } + `); + }); + }); + describe('transformCases', () => { it('transforms correctly', () => { const casesMap = new Map( @@ -110,6 +237,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "defacement", @@ -149,6 +277,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "Data Destruction", @@ -192,6 +321,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "LOLBins", @@ -239,6 +369,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "closed", "tags": Array [ "LOLBins", @@ -303,6 +434,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "LOLBins", @@ -358,6 +490,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "LOLBins", @@ -436,6 +569,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "LOLBins", @@ -489,6 +623,7 @@ describe('common utils', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "defacement", diff --git a/x-pack/plugins/cases/server/common/utils.ts b/x-pack/plugins/cases/server/common/utils.ts index 11e77c5eb4579..bc8dbf8a6e842 100644 --- a/x-pack/plugins/cases/server/common/utils.ts +++ b/x-pack/plugins/cases/server/common/utils.ts @@ -19,6 +19,7 @@ import { CaseAttributes, CasePostRequest, CaseResponse, + CaseSeverity, CasesFindResponse, CaseStatuses, CommentAttributes, @@ -56,6 +57,7 @@ export const transformNewCase = ({ }): CaseAttributes => ({ ...newCase, duration: null, + severity: newCase.severity ?? CaseSeverity.LOW, closed_at: null, closed_by: null, created_at: new Date().toISOString(), diff --git a/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts b/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts index cc45ef0e2d069..77e1a64012c6d 100644 --- a/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts +++ b/x-pack/plugins/cases/server/routes/api/__fixtures__/mock_saved_objects.ts @@ -8,6 +8,7 @@ import { SavedObject } from '@kbn/core/server'; import { CaseAttributes, + CaseSeverity, CaseStatuses, CommentAttributes, CommentType, @@ -34,6 +35,7 @@ export const mockCases: Array> = [ email: 'testemail@elastic.co', username: 'elastic', }, + severity: CaseSeverity.LOW, duration: null, description: 'This is a brand new case of a bad meanie defacing data', external_service: null, @@ -73,6 +75,7 @@ export const mockCases: Array> = [ email: 'testemail@elastic.co', username: 'elastic', }, + severity: CaseSeverity.LOW, duration: null, description: 'Oh no, a bad meanie destroying data!', external_service: null, @@ -112,6 +115,7 @@ export const mockCases: Array> = [ email: 'testemail@elastic.co', username: 'elastic', }, + severity: CaseSeverity.LOW, duration: null, description: 'Oh no, a bad meanie going LOLBins all over the place!', external_service: null, @@ -155,6 +159,7 @@ export const mockCases: Array> = [ email: 'testemail@elastic.co', username: 'elastic', }, + severity: CaseSeverity.LOW, duration: null, description: 'Oh no, a bad meanie going LOLBins all over the place!', external_service: null, diff --git a/x-pack/plugins/cases/server/saved_object_types/cases.ts b/x-pack/plugins/cases/server/saved_object_types/cases.ts index ea68fc24f60ca..9b2ea975c4dcd 100644 --- a/x-pack/plugins/cases/server/saved_object_types/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/cases.ts @@ -152,6 +152,9 @@ export const createCaseSavedObjectType = ( }, }, }, + severity: { + type: 'keyword', + }, }, }, migrations: caseMigrations, diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts index 70e0e91caa57f..b4d3421643a41 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.test.ts @@ -9,13 +9,14 @@ import { SavedObjectSanitizedDoc } from '@kbn/core/server'; import { CaseAttributes, CaseFullExternalService, + CaseSeverity, ConnectorTypes, NONE_CONNECTOR_ID, } from '../../../common/api'; import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { getNoneCaseConnector } from '../../common/utils'; import { createExternalService, ESCaseConnectorWithId } from '../../services/test_utils'; -import { addDuration, caseConnectorIdMigration, removeCaseType } from './cases'; +import { addDuration, addSeverity, caseConnectorIdMigration, removeCaseType } from './cases'; // eslint-disable-next-line @typescript-eslint/naming-convention const create_7_14_0_case = ({ @@ -496,4 +497,45 @@ describe('case migrations', () => { }); }); }); + + describe('add severity', () => { + it('adds the severity correctly when none is present', () => { + const doc = { + id: '123', + attributes: { + created_at: '2021-11-23T19:00:00Z', + closed_at: '2021-11-23T19:02:00Z', + }, + type: 'abc', + references: [], + } as unknown as SavedObjectSanitizedDoc; + expect(addSeverity(doc)).toEqual({ + ...doc, + attributes: { + ...doc.attributes, + severity: CaseSeverity.LOW, + }, + }); + }); + + it('keeps the existing value if the field already exists', () => { + const doc = { + id: '123', + attributes: { + severity: CaseSeverity.CRITICAL, + created_at: '2021-11-23T19:00:00Z', + closed_at: '2021-11-23T19:02:00Z', + }, + type: 'abc', + references: [], + } as unknown as SavedObjectSanitizedDoc; + expect(addSeverity(doc)).toEqual({ + ...doc, + attributes: { + ...doc.attributes, + severity: CaseSeverity.CRITICAL, + }, + }); + }); + }); }); diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts index 91a462c5c8053..c4961f742abc7 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/cases.ts @@ -11,7 +11,7 @@ import { cloneDeep, unset } from 'lodash'; import { SavedObjectUnsanitizedDoc, SavedObjectSanitizedDoc } from '@kbn/core/server'; import { addOwnerToSO, SanitizedCaseOwner } from '.'; import { ESConnectorFields } from '../../services'; -import { CaseAttributes, ConnectorTypes } from '../../../common/api'; +import { CaseAttributes, CaseSeverity, ConnectorTypes } from '../../../common/api'; import { CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME, @@ -21,6 +21,7 @@ import { transformPushConnectorIdToReference, } from './user_actions/connector_id'; import { CASE_TYPE_INDIVIDUAL } from './constants'; +import { pipeMigrations } from './utils'; interface UnsanitizedCaseConnector { connector_id: string; @@ -114,6 +115,13 @@ export const addDuration = ( return { ...doc, attributes: { ...doc.attributes, duration }, references: doc.references ?? [] }; }; +export const addSeverity = ( + doc: SavedObjectUnsanitizedDoc +): SavedObjectSanitizedDoc => { + const severity = doc.attributes.severity ?? CaseSeverity.LOW; + return { ...doc, attributes: { ...doc.attributes, severity }, references: doc.references ?? [] }; +}; + export const caseMigrations = { '7.10.0': ( doc: SavedObjectUnsanitizedDoc @@ -175,5 +183,5 @@ export const caseMigrations = { }, '7.15.0': caseConnectorIdMigration, '8.1.0': removeCaseType, - '8.3.0': addDuration, + '8.3.0': pipeMigrations(addDuration, addSeverity), }; diff --git a/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts b/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts index 65c1d42271845..8996f89155949 100644 --- a/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts +++ b/x-pack/plugins/cases/server/saved_object_types/migrations/utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { LogMeta, SavedObjectMigrationContext } from '@kbn/core/server'; +import { LogMeta, SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server'; interface MigrationLogMeta extends LogMeta { migrations: { @@ -39,3 +39,10 @@ export function logError({ } ); } + +type CaseMigration = (doc: SavedObjectUnsanitizedDoc) => SavedObjectUnsanitizedDoc; + +export function pipeMigrations(...migrations: Array>): CaseMigration { + return (doc: SavedObjectUnsanitizedDoc) => + migrations.reduce((migratedDoc, nextMigration) => nextMigration(migratedDoc), doc); +} diff --git a/x-pack/plugins/cases/server/services/cases/index.test.ts b/x-pack/plugins/cases/server/services/cases/index.test.ts index 84c580c8800e3..826a8d06e97f2 100644 --- a/x-pack/plugins/cases/server/services/cases/index.test.ts +++ b/x-pack/plugins/cases/server/services/cases/index.test.ts @@ -166,6 +166,7 @@ describe('CasesService', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "defacement", @@ -519,6 +520,7 @@ describe('CasesService', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "defacement", diff --git a/x-pack/plugins/cases/server/services/test_utils.ts b/x-pack/plugins/cases/server/services/test_utils.ts index 617dedd368ab3..ff86783ae8e9c 100644 --- a/x-pack/plugins/cases/server/services/test_utils.ts +++ b/x-pack/plugins/cases/server/services/test_utils.ts @@ -10,15 +10,18 @@ import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; import { ESConnectorFields } from '.'; import { CONNECTOR_ID_REFERENCE_NAME, PUSH_CONNECTOR_ID_REFERENCE_NAME } from '../common/constants'; import { + CaseAttributes, CaseConnector, CaseExternalServiceBasic, CaseFullExternalService, + CaseSeverity, CaseStatuses, ConnectorTypes, NONE_CONNECTOR_ID, } from '../../common/api'; import { CASE_SAVED_OBJECT, SECURITY_SOLUTION_OWNER } from '../../common/constants'; import { ESCaseAttributes, ExternalServicesWithoutConnectorId } from './cases/types'; +import { getNoneCaseConnector } from '../common/utils'; /** * This is only a utility interface to help with constructing test cases. After the migration, the ES format will no longer @@ -96,7 +99,7 @@ export const createExternalService = ( ...overrides, }); -export const basicCaseFields = { +export const basicCaseFields: CaseAttributes = { closed_at: null, closed_by: null, created_at: '2019-11-25T21:54:48.952Z', @@ -105,6 +108,7 @@ export const basicCaseFields = { email: 'testemail@elastic.co', username: 'elastic', }, + severity: CaseSeverity.LOW, duration: null, description: 'This is a brand new case of a bad meanie defacing data', title: 'Super Bad Security Issue', @@ -116,6 +120,8 @@ export const basicCaseFields = { email: 'testemail@elastic.co', username: 'elastic', }, + connector: getNoneCaseConnector(), + external_service: null, settings: { syncAlerts: true, }, diff --git a/x-pack/plugins/cases/server/services/user_actions/builder_factory.test.ts b/x-pack/plugins/cases/server/services/user_actions/builder_factory.test.ts index 2e2a9e905bb7e..ab349d690edef 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builder_factory.test.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builder_factory.test.ts @@ -9,6 +9,7 @@ import { SECURITY_SOLUTION_OWNER } from '../../../common'; import { Actions, ActionTypes, + CaseSeverity, CaseStatuses, CommentType, ConnectorTypes, @@ -340,6 +341,40 @@ describe('UserActionBuilder', () => { `); }); + it('builds a severity user action correctly', () => { + const builder = builderFactory.getBuilder(ActionTypes.severity)!; + const userAction = builder.build({ + payload: { severity: CaseSeverity.LOW }, + ...commonArgs, + }); + + expect(userAction).toMatchInlineSnapshot(` + Object { + "attributes": Object { + "action": "update", + "created_at": "2022-01-09T22:00:00.000Z", + "created_by": Object { + "email": "elastic@elastic.co", + "full_name": "Elastic User", + "username": "elastic", + }, + "owner": "securitySolution", + "payload": Object { + "severity": "low", + }, + "type": "severity", + }, + "references": Array [ + Object { + "id": "123", + "name": "associated-cases", + "type": "cases", + }, + ], + } + `); + }); + it('builds a settings user action correctly', () => { const builder = builderFactory.getBuilder(ActionTypes.settings)!; const userAction = builder.build({ @@ -413,6 +448,7 @@ describe('UserActionBuilder', () => { "settings": Object { "syncAlerts": true, }, + "severity": "low", "status": "open", "tags": Array [ "sir", diff --git a/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts b/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts index 5d5f33c2ae4f5..510b6d12b1fa1 100644 --- a/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts +++ b/x-pack/plugins/cases/server/services/user_actions/builder_factory.ts @@ -17,6 +17,7 @@ import { TagsUserActionBuilder } from './builders/tags'; import { SettingsUserActionBuilder } from './builders/settings'; import { DeleteCaseUserActionBuilder } from './builders/delete_case'; import { UserActionBuilder } from './abstract_builder'; +import { SeverityUserActionBuilder } from './builders/severity'; const builderMap = { title: TitleUserActionBuilder, @@ -27,6 +28,7 @@ const builderMap = { pushed: PushedUserActionBuilder, tags: TagsUserActionBuilder, status: StatusUserActionBuilder, + severity: SeverityUserActionBuilder, settings: SettingsUserActionBuilder, delete_case: DeleteCaseUserActionBuilder, }; diff --git a/x-pack/plugins/cases/server/services/user_actions/builders/severity.ts b/x-pack/plugins/cases/server/services/user_actions/builders/severity.ts new file mode 100644 index 0000000000000..4abd5856972b4 --- /dev/null +++ b/x-pack/plugins/cases/server/services/user_actions/builders/severity.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Actions, ActionTypes } from '../../../../common/api'; +import { UserActionBuilder } from '../abstract_builder'; +import { UserActionParameters, BuilderReturnValue } from '../types'; + +export class SeverityUserActionBuilder extends UserActionBuilder { + build(args: UserActionParameters<'severity'>): BuilderReturnValue { + return this.buildCommonUserAction({ + ...args, + action: Actions.update, + valueKey: 'severity', + value: args.payload.severity, + type: ActionTypes.severity, + }); + } +} diff --git a/x-pack/plugins/cases/server/services/user_actions/index.test.ts b/x-pack/plugins/cases/server/services/user_actions/index.test.ts index eb1b57622d24d..44e91bcae09d3 100644 --- a/x-pack/plugins/cases/server/services/user_actions/index.test.ts +++ b/x-pack/plugins/cases/server/services/user_actions/index.test.ts @@ -13,6 +13,7 @@ import { ACTION_SAVED_OBJECT_TYPE } from '@kbn/actions-plugin/server'; import { Actions, ActionTypes, + CaseSeverity, CaseStatuses, CaseUserActionAttributes, ConnectorUserAction, @@ -107,6 +108,7 @@ const createCaseUserAction = (): SavedObject => { description: 'a desc', settings: { syncAlerts: false }, status: CaseStatuses.open, + severity: CaseSeverity.LOW, tags: [], owner: SECURITY_SOLUTION_OWNER, }, @@ -447,6 +449,7 @@ describe('CaseUserActionService', () => { payload: casePayload, type: ActionTypes.create_case, }); + expect(unsecuredSavedObjectsClient.create).toHaveBeenCalledWith( 'cases-user-actions', { @@ -477,6 +480,7 @@ describe('CaseUserActionService', () => { owner: 'securitySolution', settings: { syncAlerts: true }, status: 'open', + severity: 'low', tags: ['sir'], title: 'Case SIR', }, @@ -517,6 +521,33 @@ describe('CaseUserActionService', () => { }); }); + describe('severity', () => { + it('creates an update severity user action', async () => { + await service.createUserAction({ + ...commonArgs, + payload: { severity: CaseSeverity.MEDIUM }, + type: ActionTypes.severity, + }); + + expect(unsecuredSavedObjectsClient.create).toHaveBeenCalledWith( + 'cases-user-actions', + { + action: Actions.update, + created_at: '2022-01-09T22:00:00.000Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic User', + username: 'elastic', + }, + type: 'severity', + owner: 'securitySolution', + payload: { severity: 'medium' }, + }, + { references: [{ id: '123', name: 'associated-cases', type: 'cases' }] } + ); + }); + }); + describe('push', () => { it('creates a push user action', async () => { await service.createUserAction({ @@ -801,6 +832,30 @@ describe('CaseUserActionService', () => { references: [{ id: '2', name: 'associated-cases', type: 'cases' }], type: 'cases-user-actions', }, + { + attributes: { + action: 'update', + created_at: '2022-01-09T22:00:00.000Z', + created_by: { + email: 'elastic@elastic.co', + full_name: 'Elastic User', + username: 'elastic', + }, + owner: 'securitySolution', + payload: { + severity: 'critical', + }, + type: 'severity', + }, + references: [ + { + id: '2', + name: 'associated-cases', + type: 'cases', + }, + ], + type: 'cases-user-actions', + }, ]); }); }); diff --git a/x-pack/plugins/cases/server/services/user_actions/mocks.ts b/x-pack/plugins/cases/server/services/user_actions/mocks.ts index c745c040ac2ce..bc35f98bf926e 100644 --- a/x-pack/plugins/cases/server/services/user_actions/mocks.ts +++ b/x-pack/plugins/cases/server/services/user_actions/mocks.ts @@ -7,7 +7,7 @@ import { CASE_SAVED_OBJECT } from '../../../common/constants'; import { SECURITY_SOLUTION_OWNER } from '../../../common'; -import { CaseStatuses, CommentType, ConnectorTypes } from '../../../common/api'; +import { CaseSeverity, CaseStatuses, CommentType, ConnectorTypes } from '../../../common/api'; import { createCaseSavedObjectResponse } from '../test_utils'; import { transformSavedObjectToExternalModel } from '../cases/transform'; @@ -30,6 +30,7 @@ export const casePayload = { }, }, settings: { syncAlerts: true }, + severity: CaseSeverity.LOW, owner: SECURITY_SOLUTION_OWNER, }; @@ -69,6 +70,7 @@ export const updatedCases = [ description: 'updated desc', tags: ['one', 'two'], settings: { syncAlerts: false }, + severity: CaseSeverity.CRITICAL, }, references: [], }, diff --git a/x-pack/plugins/cases/server/services/user_actions/types.ts b/x-pack/plugins/cases/server/services/user_actions/types.ts index f681a9186181c..a60dee552a6be 100644 --- a/x-pack/plugins/cases/server/services/user_actions/types.ts +++ b/x-pack/plugins/cases/server/services/user_actions/types.ts @@ -9,6 +9,7 @@ import { SavedObjectReference } from '@kbn/core/server'; import { CasePostRequest, CaseSettings, + CaseSeverity, CaseStatuses, CommentUserAction, ConnectorUserAction, @@ -28,6 +29,9 @@ export interface BuilderParameters { status: { parameters: { payload: { status: CaseStatuses } }; }; + severity: { + parameters: { payload: { severity: CaseSeverity } }; + }; tags: { parameters: { payload: { tags: string[] } }; }; diff --git a/x-pack/test/cases_api_integration/common/lib/mock.ts b/x-pack/test/cases_api_integration/common/lib/mock.ts index 34f1d4a9273d2..08f30f8df024e 100644 --- a/x-pack/test/cases_api_integration/common/lib/mock.ts +++ b/x-pack/test/cases_api_integration/common/lib/mock.ts @@ -17,6 +17,7 @@ import { CaseStatuses, CommentRequest, CommentRequestActionsType, + CaseSeverity, } from '@kbn/cases-plugin/common/api'; export const defaultUser = { email: null, full_name: null, username: 'elastic' }; @@ -86,6 +87,7 @@ export const postCaseResp = ( ...(id != null ? { id } : {}), comments: [], duration: null, + severity: req.severity ?? CaseSeverity.LOW, totalAlerts: 0, totalComment: 0, closed_by: null, diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts index 44da07a845ff7..2ce441c37e687 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts @@ -27,6 +27,7 @@ import { CommentUserAction, CreateCaseUserAction, CaseStatuses, + CaseSeverity, } from '@kbn/cases-plugin/common/api'; import { ObjectRemover as ActionsRemover } from '../../../../../alerting_api_integration/common/lib'; import { @@ -204,6 +205,10 @@ const expectExportToHaveCaseSavedObject = ( expect(createdCaseSO.attributes.connector.name).to.eql(caseRequest.connector.name); expect(createdCaseSO.attributes.connector.fields).to.eql([]); expect(createdCaseSO.attributes.settings).to.eql(caseRequest.settings); + expect(createdCaseSO.attributes.status).to.eql(CaseStatuses.open); + expect(createdCaseSO.attributes.severity).to.eql(CaseSeverity.LOW); + expect(createdCaseSO.attributes.duration).to.eql(null); + expect(createdCaseSO.attributes.tags).to.eql(caseRequest.tags); }; const expectExportToHaveUserActions = (objects: SavedObject[], caseRequest: CasePostRequest) => { @@ -239,6 +244,7 @@ const expectCaseCreateUserAction = ( expect(restParsedCreateCase).to.eql({ ...restCreateCase, status: CaseStatuses.open, + severity: CaseSeverity.LOW, }); expect(restParsedConnector).to.eql(restConnector); }; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/migrations.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/migrations.ts index 3c43ac1932986..4d4b9d45b6717 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/migrations.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/migrations.ts @@ -369,7 +369,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); }); - describe('8.3.0 adding duration', () => { + describe('8.3.0', () => { before(async () => { await kibanaServer.importExport.load( 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.2.0/cases_duration.json' @@ -383,34 +383,48 @@ export default function createGetTests({ getService }: FtrProviderContext) { await deleteAllCaseItems(es); }); - it('calculates the correct duration for closed cases', async () => { - const caseInfo = await getCase({ - supertest, - caseId: '4537b380-a512-11ec-b92f-859b9e89e434', + describe('adding duration', () => { + it('calculates the correct duration for closed cases', async () => { + const caseInfo = await getCase({ + supertest, + caseId: '4537b380-a512-11ec-b92f-859b9e89e434', + }); + + expect(caseInfo).to.have.property('duration'); + expect(caseInfo.duration).to.be(120); }); - expect(caseInfo).to.have.property('duration'); - expect(caseInfo.duration).to.be(120); - }); + it('sets the duration to null to open cases', async () => { + const caseInfo = await getCase({ + supertest, + caseId: '7537b580-a512-11ec-b94f-85979e89e434', + }); - it('sets the duration to null to open cases', async () => { - const caseInfo = await getCase({ - supertest, - caseId: '7537b580-a512-11ec-b94f-85979e89e434', + expect(caseInfo).to.have.property('duration'); + expect(caseInfo.duration).to.be(null); }); - expect(caseInfo).to.have.property('duration'); - expect(caseInfo.duration).to.be(null); - }); + it('sets the duration to null to in-progress cases', async () => { + const caseInfo = await getCase({ + supertest, + caseId: '1537b580-a512-11ec-b94f-85979e89e434', + }); - it('sets the duration to null to in-progress cases', async () => { - const caseInfo = await getCase({ - supertest, - caseId: '1537b580-a512-11ec-b94f-85979e89e434', + expect(caseInfo).to.have.property('duration'); + expect(caseInfo.duration).to.be(null); }); + }); - expect(caseInfo).to.have.property('duration'); - expect(caseInfo.duration).to.be(null); + describe('add severity', () => { + it('adds the severity field for existing documents', async () => { + const caseInfo = await getCase({ + supertest, + caseId: '4537b380-a512-11ec-b92f-859b9e89e434', + }); + + expect(caseInfo).to.have.property('severity'); + expect(caseInfo.severity).to.be('low'); + }); }); }); }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts index 9ef1c3d5655e4..80dffef7cd3ee 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts @@ -10,6 +10,7 @@ import { ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '@kbn/security-solution-plugin/common/constants'; import { + CaseSeverity, CasesResponse, CaseStatuses, CommentType, @@ -170,6 +171,34 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('should patch the severity of a case correctly', async () => { + const postedCase = await createCase(supertest, postCaseReq); + + // the default severity + expect(postedCase.severity).equal(CaseSeverity.LOW); + + const patchedCases = await updateCase({ + supertest, + params: { + cases: [ + { + id: postedCase.id, + version: postedCase.version, + severity: CaseSeverity.MEDIUM, + }, + ], + }, + }); + + const data = removeServerGeneratedPropertiesFromCase(patchedCases[0]); + + expect(data).to.eql({ + ...postCaseResp(), + severity: CaseSeverity.MEDIUM, + updated_by: defaultUser, + }); + }); + it('should patch a case with new connector', async () => { const postedCase = await createCase(supertest, postCaseReq); const patchedCases = await updateCase({ @@ -297,6 +326,22 @@ export default ({ getService }: FtrProviderContext): void => { }); }); + it('400s when a wrong severity value is passed', async () => { + await updateCase({ + supertest, + params: { + cases: [ + { + version: 'version', + // @ts-expect-error + severity: 'wont-do', + }, + ], + }, + expectedHttpCode: 400, + }); + }); + it('400s when id is missing', async () => { await updateCase({ supertest, diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts index 9cd986a032b24..d4b52ff6f3394 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts @@ -12,6 +12,7 @@ import { ConnectorTypes, ConnectorJiraTypeFields, CaseStatuses, + CaseSeverity, } from '@kbn/cases-plugin/common/api'; import { getPostCaseRequest, postCaseResp, defaultUser } from '../../../../common/lib/mock'; import { @@ -102,6 +103,32 @@ export default ({ getService }: FtrProviderContext): void => { ); }); + it('should post a case without severity', async () => { + const postedCase = await createCase(supertest, getPostCaseRequest()); + const data = removeServerGeneratedPropertiesFromCase(postedCase); + + expect(data).to.eql(postCaseResp(null, getPostCaseRequest())); + }); + + it('should post a case with severity', async () => { + const postedCase = await createCase( + supertest, + getPostCaseRequest({ + severity: CaseSeverity.HIGH, + }) + ); + const data = removeServerGeneratedPropertiesFromCase(postedCase); + + expect(data).to.eql( + postCaseResp( + null, + getPostCaseRequest({ + severity: CaseSeverity.HIGH, + }) + ) + ); + }); + it('should create a user action when creating a case', async () => { const postedCase = await createCase(supertest, getPostCaseRequest()); const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); @@ -122,6 +149,7 @@ export default ({ getService }: FtrProviderContext): void => { settings: postedCase.settings, owner: postedCase.owner, status: CaseStatuses.open, + severity: CaseSeverity.LOW, }, }); }); @@ -207,6 +235,11 @@ export default ({ getService }: FtrProviderContext): void => { await supertest.post(CASES_URL).set('kbn-xsrf', 'true').send(caseWithoutTags).expect(400); }); + it('400s when passing a wrong severity value', async () => { + // @ts-expect-error + await createCase(supertest, { ...getPostCaseRequest(), severity: 'very-severe' }, 400); + }); + it('400s if you passing status for a new case', async () => { const req = getPostCaseRequest(); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/get_all_user_actions.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/get_all_user_actions.ts index 283e6b0c5301b..aacb5f6c8ae17 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/get_all_user_actions.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/get_all_user_actions.ts @@ -9,6 +9,7 @@ import expect from '@kbn/expect'; import { CaseResponse, + CaseSeverity, CaseStatuses, CommentType, ConnectorTypes, @@ -106,6 +107,30 @@ export default ({ getService }: FtrProviderContext): void => { expect(statusUserAction.payload).to.eql({ status: 'closed' }); }); + it('creates a severity update user action when changing the severity', async () => { + const theCase = await createCase(supertest, postCaseReq); + await updateCase({ + supertest, + params: { + cases: [ + { + id: theCase.id, + version: theCase.version, + severity: CaseSeverity.HIGH, + }, + ], + }, + }); + + const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); + const statusUserAction = userActions[1]; + + expect(userActions.length).to.eql(2); + expect(statusUserAction.type).to.eql('severity'); + expect(statusUserAction.action).to.eql('update'); + expect(statusUserAction.payload).to.eql({ severity: 'high' }); + }); + it('creates a connector update user action', async () => { const newConnector = { id: '123', From 0650bd381978c450ce08957c7bcd69d5cb88c550 Mon Sep 17 00:00:00 2001 From: Robert Oskamp Date: Thu, 5 May 2022 11:24:03 +0200 Subject: [PATCH 66/68] [ML] Functional tests - stabilize outlier saved search tests (#131225) This PR stabilizes the outlier detection with saved searches functional tests. --- x-pack/test/accessibility/apps/ml.ts | 3 +- .../outlier_detection_creation.ts | 6 +-- ...outlier_detection_creation_saved_search.ts | 6 +-- .../ml/data_frame_analytics_creation.ts | 44 ++++++++++++++----- 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/x-pack/test/accessibility/apps/ml.ts b/x-pack/test/accessibility/apps/ml.ts index a783310d01706..2b99b665daced 100644 --- a/x-pack/test/accessibility/apps/ml.ts +++ b/x-pack/test/accessibility/apps/ml.ts @@ -251,8 +251,7 @@ export default function ({ getService }: FtrProviderContext) { await ml.dataFrameAnalyticsCreation.selectJobType(dfaJobType); await ml.testExecution.logTestStep('displays the source data preview'); await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewExists(); - await ml.testExecution.logTestStep('enables the source data preview histogram charts'); - await ml.dataFrameAnalyticsCreation.enableSourceDataPreviewHistogramCharts(true); + await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewHistogramChartEnabled(true); await ml.testExecution.logTestStep('displays the include fields selection'); await ml.dataFrameAnalyticsCreation.assertIncludeFieldsSelectionExists(); await a11y.testAppSnapshot(); diff --git a/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation.ts index 8a53528a89922..e9146ce548422 100644 --- a/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation.ts @@ -160,12 +160,10 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('displays the source data preview'); await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewExists(); - - await ml.testExecution.logTestStep('enables the source data preview histogram charts'); - await ml.dataFrameAnalyticsCreation.enableSourceDataPreviewHistogramCharts(true); + await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewHistogramChartEnabled(true); await ml.testExecution.logTestStep('displays the source data preview histogram charts'); - await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewHistogramCharts( + await ml.dataFrameAnalyticsCreation.enableAndAssertSourceDataPreviewHistogramCharts( testData.expected.histogramCharts ); diff --git a/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation_saved_search.ts b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation_saved_search.ts index 89247aed78ac4..1e428531e6aa9 100644 --- a/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation_saved_search.ts +++ b/x-pack/test/functional/apps/ml/group1/data_frame_analytics/outlier_detection_creation_saved_search.ts @@ -217,12 +217,10 @@ export default function ({ getService }: FtrProviderContext) { await ml.testExecution.logTestStep('displays the source data preview'); await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewExists(); - - await ml.testExecution.logTestStep('enables the source data preview histogram charts'); - await ml.dataFrameAnalyticsCreation.enableSourceDataPreviewHistogramCharts(true); + await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewHistogramChartEnabled(true); await ml.testExecution.logTestStep('displays the source data preview histogram charts'); - await ml.dataFrameAnalyticsCreation.assertSourceDataPreviewHistogramCharts( + await ml.dataFrameAnalyticsCreation.enableAndAssertSourceDataPreviewHistogramCharts( testData.expected.histogramCharts ); diff --git a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts index 88ef0fdf08c8d..77f1e34e67157 100644 --- a/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts +++ b/x-pack/test/functional/services/ml/data_frame_analytics_creation.ts @@ -49,6 +49,7 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( const jobTypeAttribute = `mlAnalyticsCreation-${jobType}-option`; await testSubjects.click(jobTypeAttribute); await this.assertJobTypeSelection(jobTypeAttribute); + await headerPage.waitUntilLoadingHasFinished(); }, async assertAdvancedEditorSwitchExists() { @@ -127,29 +128,41 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( await testSubjects.existOrFail('mlAnalyticsCreationDataGridHistogramButton'); }, - async enableSourceDataPreviewHistogramCharts(expectedDefaultButtonState: boolean) { - await this.assertSourceDataPreviewHistogramChartButtonCheckState(expectedDefaultButtonState); - if (expectedDefaultButtonState === false) { + async enableSourceDataPreviewHistogramCharts(shouldBeEnabled: boolean) { + const isEnabled = await this.getSourceDataPreviewHistogramChartButtonCheckState(); + if (isEnabled !== shouldBeEnabled) { await testSubjects.click('mlAnalyticsCreationDataGridHistogramButton'); - await this.assertSourceDataPreviewHistogramChartButtonCheckState(true); + await this.assertSourceDataPreviewHistogramChartEnabled(shouldBeEnabled); } }, - async assertSourceDataPreviewHistogramChartButtonCheckState(expectedCheckState: boolean) { - const actualCheckState = + async assertSourceDataPreviewHistogramChartEnabled(shouldBeEnabled: boolean) { + const isEnabled = await this.getSourceDataPreviewHistogramChartButtonCheckState(); + expect(isEnabled).to.eql( + shouldBeEnabled, + `Source data preview histogram charts should be '${ + shouldBeEnabled ? 'enabled' : 'disabled' + }' (got '${isEnabled ? 'enabled' : 'disabled'}')` + ); + }, + + async getSourceDataPreviewHistogramChartButtonCheckState(): Promise { + return ( (await testSubjects.getAttribute( 'mlAnalyticsCreationDataGridHistogramButton', 'aria-pressed' - )) === 'true'; - expect(actualCheckState).to.eql( - expectedCheckState, - `Chart histogram button check state should be '${expectedCheckState}' (got '${actualCheckState}')` + )) === 'true' ); }, + async scrollSourceDataPreviewIntoView() { + await testSubjects.scrollIntoView('mlAnalyticsCreationDataGrid loaded'); + }, + async assertSourceDataPreviewHistogramCharts( expectedHistogramCharts: Array<{ chartAvailable: boolean; id: string; legend: string }> ) { + await this.scrollSourceDataPreviewIntoView(); // For each chart, get the content of each header cell and assert // the legend text and column id and if the chart should be present or not. await retry.tryForTime(10000, async () => { @@ -178,6 +191,17 @@ export function MachineLearningDataFrameAnalyticsCreationProvider( }); }, + async enableAndAssertSourceDataPreviewHistogramCharts( + expectedHistogramCharts: Array<{ chartAvailable: boolean; id: string; legend: string }> + ) { + await retry.tryForTime(20 * 1000, async () => { + // turn histogram charts off and on before checking + await this.enableSourceDataPreviewHistogramCharts(false); + await this.enableSourceDataPreviewHistogramCharts(true); + await this.assertSourceDataPreviewHistogramCharts(expectedHistogramCharts); + }); + }, + async assertIncludeFieldsSelectionExists() { await testSubjects.existOrFail('mlAnalyticsCreateJobWizardIncludesTable', { timeout: 8000 }); From 58bc0f759e8de873bac9e9fa4607a0b2befa420d Mon Sep 17 00:00:00 2001 From: Julia Rechkunova Date: Thu, 5 May 2022 11:34:43 +0200 Subject: [PATCH 67/68] [Discover] Provide direct link from sample data UI to Discover (#130108) * [Discover] Allow to view sample data in Discover * [Discover] Update deps format * [Discover] Define order of items in the context menu * [Discover] Update for tests * [Discover] Add upgrade tests * [Discover] Add a test for ordering appLinks * [Discover] Use existing helpers * [Discover] Add 7 days time range to Discover link * [Discover] Rename the helper Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- src/plugins/discover/common/index.ts | 1 + .../common/services/saved_searches/index.ts | 9 ++ .../saved_searches/saved_searches_url.test.ts | 25 ++++++ .../saved_searches/saved_searches_url.ts | 11 +++ .../saved_searches_utils.test.ts | 16 ---- .../saved_searches/saved_searches_utils.ts | 7 +- src/plugins/discover/server/plugin.ts | 7 ++ .../discover/server/sample_data/index.ts | 9 ++ .../sample_data/register_sample_data.ts | 44 ++++++++++ .../sample_data_view_data_button.test.js.snap | 84 +++++++++++++++++++ .../components/sample_data_set_card.js | 1 + .../sample_data_view_data_button.js | 30 +++---- .../sample_data_view_data_button.test.js | 38 +++++++++ .../lib/sample_dataset_registry_types.ts | 7 ++ .../services/sample_data/routes/list.ts | 6 +- test/functional/page_objects/home_page.ts | 5 ++ .../apps/discover/discover_smoke_tests.ts | 39 +++++++-- 17 files changed, 298 insertions(+), 41 deletions(-) create mode 100644 src/plugins/discover/common/services/saved_searches/index.ts create mode 100644 src/plugins/discover/common/services/saved_searches/saved_searches_url.test.ts create mode 100644 src/plugins/discover/common/services/saved_searches/saved_searches_url.ts create mode 100644 src/plugins/discover/server/sample_data/index.ts create mode 100644 src/plugins/discover/server/sample_data/register_sample_data.ts diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts index 98ce5fc3b0b2b..173264aee731e 100644 --- a/src/plugins/discover/common/index.ts +++ b/src/plugins/discover/common/index.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +export const APP_ICON = 'discoverApp'; export const DEFAULT_COLUMNS_SETTING = 'defaultColumns'; export const SAMPLE_SIZE_SETTING = 'discover:sampleSize'; export const SORT_DEFAULT_ORDER_SETTING = 'discover:sort:defaultOrder'; diff --git a/src/plugins/discover/common/services/saved_searches/index.ts b/src/plugins/discover/common/services/saved_searches/index.ts new file mode 100644 index 0000000000000..014fdb31ed438 --- /dev/null +++ b/src/plugins/discover/common/services/saved_searches/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { getSavedSearchUrl, getSavedSearchFullPathUrl } from './saved_searches_url'; diff --git a/src/plugins/discover/common/services/saved_searches/saved_searches_url.test.ts b/src/plugins/discover/common/services/saved_searches/saved_searches_url.test.ts new file mode 100644 index 0000000000000..81f4498939b98 --- /dev/null +++ b/src/plugins/discover/common/services/saved_searches/saved_searches_url.test.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getSavedSearchUrl, getSavedSearchFullPathUrl } from './saved_searches_url'; + +describe('saved_searches_url', () => { + describe('getSavedSearchUrl', () => { + test('should return valid saved search url', () => { + expect(getSavedSearchUrl()).toBe('#/'); + expect(getSavedSearchUrl('id')).toBe('#/view/id'); + }); + }); + + describe('getSavedSearchFullPathUrl', () => { + test('should return valid full path url', () => { + expect(getSavedSearchFullPathUrl()).toBe('/app/discover#/'); + expect(getSavedSearchFullPathUrl('id')).toBe('/app/discover#/view/id'); + }); + }); +}); diff --git a/src/plugins/discover/common/services/saved_searches/saved_searches_url.ts b/src/plugins/discover/common/services/saved_searches/saved_searches_url.ts new file mode 100644 index 0000000000000..cc5ecdb61f565 --- /dev/null +++ b/src/plugins/discover/common/services/saved_searches/saved_searches_url.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const getSavedSearchUrl = (id?: string) => (id ? `#/view/${encodeURIComponent(id)}` : '#/'); + +export const getSavedSearchFullPathUrl = (id?: string) => `/app/discover${getSavedSearchUrl(id)}`; diff --git a/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts b/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts index 4a4713badb807..9b42d7557b05c 100644 --- a/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts +++ b/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts @@ -7,8 +7,6 @@ */ import { - getSavedSearchUrl, - getSavedSearchFullPathUrl, fromSavedSearchAttributes, toSavedSearchAttributes, throwErrorOnSavedSearchUrlConflict, @@ -19,20 +17,6 @@ import { createSearchSourceMock } from '@kbn/data-plugin/public/mocks'; import type { SavedSearchAttributes, SavedSearch } from './types'; describe('saved_searches_utils', () => { - describe('getSavedSearchUrl', () => { - test('should return valid saved search url', () => { - expect(getSavedSearchUrl()).toBe('#/'); - expect(getSavedSearchUrl('id')).toBe('#/view/id'); - }); - }); - - describe('getSavedSearchFullPathUrl', () => { - test('should return valid full path url', () => { - expect(getSavedSearchFullPathUrl()).toBe('/app/discover#/'); - expect(getSavedSearchFullPathUrl('id')).toBe('/app/discover#/view/id'); - }); - }); - describe('fromSavedSearchAttributes', () => { test('should convert attributes into SavedSearch', () => { const attributes: SavedSearchAttributes = { diff --git a/src/plugins/discover/public/services/saved_searches/saved_searches_utils.ts b/src/plugins/discover/public/services/saved_searches/saved_searches_utils.ts index 4dbb84613ead8..26b3c0b7cf9b5 100644 --- a/src/plugins/discover/public/services/saved_searches/saved_searches_utils.ts +++ b/src/plugins/discover/public/services/saved_searches/saved_searches_utils.ts @@ -8,9 +8,10 @@ import { i18n } from '@kbn/i18n'; import type { SavedSearchAttributes, SavedSearch } from './types'; -export const getSavedSearchUrl = (id?: string) => (id ? `#/view/${encodeURIComponent(id)}` : '#/'); - -export const getSavedSearchFullPathUrl = (id?: string) => `/app/discover${getSavedSearchUrl(id)}`; +export { + getSavedSearchUrl, + getSavedSearchFullPathUrl, +} from '../../../common/services/saved_searches'; export const getSavedSearchUrlConflictMessage = async (savedSearch: SavedSearch) => i18n.translate('discover.savedSearchEmbeddable.legacyURLConflict.errorMessage', { diff --git a/src/plugins/discover/server/plugin.ts b/src/plugins/discover/server/plugin.ts index 9147f533d28d6..888fcf55c2351 100644 --- a/src/plugins/discover/server/plugin.ts +++ b/src/plugins/discover/server/plugin.ts @@ -8,15 +8,18 @@ import { CoreSetup, CoreStart, Plugin } from '@kbn/core/server'; import type { PluginSetup as DataPluginSetup } from '@kbn/data-plugin/server'; +import type { HomeServerPluginSetup } from '@kbn/home-plugin/server'; import { getUiSettings } from './ui_settings'; import { capabilitiesProvider } from './capabilities_provider'; import { getSavedSearchObjectType } from './saved_objects'; +import { registerSampleData } from './sample_data'; export class DiscoverServerPlugin implements Plugin { public setup( core: CoreSetup, plugins: { data: DataPluginSetup; + home?: HomeServerPluginSetup; } ) { const getSearchSourceMigrations = plugins.data.search.searchSource.getAllMigrations.bind( @@ -26,6 +29,10 @@ export class DiscoverServerPlugin implements Plugin { core.uiSettings.register(getUiSettings(core.docLinks)); core.savedObjects.registerType(getSavedSearchObjectType(getSearchSourceMigrations)); + if (plugins.home) { + registerSampleData(plugins.home.sampleData); + } + return {}; } diff --git a/src/plugins/discover/server/sample_data/index.ts b/src/plugins/discover/server/sample_data/index.ts new file mode 100644 index 0000000000000..43edd42293edf --- /dev/null +++ b/src/plugins/discover/server/sample_data/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export { registerSampleData } from './register_sample_data'; diff --git a/src/plugins/discover/server/sample_data/register_sample_data.ts b/src/plugins/discover/server/sample_data/register_sample_data.ts new file mode 100644 index 0000000000000..a1ff9951d9179 --- /dev/null +++ b/src/plugins/discover/server/sample_data/register_sample_data.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { i18n } from '@kbn/i18n'; +import type { SampleDataRegistrySetup } from '@kbn/home-plugin/server'; +import { APP_ICON } from '../../common'; +import { getSavedSearchFullPathUrl } from '../../common/services/saved_searches'; + +function getDiscoverPathForSampleDataset(objId: string) { + // TODO: remove the time range from the URL query when saved search objects start supporting time range configuration + // https://github.com/elastic/kibana/issues/9761 + return `${getSavedSearchFullPathUrl(objId)}?_g=(time:(from:now-7d,to:now))`; +} + +export function registerSampleData(sampleDataRegistry: SampleDataRegistrySetup) { + const linkLabel = i18n.translate('discover.sampleData.viewLinkLabel', { + defaultMessage: 'Discover', + }); + const { addAppLinksToSampleDataset, getSampleDatasets } = sampleDataRegistry; + const sampleDatasets = getSampleDatasets(); + + sampleDatasets.forEach((sampleDataset) => { + const sampleSavedSearchObject = sampleDataset.savedObjects.find( + (object) => object.type === 'search' + ); + + if (sampleSavedSearchObject) { + addAppLinksToSampleDataset(sampleDataset.id, [ + { + sampleObject: sampleSavedSearchObject, + getPath: getDiscoverPathForSampleDataset, + label: linkLabel, + icon: APP_ICON, + order: -1, + }, + ]); + } + }); +} diff --git a/src/plugins/home/public/application/components/__snapshots__/sample_data_view_data_button.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/sample_data_view_data_button.test.js.snap index d9e341394ee00..0d634049305ad 100644 --- a/src/plugins/home/public/application/components/__snapshots__/sample_data_view_data_button.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/sample_data_view_data_button.test.js.snap @@ -57,6 +57,90 @@ exports[`should render popover when appLinks is not empty 1`] = ` `; +exports[`should render popover with ordered appLinks 1`] = ` + + View data + + } + closePopover={[Function]} + data-test-subj="launchSampleDataSetecommerce" + display="inlineBlock" + hasArrow={true} + id="sampleDataLinksecommerce" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" +> + , + "name": "myAppLabel[-1]", + "onClick": [Function], + }, + Object { + "data-test-subj": "viewSampleDataSetecommerce-dashboard", + "href": "root/app/dashboards#/view/722b74f0-b882-11e8-a6d9-e546fe2bba5f", + "icon": , + "name": "Dashboard", + "onClick": [Function], + }, + Object { + "href": "rootapp/myAppPath", + "icon": , + "name": "myAppLabel[3]", + "onClick": [Function], + }, + Object { + "href": "rootapp/myAppPath", + "icon": , + "name": "myAppLabel[5]", + "onClick": [Function], + }, + Object { + "href": "rootapp/myAppPath", + "icon": , + "name": "myAppLabel", + "onClick": [Function], + }, + ], + }, + ] + } + size="m" + /> + +`; + exports[`should render simple button when appLinks is empty 1`] = ` { + const dashboardAppLink = { + path: dashboardPath, + label: i18n.translate('home.sampleDataSetCard.dashboardLinkLabel', { + defaultMessage: 'Dashboard', + }), + icon: 'dashboardApp', + order: 0, + 'data-test-subj': `viewSampleDataSet${this.props.id}-dashboard`, + }; + + const sortedItems = sortBy([dashboardAppLink, ...this.props.appLinks], 'order'); + const items = sortedItems.map(({ path, label, icon, ...rest }) => { return { name: label, icon: , href: this.addBasePath(path), onClick: createAppNavigationHandler(path), + ...(rest['data-test-subj'] ? { 'data-test-subj': rest['data-test-subj'] } : {}), }; }); @@ -75,18 +87,7 @@ export class SampleDataViewDataButton extends React.Component { const panels = [ { id: 0, - items: [ - { - name: i18n.translate('home.sampleDataSetCard.dashboardLinkLabel', { - defaultMessage: 'Dashboard', - }), - icon: , - href: prefixedDashboardPath, - onClick: createAppNavigationHandler(dashboardPath), - 'data-test-subj': `viewSampleDataSet${this.props.id}-dashboard`, - }, - ...additionalItems, - ], + items, }, ]; const popoverButton = ( @@ -124,6 +125,7 @@ SampleDataViewDataButton.propTypes = { path: PropTypes.string.isRequired, label: PropTypes.string.isRequired, icon: PropTypes.string.isRequired, + order: PropTypes.number, }) ).isRequired, }; diff --git a/src/plugins/home/public/application/components/sample_data_view_data_button.test.js b/src/plugins/home/public/application/components/sample_data_view_data_button.test.js index b097b5e322500..f3cfd5a7a661e 100644 --- a/src/plugins/home/public/application/components/sample_data_view_data_button.test.js +++ b/src/plugins/home/public/application/components/sample_data_view_data_button.test.js @@ -48,3 +48,41 @@ test('should render popover when appLinks is not empty', () => { ); expect(component).toMatchSnapshot(); // eslint-disable-line }); + +test('should render popover with ordered appLinks', () => { + const appLinks = [ + { + path: 'app/myAppPath', + label: 'myAppLabel[-1]', + icon: 'logoKibana', + order: -1, // to position it above Dashboard link + }, + { + path: 'app/myAppPath', + label: 'myAppLabel', + icon: 'logoKibana', + }, + { + path: 'app/myAppPath', + label: 'myAppLabel[5]', + icon: 'logoKibana', + order: 5, + }, + { + path: 'app/myAppPath', + label: 'myAppLabel[3]', + icon: 'logoKibana', + order: 3, + }, + ]; + + const component = shallow( + + ); + expect(component).toMatchSnapshot(); // eslint-disable-line +}); diff --git a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts index 8d26d08460b5b..9b1212e13b024 100644 --- a/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts +++ b/src/plugins/home/server/services/sample_data/lib/sample_dataset_registry_types.ts @@ -58,4 +58,11 @@ export interface AppLinkData { * The icon for this app link. */ icon: string; + /** + * Index of the links (ascending order, smallest will be displayed first). + * Used for ordering in the dropdown. + * + * @remark links without order defined will be displayed last + */ + order?: number; } diff --git a/src/plugins/home/server/services/sample_data/routes/list.ts b/src/plugins/home/server/services/sample_data/routes/list.ts index 39690b3944d0c..a83ee7a57c432 100644 --- a/src/plugins/home/server/services/sample_data/routes/list.ts +++ b/src/plugins/home/server/services/sample_data/routes/list.ts @@ -35,12 +35,12 @@ export const createListRoute = ( ?.foundObjectId ?? id; const appLinks = (appLinksMap.get(sampleDataset.id) ?? []).map((data) => { - const { sampleObject, getPath, label, icon } = data; + const { sampleObject, getPath, label, icon, order } = data; if (sampleObject === null) { - return { path: getPath(''), label, icon }; + return { path: getPath(''), label, icon, order }; } const objectId = findObjectId(sampleObject.type, sampleObject.id); - return { path: getPath(objectId), label, icon }; + return { path: getPath(objectId), label, icon, order }; }); const sampleDataStatus = await getSampleDatasetStatus( context, diff --git a/test/functional/page_objects/home_page.ts b/test/functional/page_objects/home_page.ts index 1e3e6a9634f4c..4acd8a6e10e95 100644 --- a/test/functional/page_objects/home_page.ts +++ b/test/functional/page_objects/home_page.ts @@ -78,6 +78,11 @@ export class HomePageObject extends FtrService { }); } + async launchSampleDiscover(id: string) { + await this.launchSampleDataSet(id); + await this.find.clickByLinkText('Discover'); + } + async launchSampleDashboard(id: string) { await this.launchSampleDataSet(id); await this.find.clickByLinkText('Dashboard'); diff --git a/x-pack/test/upgrade/apps/discover/discover_smoke_tests.ts b/x-pack/test/upgrade/apps/discover/discover_smoke_tests.ts index 150458919d41d..1d2df7a703161 100644 --- a/x-pack/test/upgrade/apps/discover/discover_smoke_tests.ts +++ b/x-pack/test/upgrade/apps/discover/discover_smoke_tests.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; -export default function ({ getPageObjects, getService }: FtrProviderContext) { +export default function ({ getPageObjects }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'header', 'home', 'discover', 'timePicker']); describe('upgrade discover smoke tests', function describeIndexTests() { @@ -18,9 +18,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { ]; const discoverTests = [ - { name: 'kibana_sample_data_flights', timefield: true, hits: '' }, - { name: 'kibana_sample_data_logs', timefield: true, hits: '' }, - { name: 'kibana_sample_data_ecommerce', timefield: true, hits: '' }, + { name: 'flights', timefield: true, hits: '' }, + { name: 'logs', timefield: true, hits: '' }, + { name: 'ecommerce', timefield: true, hits: '' }, ]; spaces.forEach(({ space, basePath }) => { @@ -31,7 +31,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { basePath, }); await PageObjects.header.waitUntilLoadingHasFinished(); - await PageObjects.discover.selectIndexPattern(name); + await PageObjects.discover.selectIndexPattern(`kibana_sample_data_${name}`); await PageObjects.discover.waitUntilSearchingHasFinished(); if (timefield) { await PageObjects.timePicker.setCommonlyUsedTime('Last_24 hours'); @@ -52,6 +52,35 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); }); + + discoverTests.forEach(({ name, timefield, hits }) => { + describe('space: ' + space + ', name: ' + name, () => { + before(async () => { + await PageObjects.common.navigateToActualUrl('home', '/tutorial_directory/sampleData', { + basePath, + }); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.home.launchSampleDiscover(name); + await PageObjects.header.waitUntilLoadingHasFinished(); + if (timefield) { + await PageObjects.timePicker.setCommonlyUsedTime('Last_24 hours'); + await PageObjects.discover.waitUntilSearchingHasFinished(); + } + }); + it('shows hit count greater than zero', async () => { + const hitCount = await PageObjects.discover.getHitCount(); + if (hits === '') { + expect(hitCount).to.be.greaterThan(0); + } else { + expect(hitCount).to.be.equal(hits); + } + }); + it('shows table rows not empty', async () => { + const tableRows = await PageObjects.discover.getDocTableRows(); + expect(tableRows.length).to.be.greaterThan(0); + }); + }); + }); }); }); } From 234a6365d0eb226c5cc7fb2e98b7579c3ab9c45b Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 5 May 2022 11:39:25 +0100 Subject: [PATCH 68/68] skip flaky suite (#131602) --- .../security_solution_endpoint/apps/endpoint/policy_list.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts index 7020babc4520b..840c36a558ba0 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/policy_list.ts @@ -78,7 +78,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await backButton.click(); await pageObjects.policy.ensureIsOnListPage(); }); - describe('when the endpoint count link is clicked', () => { + // FLAKY: https://github.com/elastic/kibana/issues/131602 + describe.skip('when the endpoint count link is clicked', () => { it('navigates to the endpoint list page filtered by policy', async () => { const endpointCount = (await testSubjects.findAll('policyEndpointCountLink'))[0]; await endpointCount.click();