diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.js b/.buildkite/scripts/pipelines/pull_request/pipeline.js index 7b5c944d31c1c..02d6fc270ddb0 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.js +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.js @@ -66,12 +66,12 @@ const uploadPipeline = (pipelineContent) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/security_solution.yml')); } - // if ( - // (await doAnyChangesMatch([/^x-pack\/plugins\/apm/])) || - // process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') - // ) { - // pipeline.push(getPipeline('.buildkite/pipelines/pull_request/apm_cypress.yml')); - // } + if ( + (await doAnyChangesMatch([/^x-pack\/plugins\/apm/])) || + process.env.GITHUB_PR_LABELS.includes('ci:all-cypress-suites') + ) { + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/apm_cypress.yml')); + } if (await doAnyChangesMatch([/^x-pack\/plugins\/uptime/])) { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/uptime.yml')); diff --git a/.buildkite/scripts/steps/functional/apm_cypress.sh b/.buildkite/scripts/steps/functional/apm_cypress.sh index 800f22c78d14c..77b26fafee920 100755 --- a/.buildkite/scripts/steps/functional/apm_cypress.sh +++ b/.buildkite/scripts/steps/functional/apm_cypress.sh @@ -2,7 +2,10 @@ set -euo pipefail -source .buildkite/scripts/steps/functional/common.sh +source .buildkite/scripts/common/util.sh + +.buildkite/scripts/bootstrap.sh +.buildkite/scripts/download_build_artifacts.sh export JOB=kibana-apm-cypress @@ -11,4 +14,5 @@ echo "--- APM Cypress Tests" cd "$XPACK_DIR" checks-reporter-with-killswitch "APM Cypress Tests" \ - node plugins/apm/scripts/test/e2e.js + node plugins/apm/scripts/test/e2e.js \ + --kibana-install-dir "$KIBANA_BUILD_LOCATION" diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 341a6b6b6bb33..fda6834f9b4e9 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -16,9 +16,9 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | securitySolution | - | | | dataViews, visTypeTimeseries, reporting, discover, observability, maps, dataVisualizer, apm, lens, osquery, securitySolution, transform, savedObjects, indexPatternFieldEditor, visualizations, dashboard, graph, stackAlerts, uptime, indexPatternEditor, indexPatternManagement, inputControlVis, savedObjectsManagement, visualize, visDefaultEditor, visTypeVega, data | - | | | dataViews, discover, maps, dataVisualizer, lens, indexPatternFieldEditor, securitySolution, indexPatternEditor, indexPatternManagement, inputControlVis, visDefaultEditor, visTypeTimeseries, data | - | -| | dataViews, timelines, monitoring, securitySolution, indexPatternManagement, stackAlerts, transform | - | -| | home, savedObjects, security, fleet, indexPatternFieldEditor, discover, visualizations, dashboard, lens, observability, maps, fileUpload, dataVisualizer, ml, infra, apm, graph, monitoring, osquery, securitySolution, stackAlerts, transform, upgradeAssistant, uptime, indexPatternEditor, indexPatternManagement, inputControlVis, kibanaOverview, savedObjectsManagement, visualize, visTypeTimelion, visTypeTimeseries, visTypeVega | - | -| | dataViews, timelines, monitoring, securitySolution, indexPatternManagement, stackAlerts, transform, data | - | +| | dataViews, timelines, monitoring, securitySolution, indexPatternManagement, presentationUtil, stackAlerts, transform | - | +| | home, savedObjects, security, fleet, indexPatternFieldEditor, discover, dashboard, lens, observability, maps, fileUpload, dataVisualizer, ml, infra, graph, monitoring, osquery, securitySolution, stackAlerts, transform, upgradeAssistant, uptime, indexPatternEditor, indexPatternManagement, inputControlVis, kibanaOverview, savedObjectsManagement, visualize, visTypeTimelion, visTypeTimeseries, visTypeVega | - | +| | dataViews, timelines, monitoring, securitySolution, indexPatternManagement, presentationUtil, stackAlerts, transform, data | - | | | dataViews, discover, maps, dataVisualizer, lens, indexPatternFieldEditor, securitySolution, indexPatternEditor, indexPatternManagement, inputControlVis, visDefaultEditor, visTypeTimeseries, data | - | | | dataViews, visTypeTimeseries, reporting, discover, observability, maps, dataVisualizer, apm, lens, osquery, securitySolution, transform, savedObjects, indexPatternFieldEditor, visualizations, dashboard, graph, stackAlerts, uptime, indexPatternEditor, indexPatternManagement, inputControlVis, savedObjectsManagement, visualize, visDefaultEditor, visTypeVega, data | - | | | dataViews, discover, maps, dataVisualizer, lens, indexPatternFieldEditor, securitySolution, indexPatternEditor, indexPatternManagement, inputControlVis, visDefaultEditor, visTypeTimeseries | - | @@ -29,27 +29,30 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | dashboard, lens, maps, ml, securitySolution, security, visualize | - | | | securitySolution | - | | | dataViews, visTypeTimeseries, maps, lens, discover, data | - | -| | dataViews, discover, observability, savedObjects, security, visualizations, dashboard, lens, maps, graph, stackAlerts, transform, indexPatternManagement, inputControlVis, savedObjectsManagement, visTypeTimelion, data | - | +| | dataViews, discover, observability, savedObjects, security, dashboard, lens, maps, graph, stackAlerts, transform, indexPatternManagement, inputControlVis, savedObjectsManagement, visTypeTimelion, data | - | | | dataViews, discover, transform, canvas | - | -| | dataViews, observability, indexPatternEditor, apm | - | +| | dataViews, observability, indexPatternEditor | - | | | dataViews | - | | | dataViews, indexPatternManagement | - | | | dataViews, discover, transform, canvas, data | - | | | dataViews, data | - | | | dataViews, data | - | | | dataViews | - | -| | dataViews, observability, indexPatternEditor, apm, data | - | +| | dataViews, observability, indexPatternEditor, data | - | | | dataViews, visualizations, dashboard, data | - | | | dataViews, data | - | | | dataViews, visTypeTimeseries, maps, lens, discover, data | - | -| | dataViews, discover, observability, savedObjects, security, visualizations, dashboard, lens, maps, graph, stackAlerts, transform, indexPatternManagement, inputControlVis, savedObjectsManagement, visTypeTimelion, data | - | +| | dataViews, discover, observability, savedObjects, security, dashboard, lens, maps, graph, stackAlerts, transform, indexPatternManagement, inputControlVis, savedObjectsManagement, visTypeTimelion, data | - | | | dataViews, discover, dashboard, lens, visualize | - | | | dataViews, indexPatternManagement, data | - | +| | dataViews, maps | - | | | dataViews, discover, transform, canvas | - | | | dataViews, visTypeTimeseries, maps, lens, discover | - | +| | dataViews, maps | - | | | fleet, indexPatternFieldEditor, discover, dashboard, lens, ml, stackAlerts, indexPatternManagement, visTypePie, visTypeTable, visTypeTimeseries, visTypeXy, visTypeVislib | - | | | reporting, visTypeTimeseries | - | | | data, lens, visTypeTimeseries, infra, maps, visTypeTimelion | - | +| | maps | - | | | dashboard, maps, graph, visualize | - | | | spaces, security, reporting, actions, alerting, ml, fleet, remoteClusters, graph, indexLifecycleManagement, maps, painlessLab, rollup, searchprofiler, snapshotRestore, transform, upgradeAssistant | - | | | discover, dashboard, lens, visualize | - | @@ -57,9 +60,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | discover | - | | | discover | - | | | embeddable, presentationUtil, discover, dashboard, graph | - | -| | discover, visualizations, dashboard | - | -| | savedObjectsTaggingOss, discover, visualizations, dashboard | - | -| | discover, visualizations, dashboard | - | | | data, discover, embeddable | - | | | advancedSettings, discover | - | | | advancedSettings, discover | - | @@ -68,7 +68,9 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | security | - | | | security, licenseManagement, ml, fleet, apm, reporting, crossClusterReplication, logstash, painlessLab, searchprofiler, watcher | - | | | management, fleet, security, kibanaOverview | - | -| | visualizations | - | +| | dashboard | - | +| | savedObjectsTaggingOss, dashboard | - | +| | dashboard | - | | | spaces, savedObjectsManagement | - | | | spaces, savedObjectsManagement | - | | | reporting | - | @@ -103,14 +105,14 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | discover, visualizations, dashboard, lens, observability, timelines, maps, infra, dashboardEnhanced, discoverEnhanced, securitySolution, urlDrilldown, inputControlVis, visualize, visTypeTimelion, visTypeVega, ml, visTypeTimeseries | 8.1 | | | discover, visualizations, dashboard, lens, observability, timelines, maps, infra, dashboardEnhanced, discoverEnhanced, securitySolution, urlDrilldown, inputControlVis, visualize, visTypeTimelion, visTypeVega, ml, visTypeTimeseries | 8.1 | | | discover, visualizations, dashboard, lens, observability, timelines, maps, infra, dashboardEnhanced, discoverEnhanced, securitySolution, urlDrilldown, inputControlVis, visualize, visTypeTimelion, visTypeVega, ml, visTypeTimeseries | 8.1 | -| | dataViews, fleet, infra, monitoring, stackAlerts, indexPatternManagement | 8.1 | -| | dataViews, fleet, infra, monitoring, stackAlerts, indexPatternManagement, data | 8.1 | +| | dataViews, fleet, infra, monitoring, stackAlerts, indexPatternManagement, presentationUtil | 8.1 | +| | dataViews, fleet, infra, monitoring, stackAlerts, indexPatternManagement, presentationUtil, data | 8.1 | | | dataViews | 8.1 | | | dataViews | 8.1 | | | indexPatternManagement, dataViews | 8.1 | | | visTypeTimeseries, graph, indexPatternManagement, dataViews | 8.1 | | | dataViews, indexPatternManagement | 8.1 | -| | dataViews, fleet, infra, monitoring, stackAlerts, indexPatternManagement | 8.1 | +| | dataViews, fleet, infra, monitoring, stackAlerts, indexPatternManagement, presentationUtil | 8.1 | | | dataViews | 8.1 | | | dataViews | 8.1 | | | indexPatternManagement, dataViews | 8.1 | @@ -125,8 +127,6 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | lens, infra, apm, graph, monitoring, stackAlerts, transform | 8.1 | | | observability | 8.1 | | | observability | 8.1 | -| | visualizations, visDefaultEditor | 8.1 | -| | visualizations, visDefaultEditor | 8.1 | | | indexPatternManagement | 8.1 | | | indexPatternManagement | 8.1 | | | indexPatternManagement | 8.1 | @@ -136,6 +136,8 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | indexPatternFieldEditor | 8.1 | | | indexPatternFieldEditor | 8.1 | | | indexPatternFieldEditor | 8.1 | +| | visualizations, visDefaultEditor | 8.1 | +| | visualizations, visDefaultEditor | 8.1 | | | visualize | 8.1 | | | timelines | 8.1 | | | timelines | 8.1 | @@ -214,8 +216,6 @@ Safe to remove. | | | | | | -| | -| | | | | | | | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 7ef3a75269963..d405da72f959c 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -48,19 +48,16 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern)+ 4 more | - | -| | [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPatternSpec), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPatternSpec) | - | -| | [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=indexPatterns) | - | +| | [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=esKuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=esKuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=esKuery) | 8.1 | -| | [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPatternSpec), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPatternSpec), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPatternSpec), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPatternSpec) | - | -| | [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern)+ 4 more | - | -| | [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern), [use_index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/use_index_pattern.ts#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx#:~:text=IndexPattern) | - | +| | [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern) | - | +| | [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [SelectedFilters.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/SelectedFilters.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern), [selected_wildcards.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/components/app/RumDashboard/LocalUIFilters/selected_wildcards.tsx#:~:text=IndexPattern) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/plugin.ts#:~:text=environment) | - | | | [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode)+ 2 more | - | | | [license_context.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/public/context/license/license_context.tsx#:~:text=license%24) | - | | | [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode), [license_check.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/common/license_check.test.ts#:~:text=mode)+ 2 more | - | -| | [index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/server/routes/index_pattern.ts#:~:text=spacesService) | 7.16 | -| | [index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/server/routes/index_pattern.ts#:~:text=getSpaceId) | 7.16 | +| | [data_view.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/server/routes/data_view.ts#:~:text=spacesService) | 7.16 | +| | [data_view.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/apm/server/routes/data_view.ts#:~:text=getSpaceId) | 7.16 | @@ -228,6 +225,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/index.ts#:~:text=IndexPattern), [data_view_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.test.ts#:~:text=IndexPattern), [data_view_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.test.ts#:~:text=IndexPattern), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/public/index.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern) | - | | | [data_views.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_views.ts#:~:text=IndexPatternListItem), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/index.ts#:~:text=IndexPatternListItem) | - | | | [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=intervalName), [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=intervalName), [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=intervalName), [update_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/server/routes/update_index_pattern.ts#:~:text=intervalName), [update_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/server/routes/update_index_pattern.ts#:~:text=intervalName) | 8.1 | +| | [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=flattenHit) | - | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=addScriptedField), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=addScriptedField) | 8.1 | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=removeScriptedField) | 8.1 | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getNonScriptedFields) | 8.1 | @@ -238,6 +236,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/index.ts#:~:text=IndexPattern), [data_view_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.test.ts#:~:text=IndexPattern), [data_view_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/fields/data_view_field.test.ts#:~:text=IndexPattern), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/public/index.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=IndexPattern) | - | | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/index.ts#:~:text=IndexPatternsService), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/public/index.ts#:~:text=IndexPatternsService), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/index.ts#:~:text=IndexPatternsService), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/public/index.ts#:~:text=IndexPatternsService) | - | | | [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=intervalName), [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=intervalName), [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=intervalName), [update_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/server/routes/update_index_pattern.ts#:~:text=intervalName), [update_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/server/routes/update_index_pattern.ts#:~:text=intervalName) | 8.1 | +| | [data_view.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.ts#:~:text=flattenHit) | - | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=addScriptedField), [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=addScriptedField) | 8.1 | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=removeScriptedField) | 8.1 | | | [data_view.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/data_views/common/data_views/data_view.test.ts#:~:text=getNonScriptedFields) | 8.1 | @@ -250,11 +249,11 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts#:~:text=IndexPattern), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts#:~:text=IndexPattern), [geo_point_content_with_map.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx#:~:text=IndexPattern), [geo_point_content_with_map.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx#:~:text=IndexPattern), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPattern), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPattern)+ 60 more | - | -| | [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField)+ 16 more | - | +| | [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField)+ 20 more | - | | | [file_data_visualizer.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx#:~:text=indexPatterns), [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=indexPatterns) | - | -| | [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField)+ 16 more | - | +| | [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField)+ 20 more | - | | | [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts#:~:text=IndexPattern), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts#:~:text=IndexPattern), [geo_point_content_with_map.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx#:~:text=IndexPattern), [geo_point_content_with_map.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx#:~:text=IndexPattern), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPattern), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPattern)+ 60 more | - | -| | [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField)+ 3 more | - | +| | [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_data_row.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/types/field_data_row.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [field_types_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/util/field_types_utils.ts#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [search_panel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/search_panel/search_panel.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField), [index_data_visualizer_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/index_data_visualizer_view/index_data_visualizer_view.tsx#:~:text=IndexPatternField)+ 5 more | - | | | [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [lens_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/lens_utils.ts#:~:text=IndexPattern), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts#:~:text=IndexPattern), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/field_data_row/action_menu/actions.ts#:~:text=IndexPattern), [geo_point_content_with_map.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx#:~:text=IndexPattern), [geo_point_content_with_map.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/geo_point_content_with_map/geo_point_content_with_map.tsx#:~:text=IndexPattern), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPattern), [index_based_expanded_row.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/data_visualizer/public/application/common/components/expanded_row/index_based_expanded_row.tsx#:~:text=IndexPattern)+ 25 more | - | @@ -264,38 +263,35 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService)+ 6 more | - | -| | [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract)+ 34 more | - | -| | [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern)+ 378 more | - | -| | [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField), [discover_field_visualize.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx#:~:text=IndexPatternField), [discover_field_visualize.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx#:~:text=IndexPatternField)+ 192 more | - | +| | [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract)+ 26 more | - | +| | [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern)+ 382 more | - | +| | [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField)+ 198 more | - | | | [discover_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_index_pattern.tsx#:~:text=IndexPatternAttributes), [discover_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_index_pattern.tsx#:~:text=IndexPatternAttributes), [discover_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/components/sidebar/discover_index_pattern.d.ts#:~:text=IndexPatternAttributes), [discover_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/components/sidebar/discover_index_pattern.d.ts#:~:text=IndexPatternAttributes), [discover_sidebar_responsive.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx#:~:text=IndexPatternAttributes), [discover_sidebar_responsive.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_app.tsx#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_app.tsx#:~:text=IndexPatternAttributes)+ 3 more | - | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | | | [anchor.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/services/anchor.ts#:~:text=fetch), [fetch_hits_in_interval.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/services/utils/fetch_hits_in_interval.ts#:~:text=fetch) | 8.1 | -| | [build_services.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/build_services.ts#:~:text=indexPatterns), [source_viewer.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/source_viewer/source_viewer.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=indexPatterns), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=indexPatterns) | - | +| | [build_services.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/build_services.ts#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=indexPatterns), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=indexPatterns), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=indexPatterns) | - | | | [histogram.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/chart/histogram.tsx#:~:text=fieldFormats) | - | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=esFilters), [get_context_url.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/get_context_url.tsx#:~:text=esFilters), [get_context_url.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/get_context_url.tsx#:~:text=esFilters), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=esFilters), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=esFilters)+ 17 more | 8.1 | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/types.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=Filter)+ 22 more | 8.1 | | | [discover_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_index_pattern.tsx#:~:text=IndexPatternAttributes), [discover_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_index_pattern.tsx#:~:text=IndexPatternAttributes), [discover_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/components/sidebar/discover_index_pattern.d.ts#:~:text=IndexPatternAttributes), [discover_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/components/sidebar/discover_index_pattern.d.ts#:~:text=IndexPatternAttributes), [discover_sidebar_responsive.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx#:~:text=IndexPatternAttributes), [discover_sidebar_responsive.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_app.tsx#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_app.tsx#:~:text=IndexPatternAttributes)+ 16 more | - | -| | [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField), [discover_field_visualize.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx#:~:text=IndexPatternField), [discover_field_visualize.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx#:~:text=IndexPatternField)+ 192 more | - | +| | [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField)+ 198 more | - | | | [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService)+ 6 more | - | -| | [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract)+ 34 more | - | +| | [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_data_grid_columns.ts#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [use_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/use_index_pattern.tsx#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/utils/resolve_index_pattern.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [use_data_grid_columns.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/helpers/use_data_grid_columns.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract), [resolve_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/utils/resolve_index_pattern.d.ts#:~:text=IndexPatternsContract)+ 26 more | - | | | [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=ensureDefaultDataView), [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=ensureDefaultDataView) | - | -| | [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern)+ 378 more | - | +| | [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern)+ 382 more | - | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/types.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=Filter)+ 22 more | 8.1 | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=create), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=create) | - | | | [anchor.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/services/anchor.ts#:~:text=fetch), [fetch_hits_in_interval.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/services/utils/fetch_hits_in_interval.ts#:~:text=fetch) | 8.1 | -| | [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField), [discover_field_visualize.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx#:~:text=IndexPatternField), [discover_field_visualize.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx#:~:text=IndexPatternField)+ 91 more | - | +| | [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [discover_grid_cell_actions.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_cell_actions.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [doc_table_wrapper.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/doc_table_wrapper.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [data_visualizer_grid.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=IndexPatternField), [context_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/context/context_app.tsx#:~:text=IndexPatternField)+ 94 more | - | | | [discover_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_index_pattern.tsx#:~:text=IndexPatternAttributes), [discover_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_index_pattern.tsx#:~:text=IndexPatternAttributes), [discover_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/components/sidebar/discover_index_pattern.d.ts#:~:text=IndexPatternAttributes), [discover_index_pattern.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/apps/main/components/sidebar/discover_index_pattern.d.ts#:~:text=IndexPatternAttributes), [discover_sidebar_responsive.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx#:~:text=IndexPatternAttributes), [discover_sidebar_responsive.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/layout/types.ts#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_app.tsx#:~:text=IndexPatternAttributes), [discover_main_app.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_app.tsx#:~:text=IndexPatternAttributes)+ 3 more | - | -| | [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern)+ 184 more | - | +| | [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_flyout.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_flyout.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [discover_grid_context.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_context.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [get_render_cell_value.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/get_render_cell_value.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern), [discover_grid_columns.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx#:~:text=IndexPattern)+ 186 more | - | | | [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [popularize_field.test.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/helpers/popularize_field.test.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService), [index_patterns.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/__mocks__/index_patterns.ts#:~:text=IndexPatternsService)+ 6 more | - | | | [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [url_generator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/url_generator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [locator.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/locator.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/types.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=Filter), [discover_state.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/services/discover_state.ts#:~:text=Filter)+ 22 more | 8.1 | | | [discover_main_route.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/discover_main_route.tsx#:~:text=ensureDefaultDataView) | - | | | [on_save_search.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/top_nav/on_save_search.tsx#:~:text=SavedObjectSaveModal), [on_save_search.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/apps/main/components/top_nav/on_save_search.tsx#:~:text=SavedObjectSaveModal) | - | -| | [saved_searches.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/saved_searches/legacy/saved_searches.ts#:~:text=SavedObjectLoader), [saved_searches.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/saved_searches/legacy/saved_searches.ts#:~:text=SavedObjectLoader), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=SavedObjectLoader), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=SavedObjectLoader) | - | -| | [_saved_search.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/saved_searches/legacy/_saved_search.ts#:~:text=SavedObject), [_saved_search.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/saved_searches/legacy/_saved_search.ts#:~:text=SavedObject) | - | -| | [_saved_search.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/saved_searches/legacy/_saved_search.ts#:~:text=SavedObjectClass) | - | | | [saved_search_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx#:~:text=executeTriggerActions), [search_embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/application/embeddable/search_embeddable_factory.ts#:~:text=executeTriggerActions), [plugin.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/discover/public/plugin.tsx#:~:text=executeTriggerActions), [search_embeddable_factory.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/target/types/public/application/embeddable/search_embeddable_factory.d.ts#:~:text=executeTriggerActions) | - | -| | [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric) | - | -| | [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric) | - | +| | [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric) | - | +| | [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric), [ui_settings.ts](https://github.com/elastic/kibana/tree/master/src/plugins/discover/server/ui_settings.ts#:~:text=metric) | - | @@ -443,7 +439,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IFieldType), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IFieldType), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IFieldType), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IFieldType) | 8.1 | | | [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IndexPatternListItem), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IndexPatternListItem), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IndexPatternListItem), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IndexPatternListItem), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IndexPatternListItem), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IndexPatternListItem), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IndexPatternListItem), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IndexPatternListItem) | - | | | [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/constants/index.ts#:~:text=getKbnTypeNames), [index.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/constants/index.ts#:~:text=getKbnTypeNames) | 8.1 | -| | [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=indexPatterns), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=indexPatterns), [edit_index_pattern_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_container.tsx#:~:text=indexPatterns), [edit_index_pattern_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_container.tsx#:~:text=indexPatterns), [create_edit_field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx#:~:text=indexPatterns), [create_edit_field_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx#:~:text=indexPatterns), [create_edit_field_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx#:~:text=indexPatterns) | - | +| | [scripted_fields_table.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/scripted_fields_table.tsx#:~:text=indexPatterns), [tabs.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/tabs/tabs.tsx#:~:text=indexPatterns), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=indexPatterns), [edit_index_pattern.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern.tsx#:~:text=indexPatterns), [edit_index_pattern_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_container.tsx#:~:text=indexPatterns), [edit_index_pattern_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/edit_index_pattern_container.tsx#:~:text=indexPatterns), [create_edit_field.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field.tsx#:~:text=indexPatterns), [create_edit_field_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx#:~:text=indexPatterns), [create_edit_field_container.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/edit_index_pattern/create_edit_field/create_edit_field_container.tsx#:~:text=indexPatterns) | - | | | [field_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx#:~:text=fieldFormats), [field_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx#:~:text=fieldFormats), [field_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx#:~:text=fieldFormats), [field_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx#:~:text=fieldFormats), [field_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx#:~:text=fieldFormats), [field_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx#:~:text=fieldFormats) | - | | | [test_script.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=esQuery), [test_script.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=esQuery), [test_script.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/field_editor/components/scripting_help/test_script.tsx#:~:text=esQuery) | 8.1 | | | [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IFieldType), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IFieldType), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IFieldType), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IFieldType), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IFieldType), [utils.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/public/components/utils.ts#:~:text=IFieldType), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IFieldType), [utils.d.ts](https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_management/target/types/public/components/utils.d.ts#:~:text=IFieldType) | 8.1 | @@ -541,18 +537,18 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService) | - | -| | [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract)+ 20 more | - | +| | [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract)+ 22 more | - | | | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern)+ 36 more | - | | | [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField)+ 8 more | - | | | [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=indexPatterns), [indexpattern.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx#:~:text=indexPatterns), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=indexPatterns), [lens_top_nav.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/lens_top_nav.tsx#:~:text=indexPatterns), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=indexPatterns), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=indexPatterns) | - | | | [ranges.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/ranges/ranges.tsx#:~:text=fieldFormats), [droppable.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/droppable/droppable.test.ts#:~:text=fieldFormats) | - | -| | [save_modal_container.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx#:~:text=esFilters), [save_modal_container.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx#:~:text=esFilters), [mocks.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/mocks.tsx#:~:text=esFilters), [mocks.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/mocks.tsx#:~:text=esFilters) | 8.1 | +| | [save_modal_container.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx#:~:text=esFilters), [save_modal_container.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/app_plugin/save_modal_container.tsx#:~:text=esFilters), [data_plugin_mock.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/mocks/data_plugin_mock.ts#:~:text=esFilters), [data_plugin_mock.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/mocks/data_plugin_mock.ts#:~:text=esFilters) | 8.1 | | | [validation.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts#:~:text=esKuery), [validation.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts#:~:text=esKuery), [validation.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts#:~:text=esKuery) | 8.1 | | | [validation.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts#:~:text=esQuery), [validation.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/validation.ts#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms/index.tsx#:~:text=esQuery), [field_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#:~:text=esQuery), [field_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#:~:text=esQuery), [field_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#:~:text=esQuery), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=esQuery), [datapanel.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx#:~:text=esQuery)+ 1 more | 8.1 | | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/types.ts#:~:text=Filter), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=Filter), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=Filter), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/state_management/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/state_management/types.ts#:~:text=Filter), [field_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#:~:text=Filter), [field_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#:~:text=Filter)+ 16 more | 8.1 | | | [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/field_stats.d.ts#:~:text=IndexPatternField), [field_stats.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/field_stats.ts#:~:text=IndexPatternField)+ 8 more | - | | | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPatternsService) | - | -| | [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract)+ 20 more | - | +| | [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/utils.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [embeddable_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable_factory.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract), [loader.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts#:~:text=IndexPatternsContract)+ 22 more | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=ensureDefaultDataView), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/plugin.ts#:~:text=ensureDefaultDataView) | - | | | [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/server/routes/existing_fields.test.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [existing_fields.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/target/types/server/routes/existing_fields.d.ts#:~:text=IndexPattern), [loader.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/loader.ts#:~:text=IndexPattern), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=IndexPattern)+ 36 more | - | | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/types.ts#:~:text=Filter), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=Filter), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=Filter), [embeddable.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/embeddable/embeddable.tsx#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/state_management/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/state_management/types.ts#:~:text=Filter), [field_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#:~:text=Filter), [field_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx#:~:text=Filter)+ 16 more | 8.1 | @@ -608,12 +604,15 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService), [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService) | - | | | [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/lazy_load_bundle/index.ts#:~:text=IndexPatternsContract), [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/lazy_load_bundle/index.ts#:~:text=IndexPatternsContract), [index.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/target/types/public/lazy_load_bundle/index.d.ts#:~:text=IndexPatternsContract), [index.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/target/types/public/lazy_load_bundle/index.d.ts#:~:text=IndexPatternsContract), [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/lazy_load_bundle/index.ts#:~:text=IndexPatternsContract), [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/lazy_load_bundle/index.ts#:~:text=IndexPatternsContract), [index.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/target/types/public/lazy_load_bundle/index.d.ts#:~:text=IndexPatternsContract), [index.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/target/types/public/lazy_load_bundle/index.d.ts#:~:text=IndexPatternsContract) | - | | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=IndexPattern), [es_agg_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts#:~:text=IndexPattern), [es_agg_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts#:~:text=IndexPattern), [agg_field_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/agg_field_types.ts#:~:text=IndexPattern), [agg_field_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/agg_field_types.ts#:~:text=IndexPattern), [percentile_agg_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts#:~:text=IndexPattern), [percentile_agg_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts#:~:text=IndexPattern), [es_geo_grid_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx#:~:text=IndexPattern), [es_geo_grid_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx#:~:text=IndexPattern)+ 206 more | - | +| | [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit) | - | | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/reducers/map/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/reducers/map/types.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [vector_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx#:~:text=Filter), [vector_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx#:~:text=Filter), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=Filter), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=Filter)+ 115 more | 8.1 | | | [es_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_source/es_source.ts#:~:text=fetch), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=fetch), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=fetch) | 8.1 | | | [es_agg_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts#:~:text=IndexPatternField), [es_agg_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts#:~:text=IndexPatternField), [es_agg_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts#:~:text=IndexPatternField), [es_agg_utils.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/target/types/common/elasticsearch_util/es_agg_utils.d.ts#:~:text=IndexPatternField), [es_agg_utils.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/target/types/common/elasticsearch_util/es_agg_utils.d.ts#:~:text=IndexPatternField), [es_agg_utils.d.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/target/types/common/elasticsearch_util/es_agg_utils.d.ts#:~:text=IndexPatternField), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=IndexPatternField), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=IndexPatternField), [es_doc_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts#:~:text=IndexPatternField), [es_doc_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/es_doc_field.ts#:~:text=IndexPatternField)+ 129 more | - | | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/embeddable/types.ts#:~:text=IndexPattern), [es_agg_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts#:~:text=IndexPattern), [es_agg_utils.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts#:~:text=IndexPattern), [agg_field_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/agg_field_types.ts#:~:text=IndexPattern), [agg_field_types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/agg_field_types.ts#:~:text=IndexPattern), [percentile_agg_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts#:~:text=IndexPattern), [percentile_agg_field.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/fields/agg/percentile_agg_field.ts#:~:text=IndexPattern), [es_geo_grid_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx#:~:text=IndexPattern), [es_geo_grid_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx#:~:text=IndexPattern)+ 98 more | - | | | [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService), [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService), [create_doc_source.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/create_doc_source.ts#:~:text=IndexPatternsService) | - | +| | [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit) | - | | | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/reducers/map/types.ts#:~:text=Filter), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/reducers/map/types.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/tooltip_property.ts#:~:text=Filter), [vector_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx#:~:text=Filter), [vector_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/vector_source/vector_source.tsx#:~:text=Filter), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=Filter), [es_tooltip_property.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/tooltips/es_tooltip_property.ts#:~:text=Filter)+ 115 more | 8.1 | +| | [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit), [es_search_source.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=flattenHit) | - | | | [kibana_server_services.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/kibana_server_services.ts#:~:text=indexPatternsServiceFactory), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/plugin.ts#:~:text=indexPatternsServiceFactory), [indexing_routes.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/data_indexing/indexing_routes.ts#:~:text=indexPatternsServiceFactory) | - | | | [maps_list_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx#:~:text=settings), [maps_list_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx#:~:text=settings), [maps_list_view.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/public/routes/list_page/maps_list_view.tsx#:~:text=settings) | - | | | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/maps/server/plugin.ts#:~:text=license%24) | - | @@ -683,11 +682,11 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=IndexPattern), [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=IndexPattern), [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern)+ 2 more | - | -| | [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=indexPatterns), [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=indexPatterns) | - | -| | [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=IndexPattern), [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=IndexPattern), [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern)+ 2 more | - | -| | [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_errors.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [use_scheduled_query_group_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/use_scheduled_query_group_query_last_results.ts#:~:text=IndexPattern), [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=IndexPattern), [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=IndexPattern) | - | -| | [scheduled_query_group_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_status_table.tsx#:~:text=urlGenerator), [use_discover_link.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/common/hooks/use_discover_link.tsx#:~:text=urlGenerator) | - | +| | [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=IndexPattern), [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=IndexPattern), [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern)+ 2 more | - | +| | [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=indexPatterns), [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=indexPatterns) | - | +| | [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=IndexPattern), [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=IndexPattern), [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern)+ 2 more | - | +| | [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_errors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_errors.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [use_pack_query_last_results.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/use_pack_query_last_results.ts#:~:text=IndexPattern), [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=IndexPattern), [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=IndexPattern) | - | +| | [pack_queries_status_table.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/packs/pack_queries_status_table.tsx#:~:text=urlGenerator), [use_discover_link.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/osquery/public/common/hooks/use_discover_link.tsx#:~:text=urlGenerator) | - | @@ -704,7 +703,12 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| +| | [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern) | - | +| | [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType) | 8.1 | | | [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=esFilters), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=esFilters) | 8.1 | +| | [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType)+ 10 more | 8.1 | +| | [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IIndexPattern)+ 10 more | - | +| | [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_embeddable.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_embeddable.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType), [options_list_editor.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/controls/control_types/options_list/options_list_editor.tsx#:~:text=IFieldType) | 8.1 | | | [saved_object_save_modal_dashboard.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx#:~:text=SavedObjectSaveModal), [saved_object_save_modal_dashboard.tsx](https://github.com/elastic/kibana/tree/master/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx#:~:text=SavedObjectSaveModal) | - | @@ -826,23 +830,23 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [use_risky_hosts_dashboard_button_href.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_button_href.ts#:~:text=dashboardUrlGenerator), [use_risky_hosts_dashboard_links.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/overview/containers/overview_risky_host_links/use_risky_hosts_dashboard_links.tsx#:~:text=dashboardUrlGenerator), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/index.tsx#:~:text=dashboardUrlGenerator) | - | | | [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [list_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/list_item.tsx#:~:text=IndexPattern), [list_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/list_item.tsx#:~:text=IndexPattern)+ 30 more | - | | | [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField), [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField), [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField), [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField) | - | -| | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [action.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#:~:text=IIndexPattern), [action.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern)+ 74 more | - | +| | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern)+ 74 more | - | | | [middleware.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.ts#:~:text=indexPatterns), [plugin.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/plugin.tsx#:~:text=indexPatterns), [dependencies_start_mock.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/mock/endpoint/dependencies_start_mock.ts#:~:text=indexPatterns) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx#:~:text=esFilters), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters), [epic.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts#:~:text=esFilters)+ 14 more | 8.1 | | | [expandable_network.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/side_panel/network_details/expandable_network.tsx#:~:text=esQuery), [expandable_network.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/side_panel/network_details/expandable_network.tsx#:~:text=esQuery), [events_viewer.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx#:~:text=esQuery), [events_viewer.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_histogram_panel/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/top_n/index.tsx#:~:text=esQuery)+ 30 more | 8.1 | -| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [selectors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts#:~:text=Filter), [selectors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter)+ 163 more | 8.1 | -| | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [action.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#:~:text=IIndexPattern), [action.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/action.ts#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern)+ 158 more | - | +| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx#:~:text=Filter), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx#:~:text=Filter)+ 165 more | 8.1 | +| | [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/types.ts#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/containers/source/index.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/timeline/helpers.tsx#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/url_state/types.ts#:~:text=IIndexPattern)+ 158 more | - | | | [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField), [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField), [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField), [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField) | - | | | [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [list_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/list_item.tsx#:~:text=IndexPattern), [list_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/list_item.tsx#:~:text=IndexPattern)+ 30 more | - | -| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [selectors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts#:~:text=Filter), [selectors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter)+ 163 more | 8.1 | +| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx#:~:text=Filter), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx#:~:text=Filter)+ 165 more | 8.1 | | | [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField), [field_name_cell.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/event_details/table/field_name_cell.tsx#:~:text=IndexPatternField) | - | | | [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/helpers.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [entry_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/entry_item.tsx#:~:text=IndexPattern), [list_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/list_item.tsx#:~:text=IndexPattern), [list_item.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/components/threat_match/list_item.tsx#:~:text=IndexPattern)+ 10 more | - | -| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [selectors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts#:~:text=Filter), [selectors.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/selectors.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter)+ 163 more | 8.1 | +| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/model.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/common/store/inputs/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [actions.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/store/timeline/actions.ts#:~:text=Filter), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx#:~:text=Filter), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx#:~:text=Filter)+ 165 more | 8.1 | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [isolation.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts#:~:text=mode), [isolation.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts#:~:text=mode)+ 4 more | - | | | [policy_config.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [policy_config.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/common/license/policy_config.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [fleet_integration.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [license_watch.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts#:~:text=mode), [isolation.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts#:~:text=mode), [isolation.test.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts#:~:text=mode)+ 4 more | - | -| | [create_signals_migration_route.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts#:~:text=authc), [delete_signals_migration_route.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts#:~:text=authc), [finalize_signals_migration_route.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts#:~:text=authc), [common.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/timeline/utils/common.ts#:~:text=authc) | - | -| | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/plugin.ts#:~:text=spacesService), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/plugin.ts#:~:text=spacesService) | 7.16 | -| | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/plugin.ts#:~:text=getSpaceId), [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/plugin.ts#:~:text=getSpaceId) | 7.16 | +| | [create_signals_migration_route.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/create_signals_migration_route.ts#:~:text=authc), [delete_signals_migration_route.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/delete_signals_migration_route.ts#:~:text=authc), [finalize_signals_migration_route.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/finalize_signals_migration_route.ts#:~:text=authc), [preview_rules_route.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/preview_rules_route.ts#:~:text=authc), [request_context_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=authc), [common.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/lib/timeline/utils/common.ts#:~:text=authc) | - | +| | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/plugin.ts#:~:text=spacesService), [request_context_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=spacesService), [request_context_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=spacesService) | 7.16 | +| | [plugin.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/plugin.ts#:~:text=getSpaceId), [request_context_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=getSpaceId), [request_context_factory.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/server/request_context_factory.ts#:~:text=getSpaceId) | 7.16 | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/index.tsx#:~:text=onAppLeave) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/timelines/components/flyout/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/home/template_wrapper/bottom_bar/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/home/template_wrapper/bottom_bar/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/home/template_wrapper/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/home/index.tsx#:~:text=AppLeaveHandler), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/home/index.tsx#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler), [routes.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/security_solution/public/app/routes.tsx#:~:text=AppLeaveHandler)+ 3 more | - | @@ -894,11 +898,11 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=IIndexPattern), [index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=IIndexPattern), [index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=IIndexPattern) | - | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/columns/index.tsx#:~:text=IFieldSubType), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/columns/index.tsx#:~:text=IFieldSubType) | 8.1 | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=esQuery), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=esQuery) | 8.1 | -| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=Filter)+ 5 more | 8.1 | +| | [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/cells/index.ts#:~:text=Filter), [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/cells/index.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter)+ 5 more | 8.1 | | | [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=IIndexPattern), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/container/source/index.tsx#:~:text=IIndexPattern), [index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=IIndexPattern), [index_pattern.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/mock/index_pattern.ts#:~:text=IIndexPattern), [helpers.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx#:~:text=IIndexPattern)+ 8 more | - | -| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=Filter)+ 5 more | 8.1 | +| | [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/cells/index.ts#:~:text=Filter), [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/cells/index.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter)+ 5 more | 8.1 | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/columns/index.tsx#:~:text=IFieldSubType), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/columns/index.tsx#:~:text=IFieldSubType) | 8.1 | -| | [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx#:~:text=Filter)+ 5 more | 8.1 | +| | [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/cells/index.ts#:~:text=Filter), [index.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/cells/index.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [store.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/store.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [model.ts](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/store/t_grid/model.ts#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx#:~:text=Filter)+ 5 more | 8.1 | | | [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/columns/index.tsx#:~:text=IFieldSubType), [index.tsx](https://github.com/elastic/kibana/tree/master/x-pack/plugins/timelines/common/types/timeline/columns/index.tsx#:~:text=IFieldSubType) | 8.1 | @@ -1073,23 +1077,16 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| -| | [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract) | - | | | [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern)+ 10 more | - | | | [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=toJSON) | 8.1 | -| | [plugin.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/plugin.ts#:~:text=indexPatterns) | - | | | [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=esFilters), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=esFilters) | 8.1 | | | [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter) | 8.1 | | | [controls_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [controls_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [timeseries_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [timeseries_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/timeseries_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [visualization_saved_object_migrations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/server/migrations/visualization_saved_object_migrations.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE), [controls_references.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/utils/saved_visualization_references/controls_references.ts#:~:text=INDEX_PATTERN_SAVED_OBJECT_TYPE)+ 8 more | - | -| | [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=IndexPatternsContract) | - | | | [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern)+ 10 more | - | | | [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter) | 8.1 | | | [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=toJSON) | 8.1 | | | [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [types.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/vis_types/types.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [create_vis_embeddable_from_object.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/create_vis_embeddable_from_object.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=IndexPattern) | - | | | [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter), [visualize_embeddable.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts#:~:text=Filter) | 8.1 | -| | [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=__LEGACY), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=__LEGACY) | - | -| | [find_list_items.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/find_list_items.ts#:~:text=SavedObjectLoader), [find_list_items.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/find_list_items.ts#:~:text=SavedObjectLoader), [saved_visualizations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts#:~:text=SavedObjectLoader), [saved_visualizations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts#:~:text=SavedObjectLoader), [saved_visualizations.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/saved_visualizations.ts#:~:text=SavedObjectLoader) | - | -| | [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=SavedObject), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=SavedObject), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=SavedObject), [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=SavedObject) | - | -| | [_saved_vis.ts](https://github.com/elastic/kibana/tree/master/src/plugins/visualizations/public/saved_visualizations/_saved_vis.ts#:~:text=SavedObjectClass) | - | diff --git a/api_docs/elastic_apm_generator.json b/api_docs/elastic_apm_generator.json deleted file mode 100644 index 24f11791d92b6..0000000000000 --- a/api_docs/elastic_apm_generator.json +++ /dev/null @@ -1,288 +0,0 @@ -{ - "id": "@elastic/apm-generator", - "client": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "server": { - "classes": [], - "functions": [ - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.getBreakdownMetrics", - "type": "Function", - "tags": [], - "label": "getBreakdownMetrics", - "description": [], - "signature": [ - "(events: Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]) => Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]" - ], - "path": "packages/elastic-apm-generator/src/lib/utils/get_breakdown_metrics.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.getBreakdownMetrics.$1", - "type": "Array", - "tags": [], - "label": "events", - "description": [], - "signature": [ - "Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]" - ], - "path": "packages/elastic-apm-generator/src/lib/utils/get_breakdown_metrics.ts", - "deprecated": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.getObserverDefaults", - "type": "Function", - "tags": [], - "label": "getObserverDefaults", - "description": [], - "signature": [ - "() => Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>" - ], - "path": "packages/elastic-apm-generator/src/lib/defaults/get_observer_defaults.ts", - "deprecated": false, - "children": [], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.getSpanDestinationMetrics", - "type": "Function", - "tags": [], - "label": "getSpanDestinationMetrics", - "description": [], - "signature": [ - "(events: Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]) => { \"metricset.name\": string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; '@timestamp'?: number | undefined; 'agent.name'?: string | undefined; 'agent.version'?: string | undefined; 'container.id'?: string | undefined; 'ecs.version'?: string | undefined; 'event.outcome'?: string | undefined; 'event.ingested'?: number | undefined; 'host.name'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.duration.histogram'?: { values: number[]; counts: number[]; } | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; }[]" - ], - "path": "packages/elastic-apm-generator/src/lib/utils/get_span_destination_metrics.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.getSpanDestinationMetrics.$1", - "type": "Array", - "tags": [], - "label": "events", - "description": [], - "signature": [ - "Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]" - ], - "path": "packages/elastic-apm-generator/src/lib/utils/get_span_destination_metrics.ts", - "deprecated": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.getTransactionMetrics", - "type": "Function", - "tags": [], - "label": "getTransactionMetrics", - "description": [], - "signature": [ - "(events: Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]) => { 'transaction.duration.histogram': { values: number[]; counts: number[]; }; _doc_count: number; '@timestamp'?: number | undefined; 'agent.name'?: string | undefined; 'agent.version'?: string | undefined; 'container.id'?: string | undefined; 'ecs.version'?: string | undefined; 'event.outcome'?: string | undefined; 'event.ingested'?: number | undefined; 'host.name'?: string | undefined; 'metricset.name'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.destination.service.response_time.sum.us'?: number | undefined; 'span.destination.service.response_time.count'?: number | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; }[]" - ], - "path": "packages/elastic-apm-generator/src/lib/utils/get_transaction_metrics.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.getTransactionMetrics.$1", - "type": "Array", - "tags": [], - "label": "events", - "description": [], - "signature": [ - "Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]" - ], - "path": "packages/elastic-apm-generator/src/lib/utils/get_transaction_metrics.ts", - "deprecated": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.service", - "type": "Function", - "tags": [], - "label": "service", - "description": [], - "signature": [ - "(name: string, environment: string, agentName: string) => ", - "Service" - ], - "path": "packages/elastic-apm-generator/src/lib/service.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.service.$1", - "type": "string", - "tags": [], - "label": "name", - "description": [], - "signature": [ - "string" - ], - "path": "packages/elastic-apm-generator/src/lib/service.ts", - "deprecated": false, - "isRequired": true - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.service.$2", - "type": "string", - "tags": [], - "label": "environment", - "description": [], - "signature": [ - "string" - ], - "path": "packages/elastic-apm-generator/src/lib/service.ts", - "deprecated": false, - "isRequired": true - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.service.$3", - "type": "string", - "tags": [], - "label": "agentName", - "description": [], - "signature": [ - "string" - ], - "path": "packages/elastic-apm-generator/src/lib/service.ts", - "deprecated": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.timerange", - "type": "Function", - "tags": [], - "label": "timerange", - "description": [], - "signature": [ - "(from: number, to: number) => ", - "Timerange" - ], - "path": "packages/elastic-apm-generator/src/lib/timerange.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.timerange.$1", - "type": "number", - "tags": [], - "label": "from", - "description": [], - "signature": [ - "number" - ], - "path": "packages/elastic-apm-generator/src/lib/timerange.ts", - "deprecated": false, - "isRequired": true - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.timerange.$2", - "type": "number", - "tags": [], - "label": "to", - "description": [], - "signature": [ - "number" - ], - "path": "packages/elastic-apm-generator/src/lib/timerange.ts", - "deprecated": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.toElasticsearchOutput", - "type": "Function", - "tags": [], - "label": "toElasticsearchOutput", - "description": [], - "signature": [ - "(events: Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[], versionOverride: string | undefined) => { _index: string; _source: {}; }[]" - ], - "path": "packages/elastic-apm-generator/src/lib/output/to_elasticsearch_output.ts", - "deprecated": false, - "children": [ - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.toElasticsearchOutput.$1", - "type": "Array", - "tags": [], - "label": "events", - "description": [], - "signature": [ - "Partial<{ '@timestamp': number; 'agent.name': string; 'agent.version': string; 'container.id': string; 'ecs.version': string; 'event.outcome': string; 'event.ingested': number; 'host.name': string; 'metricset.name': string; 'observer.version': string; 'observer.version_major': number; 'parent.id': string; 'processor.event': string; 'processor.name': string; 'trace.id': string; 'transaction.name': string; 'transaction.type': string; 'transaction.id': string; 'transaction.duration.us': number; 'transaction.duration.histogram': { values: number[]; counts: number[]; }; 'transaction.sampled': true; 'service.name': string; 'service.environment': string; 'service.node.name': string; 'span.id': string; 'span.name': string; 'span.type': string; 'span.subtype': string; 'span.duration.us': number; 'span.destination.service.name': string; 'span.destination.service.resource': string; 'span.destination.service.type': string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; 'span.self_time.count': number; 'span.self_time.sum.us': number; }>[]" - ], - "path": "packages/elastic-apm-generator/src/lib/output/to_elasticsearch_output.ts", - "deprecated": false, - "isRequired": true - }, - { - "parentPluginId": "@elastic/apm-generator", - "id": "def-server.toElasticsearchOutput.$2", - "type": "string", - "tags": [], - "label": "versionOverride", - "description": [], - "signature": [ - "string | undefined" - ], - "path": "packages/elastic-apm-generator/src/lib/output/to_elasticsearch_output.ts", - "deprecated": false, - "isRequired": false - } - ], - "returnComment": [], - "initialIsOpen": false - } - ], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - } -} \ No newline at end of file diff --git a/api_docs/elastic_apm_synthtrace.json b/api_docs/elastic_apm_synthtrace.json new file mode 100644 index 0000000000000..13d950c53a8df --- /dev/null +++ b/api_docs/elastic_apm_synthtrace.json @@ -0,0 +1,321 @@ +{ + "id": "@elastic/apm-synthtrace", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.getBreakdownMetrics", + "type": "Function", + "tags": [], + "label": "getBreakdownMetrics", + "description": [], + "signature": [ + "(events: ", + "Fields", + "[]) => ", + "Fields", + "[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/utils/get_breakdown_metrics.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.getBreakdownMetrics.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [], + "signature": [ + "Fields", + "[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/utils/get_breakdown_metrics.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.getObserverDefaults", + "type": "Function", + "tags": [], + "label": "getObserverDefaults", + "description": [], + "signature": [ + "() => ", + "Fields" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/defaults/get_observer_defaults.ts", + "deprecated": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.getSpanDestinationMetrics", + "type": "Function", + "tags": [], + "label": "getSpanDestinationMetrics", + "description": [], + "signature": [ + "(events: ", + "Fields", + "[]) => { \"metricset.name\": string; 'span.destination.service.response_time.sum.us': number; 'span.destination.service.response_time.count': number; '@timestamp'?: number | undefined; 'agent.name'?: string | undefined; 'agent.version'?: string | undefined; 'container.id'?: string | undefined; 'ecs.version'?: string | undefined; 'event.outcome'?: string | undefined; 'event.ingested'?: number | undefined; 'error.id'?: string | undefined; 'error.exception'?: ", + "Exception", + "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.duration.histogram'?: { values: number[]; counts: number[]; } | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; }[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/utils/get_span_destination_metrics.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.getSpanDestinationMetrics.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [], + "signature": [ + "Fields", + "[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/utils/get_span_destination_metrics.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.getTransactionMetrics", + "type": "Function", + "tags": [], + "label": "getTransactionMetrics", + "description": [], + "signature": [ + "(events: ", + "Fields", + "[]) => { 'transaction.duration.histogram': { values: number[]; counts: number[]; }; _doc_count: number; '@timestamp'?: number | undefined; 'agent.name'?: string | undefined; 'agent.version'?: string | undefined; 'container.id'?: string | undefined; 'ecs.version'?: string | undefined; 'event.outcome'?: string | undefined; 'event.ingested'?: number | undefined; 'error.id'?: string | undefined; 'error.exception'?: ", + "Exception", + "[] | undefined; 'error.grouping_name'?: string | undefined; 'error.grouping_key'?: string | undefined; 'host.name'?: string | undefined; 'metricset.name'?: string | undefined; 'observer.version'?: string | undefined; 'observer.version_major'?: number | undefined; 'parent.id'?: string | undefined; 'processor.event'?: string | undefined; 'processor.name'?: string | undefined; 'trace.id'?: string | undefined; 'transaction.name'?: string | undefined; 'transaction.type'?: string | undefined; 'transaction.id'?: string | undefined; 'transaction.duration.us'?: number | undefined; 'transaction.sampled'?: true | undefined; 'service.name'?: string | undefined; 'service.environment'?: string | undefined; 'service.node.name'?: string | undefined; 'span.id'?: string | undefined; 'span.name'?: string | undefined; 'span.type'?: string | undefined; 'span.subtype'?: string | undefined; 'span.duration.us'?: number | undefined; 'span.destination.service.name'?: string | undefined; 'span.destination.service.resource'?: string | undefined; 'span.destination.service.type'?: string | undefined; 'span.destination.service.response_time.sum.us'?: number | undefined; 'span.destination.service.response_time.count'?: number | undefined; 'span.self_time.count'?: number | undefined; 'span.self_time.sum.us'?: number | undefined; 'system.process.memory.size'?: number | undefined; 'system.memory.actual.free'?: number | undefined; 'system.memory.total'?: number | undefined; 'system.cpu.total.norm.pct'?: number | undefined; 'system.process.memory.rss.bytes'?: number | undefined; 'system.process.cpu.total.norm.pct'?: number | undefined; }[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/utils/get_transaction_metrics.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.getTransactionMetrics.$1", + "type": "Array", + "tags": [], + "label": "events", + "description": [], + "signature": [ + "Fields", + "[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/utils/get_transaction_metrics.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.service", + "type": "Function", + "tags": [], + "label": "service", + "description": [], + "signature": [ + "(name: string, environment: string, agentName: string) => ", + "Service" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/service.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.service.$1", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "signature": [ + "string" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/service.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.service.$2", + "type": "string", + "tags": [], + "label": "environment", + "description": [], + "signature": [ + "string" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/service.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.service.$3", + "type": "string", + "tags": [], + "label": "agentName", + "description": [], + "signature": [ + "string" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/service.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.timerange", + "type": "Function", + "tags": [], + "label": "timerange", + "description": [], + "signature": [ + "(from: number, to: number) => ", + "Timerange" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/timerange.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.timerange.$1", + "type": "number", + "tags": [], + "label": "from", + "description": [], + "signature": [ + "number" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/timerange.ts", + "deprecated": false, + "isRequired": true + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.timerange.$2", + "type": "number", + "tags": [], + "label": "to", + "description": [], + "signature": [ + "number" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/timerange.ts", + "deprecated": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.toElasticsearchOutput", + "type": "Function", + "tags": [], + "label": "toElasticsearchOutput", + "description": [], + "signature": [ + "({\n events,\n writeTargets,\n}: { events: ", + "Fields", + "[]; writeTargets: ", + "ElasticsearchOutputWriteTargets", + "; }) => ", + "ElasticsearchOutput", + "[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.toElasticsearchOutput.$1", + "type": "Object", + "tags": [], + "label": "{\n events,\n writeTargets,\n}", + "description": [], + "path": "packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts", + "deprecated": false, + "children": [ + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.toElasticsearchOutput.$1.events", + "type": "Array", + "tags": [], + "label": "events", + "description": [], + "signature": [ + "Fields", + "[]" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts", + "deprecated": false + }, + { + "parentPluginId": "@elastic/apm-synthtrace", + "id": "def-server.toElasticsearchOutput.$1.writeTargets", + "type": "Object", + "tags": [], + "label": "writeTargets", + "description": [], + "signature": [ + "ElasticsearchOutputWriteTargets" + ], + "path": "packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts", + "deprecated": false + } + ] + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/elastic_apm_generator.mdx b/api_docs/elastic_apm_synthtrace.mdx similarity index 63% rename from api_docs/elastic_apm_generator.mdx rename to api_docs/elastic_apm_synthtrace.mdx index 4c95050b09c28..b41afe6c7357c 100644 --- a/api_docs/elastic_apm_generator.mdx +++ b/api_docs/elastic_apm_synthtrace.mdx @@ -1,14 +1,14 @@ --- -id: kibElasticApmGeneratorPluginApi -slug: /kibana-dev-docs/api/elastic-apm-generator -title: "@elastic/apm-generator" +id: kibElasticApmSynthtracePluginApi +slug: /kibana-dev-docs/api/elastic-apm-synthtrace +title: "@elastic/apm-synthtrace" image: https://source.unsplash.com/400x175/?github -summary: API docs for the @elastic/apm-generator plugin +summary: API docs for the @elastic/apm-synthtrace plugin date: 2020-11-16 -tags: ['contributor', 'dev', 'apidocs', 'kibana', '@elastic/apm-generator'] +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@elastic/apm-synthtrace'] warning: This document is auto-generated and is meant to be viewed inside our experimental, new docs system. Reach out in #docs-engineering for more info. --- -import elasticApmGeneratorObj from './elastic_apm_generator.json'; +import elasticApmSynthtraceObj from './elastic_apm_synthtrace.json'; Elastic APM trace data generator @@ -18,10 +18,10 @@ Contact [Owner missing] for questions regarding this plugin. | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 17 | 0 | 17 | 2 | +| 18 | 0 | 18 | 6 | ## Server ### Functions - + diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 19e3bc08a5361..d23a52b07a1e3 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -18,7 +18,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 24459 | 276 | 19826 | 1583 | +| 24503 | 264 | 19863 | 1594 | ## Plugin Directory @@ -26,7 +26,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex |--------------|----------------|-----------|--------------|----------|---------------|--------| | | [Kibana Alerting](https://github.com/orgs/elastic/teams/kibana-alerting-services) | - | 125 | 0 | 125 | 8 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 23 | 0 | 22 | 1 | -| | [Kibana Alerting](https://github.com/orgs/elastic/teams/kibana-alerting-services) | - | 257 | 0 | 249 | 17 | +| | [Kibana Alerting](https://github.com/orgs/elastic/teams/kibana-alerting-services) | - | 258 | 0 | 250 | 17 | | | [APM UI](https://github.com/orgs/elastic/teams/apm-ui) | The user interface for Elastic APM | 39 | 0 | 39 | 37 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 9 | 0 | 9 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Considering using bfetch capabilities when fetching large amounts of data. This services supports batching HTTP requests and streaming responses back. | 76 | 1 | 67 | 2 | @@ -34,18 +34,18 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Security Solution Threat Hunting](https://github.com/orgs/elastic/teams/security-threat-hunting) | The Case management system in Kibana | 476 | 0 | 432 | 14 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 285 | 4 | 253 | 3 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 22 | 0 | 22 | 0 | -| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 9 | 0 | 9 | 1 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2298 | 27 | 1018 | 29 | +| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 13 | 0 | 13 | 1 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 2304 | 27 | 1023 | 29 | | crossClusterReplication | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 91 | 1 | 75 | 1 | -| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 145 | 1 | 132 | 10 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | Add custom data integrations so they can be displayed in the Fleet integrations app | 100 | 1 | 84 | 1 | +| | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds the Dashboard app to Kibana | 147 | 1 | 134 | 10 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 51 | 0 | 50 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3193 | 43 | 2807 | 48 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 3238 | 40 | 2848 | 48 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Enhanced data plugin. (See src/plugins/data.) Enhances the main data plugin with a search session management UI. Includes a reusable search session indicator component to use in other applications. Exposes routes for managing search sessions. Includes a service that monitors, updates, and cleans up search session saved objects. | 16 | 0 | 16 | 2 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 683 | 6 | 541 | 5 | -| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 80 | 5 | 80 | 0 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Data services are useful for searching and querying data from Elasticsearch. Helpful utilities include: a re-usable react query bar, KQL autocomplete, async search, Data Views (Index Patterns) and field formatters. | 668 | 5 | 526 | 5 | +| | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index. | 84 | 5 | 84 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 10 | 0 | 8 | 2 | -| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 103 | 0 | 77 | 7 | +| | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the Discover application and the saved search embeddable. | 84 | 0 | 58 | 7 | | | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 37 | 0 | 35 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds embeddables service to Kibana | 469 | 5 | 393 | 3 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Extends embeddable plugin with more functionality | 14 | 0 | 14 | 0 | @@ -61,17 +61,17 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'revealImage' function and renderer to expressions | 12 | 0 | 12 | 3 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds 'shape' function and renderer to expressions | 143 | 0 | 143 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Expression Tagcloud plugin adds a `tagcloud` renderer and function to the expression plugin. The renderer will display the `Wordcloud` chart. | 5 | 0 | 5 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds expression runtime to Kibana | 2086 | 27 | 1640 | 4 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds expression runtime to Kibana | 2092 | 27 | 1646 | 3 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 216 | 0 | 98 | 2 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 288 | 7 | 250 | 3 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Index pattern fields and ambiguous values formatters | 284 | 7 | 246 | 3 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 129 | 4 | 129 | 1 | -| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1210 | 15 | 1110 | 10 | +| | [Fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1225 | 15 | 1122 | 10 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 68 | 0 | 14 | 5 | | globalSearchBar | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | globalSearchProviders | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 0 | 0 | 0 | 0 | | graph | [Data Discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 0 | 0 | 0 | 0 | | grokdebugger | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | -| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 99 | 3 | 77 | 5 | +| | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 96 | 2 | 74 | 5 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 4 | 0 | 4 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 169 | 9 | 164 | 3 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | This plugin provides the ability to create index patterns via a modal flyout from any kibana app | 13 | 1 | 8 | 0 | @@ -82,16 +82,16 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | inputControlVis | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds Input Control visualization to Kibana | 0 | 0 | 0 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 123 | 6 | 96 | 4 | | | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides UI and APIs for the interactive setup mode. | 26 | 0 | 16 | 0 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 48 | 1 | 45 | 0 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 12 | 0 | 9 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 6 | 0 | 6 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 297 | 8 | 260 | 5 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 282 | 2 | 245 | 5 | | kibanaUsageCollection | [Kibana Telemtry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 0 | 0 | 0 | 0 | -| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 606 | 3 | 413 | 8 | +| | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 607 | 3 | 414 | 8 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana. | 253 | 0 | 235 | 24 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 8 | 0 | 8 | 0 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 3 | 0 | 3 | 0 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 117 | 0 | 42 | 8 | -| | [Security detections response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 150 | 0 | 143 | 38 | +| | [Security detections response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 155 | 0 | 148 | 39 | | logstash | [Logstash](https://github.com/orgs/elastic/teams/logstash) | - | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | - | 40 | 0 | 40 | 5 | | | [GIS](https://github.com/orgs/elastic/teams/kibana-gis) | - | 202 | 0 | 201 | 29 | @@ -101,14 +101,14 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Stack Monitoring](https://github.com/orgs/elastic/teams/stack-monitoring-ui) | - | 10 | 0 | 10 | 2 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 31 | 0 | 31 | 2 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | -| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 258 | 1 | 257 | 12 | -| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 11 | 0 | 11 | 0 | +| | [Observability UI](https://github.com/orgs/elastic/teams/observability-ui) | - | 268 | 1 | 267 | 15 | +| | [Security asset management](https://github.com/orgs/elastic/teams/security-asset-management) | - | 10 | 0 | 10 | 0 | | painlessLab | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | | | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). | 178 | 3 | 151 | 6 | | | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 4 | 0 | 4 | 0 | -| | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 135 | 0 | 134 | 12 | -| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 20 | 0 | 20 | 0 | -| | [RAC](https://github.com/orgs/elastic/teams/rac) | - | 136 | 0 | 113 | 7 | +| | [Kibana Reporting Services](https://github.com/orgs/elastic/teams/kibana-reporting-services) | Reporting Services enables applications to feature reports that the user can automate with Watcher and download later. | 137 | 0 | 136 | 12 | +| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 21 | 0 | 21 | 0 | +| | [RAC](https://github.com/orgs/elastic/teams/rac) | - | 151 | 0 | 128 | 7 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 24 | 0 | 19 | 2 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 221 | 3 | 207 | 4 | | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 103 | 0 | 90 | 0 | @@ -116,18 +116,18 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Kibana Core](https://github.com/orgs/elastic/teams/kibana-core) | - | 90 | 3 | 51 | 0 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | - | 22 | 0 | 17 | 1 | | searchprofiler | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | -| | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 113 | 0 | 51 | 7 | -| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 1361 | 8 | 1307 | 30 | +| | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 116 | 0 | 54 | 8 | +| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 1372 | 8 | 1318 | 33 | | | [App Services](https://github.com/orgs/elastic/teams/kibana-app-services) | Adds URL Service and sharing capabilities to Kibana | 143 | 1 | 90 | 10 | -| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 23 | 1 | 22 | 1 | +| | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 23 | 1 | 23 | 1 | | | [Platform Security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides the Spaces feature, which allows saved objects to be organized into meaningful categories. | 208 | 0 | 21 | 1 | | | [Kibana Alerting](https://github.com/orgs/elastic/teams/kibana-alerting-services) | - | 4 | 0 | 4 | 0 | | | [Kibana Alerting](https://github.com/orgs/elastic/teams/kibana-alerting-services) | - | 70 | 0 | 32 | 7 | | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 41 | 0 | 0 | 0 | -| | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 36 | 0 | 36 | 4 | +| | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 32 | 0 | 32 | 5 | | | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 1 | 0 | 1 | 0 | -| | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 14 | 0 | 13 | 0 | -| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 968 | 6 | 847 | 25 | +| | [Kibana Telemetry](https://github.com/orgs/elastic/teams/kibana-telemetry) | - | 11 | 0 | 10 | 0 | +| | [Security solution](https://github.com/orgs/elastic/teams/security-solution) | - | 969 | 6 | 848 | 25 | | | [Machine Learning UI](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics. | 4 | 0 | 4 | 1 | | translations | [Kibana Localization](https://github.com/orgs/elastic/teams/kibana-localization) | - | 0 | 0 | 0 | 0 | | | [Kibana Alerting](https://github.com/orgs/elastic/teams/kibana-alerting-services) | - | 238 | 1 | 229 | 18 | @@ -142,14 +142,14 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | visTypeMarkdown | [Kibana Presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | Adds a markdown visualization type | 0 | 0 | 0 | 0 | | visTypeMetric | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the Metric aggregation-based visualization. | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the pie chart implementation using the elastic-charts library. The goal is to eventually deprecate the old implementation and keep only this. Until then, the library used is defined by the Legacy charts library advanced setting. | 12 | 0 | 12 | 2 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the datatable aggregation-based visualization. | 11 | 0 | 11 | 0 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the datatable aggregation-based visualization. | 12 | 0 | 12 | 0 | | visTypeTagcloud | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the tagcloud visualization. It is based on elastic-charts wordcloud. | 0 | 0 | 0 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the timelion visualization. Also contains the backend for both timelion app and timelion visualization. | 2 | 0 | 2 | 2 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the TSVB visualization. TSVB has its one editor, works with index patterns and index strings and contains 6 types of charts: timeseries, topN, table. markdown, metric and gauge. | 10 | 1 | 10 | 3 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Registers the vega visualization. Is the elastic version of vega and vega-lite libraries. | 2 | 0 | 2 | 0 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the vislib visualizations. These are the classical area/line/bar, pie, gauge/goal and heatmap charts. We want to replace them with elastic-charts. | 26 | 0 | 25 | 1 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the new xy-axis chart using the elastic-charts library, which will eventually replace the vislib xy-axis charts including bar, area, and line. | 57 | 0 | 51 | 5 | -| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 304 | 13 | 286 | 16 | +| | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the shared architecture among all the legacy visualizations, e.g. the visualization type registry or the visualization embeddable. | 303 | 13 | 285 | 15 | | | [Vis Editors](https://github.com/orgs/elastic/teams/kibana-vis-editors) | Contains the visualize application which includes the listing page and the app frame, which will load the visualization's editor. | 24 | 0 | 23 | 1 | | watcher | [Stack Management](https://github.com/orgs/elastic/teams/kibana-stack-management) | - | 0 | 0 | 0 | 0 | @@ -157,7 +157,7 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | Package name           | Maintaining team | Description | API Cnt | Any Cnt | Missing
comments | Missing
exports | |--------------|----------------|-----------|--------------|----------|---------------|--------| -| | [Owner missing] | Elastic APM trace data generator | 17 | 0 | 17 | 2 | +| | [Owner missing] | Elastic APM trace data generator | 18 | 0 | 18 | 6 | | | [Owner missing] | elasticsearch datemath parser, used in kibana | 44 | 0 | 43 | 0 | | | [Owner missing] | - | 11 | 5 | 11 | 0 | | | [Owner missing] | Alerts components and hooks | 9 | 1 | 9 | 0 | @@ -187,13 +187,13 @@ warning: This document is auto-generated and is meant to be viewed inside our ex | | [Owner missing] | security solution elastic search utilities to use across plugins such lists, security_solution, cases, etc... | 54 | 0 | 51 | 0 | | | [Owner missing] | Security Solution utilities for React hooks | 8 | 0 | 1 | 1 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 147 | 1 | 128 | 0 | -| | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 418 | 1 | 409 | 0 | +| | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 419 | 1 | 410 | 0 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 45 | 0 | 23 | 0 | | | [Owner missing] | io ts utilities and types to be shared with plugins from the security solution project | 28 | 0 | 22 | 0 | | | [Owner missing] | security solution list REST API | 42 | 0 | 41 | 5 | | | [Owner missing] | security solution list constants to use across plugins such lists, security_solution, cases, etc... | 23 | 0 | 9 | 0 | | | [Owner missing] | Security solution list ReactJS hooks | 56 | 0 | 44 | 0 | -| | [Owner missing] | security solution list utilities | 222 | 0 | 177 | 0 | +| | [Owner missing] | security solution list utilities | 223 | 0 | 178 | 0 | | | [Owner missing] | security solution t-grid packages will allow sharing components between timelines and security_solution plugin until we transfer all functionality to timelines plugin | 120 | 0 | 116 | 0 | | | [Owner missing] | security solution utilities to use across plugins such lists, security_solution, cases, etc... | 6 | 0 | 4 | 0 | | | [Owner missing] | - | 53 | 0 | 50 | 1 | diff --git a/config/kibana.yml b/config/kibana.yml index 8338a148ef176..eeb7c84df4318 100644 --- a/config/kibana.yml +++ b/config/kibana.yml @@ -31,10 +31,6 @@ # The URLs of the Elasticsearch instances to use for all your queries. #elasticsearch.hosts: ["http://localhost:9200"] -# Kibana uses an index in Elasticsearch to store saved searches, visualizations and -# dashboards. Kibana creates a new index if the index doesn't already exist. -#kibana.index: ".kibana" - # If your Elasticsearch is protected with basic authentication, these settings provide # the username and password that the Kibana server uses to perform maintenance on the Kibana # index at startup. Your Kibana users still need to authenticate with Elasticsearch, which diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md index 01e7beae61ce8..ed6763db69ffe 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.links.md @@ -229,6 +229,7 @@ readonly links: { readonly snapshotRestore: Record; readonly ingest: Record; readonly fleet: Readonly<{ + datastreamsILM: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; diff --git a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md index fdf469f443f28..96c2c0df9d782 100644 --- a/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md +++ b/docs/development/core/public/kibana-plugin-core-public.doclinksstart.md @@ -17,5 +17,5 @@ export interface DocLinksStart | --- | --- | --- | | [DOC\_LINK\_VERSION](./kibana-plugin-core-public.doclinksstart.doc_link_version.md) | string | | | [ELASTIC\_WEBSITE\_URL](./kibana-plugin-core-public.doclinksstart.elastic_website_url.md) | string | | -| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly settings: string;
readonly elasticStackGetStarted: string;
readonly apm: {
readonly kibanaSettings: string;
readonly supportedServiceMaps: string;
readonly customLinks: string;
readonly droppedTransactionSpans: string;
readonly upgrading: string;
readonly metaData: string;
};
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
readonly suricataModule: string;
readonly zeekModule: string;
};
readonly auditbeat: {
readonly base: string;
readonly auditdModule: string;
readonly systemModule: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly libbeat: {
readonly getStarted: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
readonly ruleChangeLog: string;
readonly detectionsReq: string;
readonly networkMap: string;
readonly troubleshootGaps: string;
};
readonly securitySolution: {
readonly trustedApps: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
readonly autocompleteChanges: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Readonly<{
guide: string;
infrastructureThreshold: string;
logsThreshold: string;
metricsThreshold: string;
monitorStatus: string;
monitorUptime: string;
tlsCertificate: string;
uptimeDurationAnomaly: string;
}>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly spaces: Readonly<{
kibanaLegacyUrlAliases: string;
kibanaDisableLegacyUrlAliasesApi: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
installElasticAgent: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
learnMoreBlog: string;
apiKeysLearnMore: string;
}>;
readonly ecs: {
readonly guide: string;
};
readonly clients: {
readonly guide: string;
readonly goOverview: string;
readonly javaIndex: string;
readonly jsIntro: string;
readonly netGuide: string;
readonly perlGuide: string;
readonly phpGuide: string;
readonly pythonGuide: string;
readonly rubyOverview: string;
readonly rustGuide: string;
};
} | | +| [links](./kibana-plugin-core-public.doclinksstart.links.md) | {
readonly settings: string;
readonly elasticStackGetStarted: string;
readonly apm: {
readonly kibanaSettings: string;
readonly supportedServiceMaps: string;
readonly customLinks: string;
readonly droppedTransactionSpans: string;
readonly upgrading: string;
readonly metaData: string;
};
readonly canvas: {
readonly guide: string;
};
readonly dashboard: {
readonly guide: string;
readonly drilldowns: string;
readonly drilldownsTriggerPicker: string;
readonly urlDrilldownTemplateSyntax: string;
readonly urlDrilldownVariables: string;
};
readonly discover: Record<string, string>;
readonly filebeat: {
readonly base: string;
readonly installation: string;
readonly configuration: string;
readonly elasticsearchOutput: string;
readonly elasticsearchModule: string;
readonly startup: string;
readonly exportedFields: string;
readonly suricataModule: string;
readonly zeekModule: string;
};
readonly auditbeat: {
readonly base: string;
readonly auditdModule: string;
readonly systemModule: string;
};
readonly metricbeat: {
readonly base: string;
readonly configure: string;
readonly httpEndpoint: string;
readonly install: string;
readonly start: string;
};
readonly enterpriseSearch: {
readonly base: string;
readonly appSearchBase: string;
readonly workplaceSearchBase: string;
};
readonly heartbeat: {
readonly base: string;
};
readonly libbeat: {
readonly getStarted: string;
};
readonly logstash: {
readonly base: string;
};
readonly functionbeat: {
readonly base: string;
};
readonly winlogbeat: {
readonly base: string;
};
readonly aggs: {
readonly composite: string;
readonly composite_missing_bucket: string;
readonly date_histogram: string;
readonly date_range: string;
readonly date_format_pattern: string;
readonly filter: string;
readonly filters: string;
readonly geohash_grid: string;
readonly histogram: string;
readonly ip_range: string;
readonly range: string;
readonly significant_terms: string;
readonly terms: string;
readonly avg: string;
readonly avg_bucket: string;
readonly max_bucket: string;
readonly min_bucket: string;
readonly sum_bucket: string;
readonly cardinality: string;
readonly count: string;
readonly cumulative_sum: string;
readonly derivative: string;
readonly geo_bounds: string;
readonly geo_centroid: string;
readonly max: string;
readonly median: string;
readonly min: string;
readonly moving_avg: string;
readonly percentile_ranks: string;
readonly serial_diff: string;
readonly std_dev: string;
readonly sum: string;
readonly top_hits: string;
};
readonly runtimeFields: {
readonly overview: string;
readonly mapping: string;
};
readonly scriptedFields: {
readonly scriptFields: string;
readonly scriptAggs: string;
readonly painless: string;
readonly painlessApi: string;
readonly painlessLangSpec: string;
readonly painlessSyntax: string;
readonly painlessWalkthrough: string;
readonly luceneExpressions: string;
};
readonly search: {
readonly sessions: string;
readonly sessionLimits: string;
};
readonly indexPatterns: {
readonly introduction: string;
readonly fieldFormattersNumber: string;
readonly fieldFormattersString: string;
readonly runtimeFields: string;
};
readonly addData: string;
readonly kibana: string;
readonly upgradeAssistant: string;
readonly rollupJobs: string;
readonly elasticsearch: Record<string, string>;
readonly siem: {
readonly privileges: string;
readonly guide: string;
readonly gettingStarted: string;
readonly ml: string;
readonly ruleChangeLog: string;
readonly detectionsReq: string;
readonly networkMap: string;
readonly troubleshootGaps: string;
};
readonly securitySolution: {
readonly trustedApps: string;
};
readonly query: {
readonly eql: string;
readonly kueryQuerySyntax: string;
readonly luceneQuerySyntax: string;
readonly percolate: string;
readonly queryDsl: string;
readonly autocompleteChanges: string;
};
readonly date: {
readonly dateMath: string;
readonly dateMathIndexNames: string;
};
readonly management: Record<string, string>;
readonly ml: Record<string, string>;
readonly transforms: Record<string, string>;
readonly visualize: Record<string, string>;
readonly apis: Readonly<{
bulkIndexAlias: string;
byteSizeUnits: string;
createAutoFollowPattern: string;
createFollower: string;
createIndex: string;
createSnapshotLifecyclePolicy: string;
createRoleMapping: string;
createRoleMappingTemplates: string;
createRollupJobsRequest: string;
createApiKey: string;
createPipeline: string;
createTransformRequest: string;
cronExpressions: string;
executeWatchActionModes: string;
indexExists: string;
openIndex: string;
putComponentTemplate: string;
painlessExecute: string;
painlessExecuteAPIContexts: string;
putComponentTemplateMetadata: string;
putSnapshotLifecyclePolicy: string;
putIndexTemplateV1: string;
putWatch: string;
simulatePipeline: string;
timeUnits: string;
updateTransform: string;
}>;
readonly observability: Readonly<{
guide: string;
infrastructureThreshold: string;
logsThreshold: string;
metricsThreshold: string;
monitorStatus: string;
monitorUptime: string;
tlsCertificate: string;
uptimeDurationAnomaly: string;
}>;
readonly alerting: Record<string, string>;
readonly maps: Record<string, string>;
readonly monitoring: Record<string, string>;
readonly security: Readonly<{
apiKeyServiceSettings: string;
clusterPrivileges: string;
elasticsearchSettings: string;
elasticsearchEnableSecurity: string;
elasticsearchEnableApiKeys: string;
indicesPrivileges: string;
kibanaTLS: string;
kibanaPrivileges: string;
mappingRoles: string;
mappingRolesFieldRules: string;
runAsPrivilege: string;
}>;
readonly spaces: Readonly<{
kibanaLegacyUrlAliases: string;
kibanaDisableLegacyUrlAliasesApi: string;
}>;
readonly watcher: Record<string, string>;
readonly ccs: Record<string, string>;
readonly plugins: Record<string, string>;
readonly snapshotRestore: Record<string, string>;
readonly ingest: Record<string, string>;
readonly fleet: Readonly<{
datastreamsILM: string;
guide: string;
fleetServer: string;
fleetServerAddFleetServer: string;
settings: string;
settingsFleetServerHostSettings: string;
troubleshooting: string;
elasticAgent: string;
datastreams: string;
datastreamsNamingScheme: string;
installElasticAgent: string;
upgradeElasticAgent: string;
upgradeElasticAgent712lower: string;
learnMoreBlog: string;
apiKeysLearnMore: string;
}>;
readonly ecs: {
readonly guide: string;
};
readonly clients: {
readonly guide: string;
readonly goOverview: string;
readonly javaIndex: string;
readonly jsIntro: string;
readonly netGuide: string;
readonly perlGuide: string;
readonly phpGuide: string;
readonly pythonGuide: string;
readonly rubyOverview: string;
readonly rustGuide: string;
};
} | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.getkibanaindex.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.getkibanaindex.md new file mode 100644 index 0000000000000..9319ae987ad44 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.getkibanaindex.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsServiceSetup](./kibana-plugin-core-server.savedobjectsservicesetup.md) > [getKibanaIndex](./kibana-plugin-core-server.savedobjectsservicesetup.getkibanaindex.md) + +## SavedObjectsServiceSetup.getKibanaIndex property + +Returns the default index used for saved objects. + +Signature: + +```typescript +getKibanaIndex: () => string; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md index a1bc99ce8d13d..336d9f63f0ced 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsservicesetup.md @@ -52,6 +52,7 @@ export class Plugin() { | Property | Type | Description | | --- | --- | --- | | [addClientWrapper](./kibana-plugin-core-server.savedobjectsservicesetup.addclientwrapper.md) | (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void | Add a [client wrapper factory](./kibana-plugin-core-server.savedobjectsclientwrapperfactory.md) with the given priority. | +| [getKibanaIndex](./kibana-plugin-core-server.savedobjectsservicesetup.getkibanaindex.md) | () => string | Returns the default index used for saved objects. | | [registerType](./kibana-plugin-core-server.savedobjectsservicesetup.registertype.md) | <Attributes = any>(type: SavedObjectsType<Attributes>) => void | Register a [savedObjects type](./kibana-plugin-core-server.savedobjectstype.md) definition.See the [mappings format](./kibana-plugin-core-server.savedobjectstypemappingdefinition.md) and [migration format](./kibana-plugin-core-server.savedobjectmigrationmap.md) for more details about these. | | [setClientFactoryProvider](./kibana-plugin-core-server.savedobjectsservicesetup.setclientfactoryprovider.md) | (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void | Set the default [factory provider](./kibana-plugin-core-server.savedobjectsclientfactoryprovider.md) for creating Saved Objects clients. Only one provider can be set, subsequent calls to this method will fail. | diff --git a/docs/development/core/server/kibana-plugin-core-server.sharedglobalconfig.md b/docs/development/core/server/kibana-plugin-core-server.sharedglobalconfig.md index ec2e1b227a2d7..477cd5a651a56 100644 --- a/docs/development/core/server/kibana-plugin-core-server.sharedglobalconfig.md +++ b/docs/development/core/server/kibana-plugin-core-server.sharedglobalconfig.md @@ -9,7 +9,6 @@ ```typescript export declare type SharedGlobalConfig = RecursiveReadonly<{ - kibana: Pick; elasticsearch: Pick; path: Pick; savedObjects: Pick; diff --git a/docs/maps/vector-layer.asciidoc b/docs/maps/vector-layer.asciidoc index 7191197c27dbe..f70e4d59796cc 100644 --- a/docs/maps/vector-layer.asciidoc +++ b/docs/maps/vector-layer.asciidoc @@ -27,9 +27,9 @@ Results exceeding `index.max_result_window` are not displayed. * *Show clusters when results exceed 10,000* When results exceed `index.max_result_window`, the layer uses {ref}/search-aggregations-bucket-geotilegrid-aggregation.html[GeoTile grid aggregation] to group your documents into clusters and displays metrics for each cluster. When results are less then `index.max_result_window`, the layer displays features from individual documents. -* *Use vector tiles.* Vector tiles partition your map into 6 to 8 tiles. +* *Use vector tiles.* Vector tiles partition your map into tiles. Each tile request is limited to the `index.max_result_window` index setting. -Tiles exceeding `index.max_result_window` have a visual indicator when there are too many features to display. +When a tile exceeds `index.max_result_window`, results exceeding `index.max_result_window` are not contained in the tile and a dashed rectangle outlining the bounding box containing all geo values within the tile is displayed. *EMS Boundaries*:: Administrative boundaries from https://www.elastic.co/elastic-maps-service[Elastic Maps Service]. diff --git a/docs/settings/security-settings.asciidoc b/docs/settings/security-settings.asciidoc index c291b65c3c35b..7737745c7cfa8 100644 --- a/docs/settings/security-settings.asciidoc +++ b/docs/settings/security-settings.asciidoc @@ -12,20 +12,6 @@ You do not need to configure any additional settings to use the [[general-security-settings]] ==== General security settings -[cols="2*<"] -|=== -| `xpack.security.enabled` - | deprecated:[7.16.0,"In 8.0 and later, this setting will no longer be supported."] - By default, {kib} automatically detects whether to enable the - {security-features} based on the license and whether {es} {security-features} - are enabled. + - + - Do not set this to `false`; it disables the login form, user and role management - screens, and authorization using <>. To disable - {security-features} entirely, see - {ref}/security-settings.html[{es} security settings]. -|=== - [float] [[authentication-security-settings]] ==== Authentication security settings diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 7235c2a673376..6ff5556c331a2 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -285,18 +285,6 @@ is an alternative to `elasticsearch.username` and `elasticsearch.password`. | `interpreter.enableInVisualize` | Enables use of interpreter in Visualize. *Default: `true`* -|[[kibana-index]] `kibana.index:` - | deprecated:[7.11.0,This setting will be removed in 8.0.] Multitenancy by - changing `kibana.index` will not be supported starting in 8.0. See - https://ela.st/kbn-remove-legacy-multitenancy[8.0 Breaking Changes] for more - details. - + - {kib} uses an index in {es} to store saved searches, visualizations, and - dashboards. {kib} creates a new index if the index doesn’t already exist. If - you configure a custom index, the name must be lowercase, and conform to the - {es} {ref}/indices-create-index.html[index name limitations]. - *Default: `".kibana"`* - | `data.autocomplete.valueSuggestions.timeout:` {ess-icon} | Time in milliseconds to wait for autocomplete suggestions from {es}. This value must be a whole number greater than zero. *Default: `"1000"`* diff --git a/docs/setup/upgrade/upgrade-migrations.asciidoc b/docs/setup/upgrade/upgrade-migrations.asciidoc index 947043b21ef50..adf86d2b2b542 100644 --- a/docs/setup/upgrade/upgrade-migrations.asciidoc +++ b/docs/setup/upgrade/upgrade-migrations.asciidoc @@ -16,8 +16,8 @@ WARNING: The following instructions assumes {kib} is using the default index nam Saved objects are stored in two indices: -* `.kibana_{kibana_version}_001`, or if the `kibana.index` configuration setting is set `.{kibana.index}_{kibana_version}_001`. E.g. for Kibana v7.12.0 `.kibana_7.12.0_001`. -* `.kibana_task_manager_{kibana_version}_001`, or if the `xpack.tasks.index` configuration setting is set `.{xpack.tasks.index}_{kibana_version}_001` E.g. for Kibana v7.12.0 `.kibana_task_manager_7.12.0_001`. +* `.kibana_{kibana_version}_001`, e.g. for Kibana v7.12.0 `.kibana_7.12.0_001`. +* `.kibana_task_manager_{kibana_version}_001`, e.g. for Kibana v7.12.0 `.kibana_task_manager_7.12.0_001`. The index aliases `.kibana` and `.kibana_task_manager` will always point to the most up-to-date saved object indices. diff --git a/package.json b/package.json index 3df7b65315a85..1f2102f3aff2e 100644 --- a/package.json +++ b/package.json @@ -95,14 +95,14 @@ "@dnd-kit/core": "^3.1.1", "@dnd-kit/sortable": "^4.0.0", "@dnd-kit/utilities": "^2.0.0", - "@elastic/apm-generator": "link:bazel-bin/packages/elastic-apm-generator", + "@elastic/apm-synthtrace": "link:bazel-bin/packages/elastic-apm-synthtrace", "@elastic/apm-rum": "^5.9.1", "@elastic/apm-rum-react": "^1.3.1", "@elastic/charts": "38.0.1", "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.21", "@elastic/ems-client": "7.16.0", - "@elastic/eui": "39.1.1", + "@elastic/eui": "40.0.0", "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.3.0", "@elastic/node-crypto": "1.2.1", @@ -166,7 +166,6 @@ "@mapbox/geojson-rewind": "^0.5.0", "@mapbox/mapbox-gl-draw": "1.3.0", "@mapbox/mapbox-gl-rtl-text": "0.2.3", - "@mapbox/vector-tile": "1.3.1", "@reduxjs/toolkit": "^1.6.1", "@slack/webhook": "^5.0.4", "@turf/along": "6.0.1", @@ -460,6 +459,7 @@ "@kbn/test": "link:bazel-bin/packages/kbn-test", "@kbn/test-subj-selector": "link:bazel-bin/packages/kbn-test-subj-selector", "@loaders.gl/polyfills": "^2.3.5", + "@mapbox/vector-tile": "1.3.1", "@microsoft/api-documenter": "7.7.2", "@microsoft/api-extractor": "7.7.0", "@octokit/rest": "^16.35.0", @@ -743,7 +743,7 @@ "jsondiffpatch": "0.4.1", "license-checker": "^16.0.0", "listr": "^0.14.1", - "lmdb-store": "^1.6.8", + "lmdb-store": "^1.6.11", "marge": "^1.0.1", "micromatch": "3.1.10", "minimist": "^1.2.5", diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index ace4f982b8515..846f2c9fc3e4b 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -3,7 +3,7 @@ filegroup( name = "build", srcs = [ - "//packages/elastic-apm-generator:build", + "//packages/elastic-apm-synthtrace:build", "//packages/elastic-datemath:build", "//packages/elastic-eslint-config-kibana:build", "//packages/elastic-safer-lodash-set:build", diff --git a/packages/elastic-apm-generator/README.md b/packages/elastic-apm-generator/README.md deleted file mode 100644 index e43187a8155d3..0000000000000 --- a/packages/elastic-apm-generator/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# @elastic/apm-generator - -`@elastic/apm-generator` is an experimental tool to generate synthetic APM data. It is intended to be used for development and testing of the Elastic APM app in Kibana. - -At a high-level, the module works by modeling APM events/metricsets with [a fluent API](https://en.wikipedia.org/wiki/Fluent_interface). The models can then be serialized and converted to Elasticsearch documents. In the future we might support APM Server as an output as well. - -## Usage - -This section assumes that you've installed Kibana's dependencies by running `yarn kbn bootstrap` in the repository's root folder. - -This library can currently be used in two ways: - -- Imported as a Node.js module, for instance to be used in Kibana's functional test suite. -- With a command line interface, to index data based on some example scenarios. - -### Using the Node.js module - -#### Concepts - -- `Service`: a logical grouping for a monitored service. A `Service` object contains fields like `service.name`, `service.environment` and `agent.name`. -- `Instance`: a single instance of a monitored service. E.g., the workload for a monitored service might be spread across multiple containers. An `Instance` object contains fields like `service.node.name` and `container.id`. -- `Timerange`: an object that will return an array of timestamps based on an interval and a rate. These timestamps can be used to generate events/metricsets. -- `Transaction`, `Span`, `APMError` and `Metricset`: events/metricsets that occur on an instance. For more background, see the [explanation of the APM data model](https://www.elastic.co/guide/en/apm/get-started/7.15/apm-data-model.html) - - -#### Example - -```ts -import { service, timerange, toElasticsearchOutput } from '@elastic/apm-generator'; - -const instance = service('synth-go', 'production', 'go') - .instance('instance-a'); - -const from = new Date('2021-01-01T12:00:00.000Z').getTime(); -const to = new Date('2021-01-01T12:00:00.000Z').getTime() - 1; - -const traceEvents = timerange(from, to) - .interval('1m') - .rate(10) - .flatMap(timestamp => instance.transaction('GET /api/product/list') - .timestamp(timestamp) - .duration(1000) - .success() - .children( - instance.span('GET apm-*/_search', 'db', 'elasticsearch') - .timestamp(timestamp + 50) - .duration(900) - .destination('elasticsearch') - .success() - ).serialize() - ); - -const metricsets = timerange(from, to) - .interval('30s') - .rate(1) - .flatMap(timestamp => instance.appMetrics({ - 'system.memory.actual.free': 800, - 'system.memory.total': 1000, - 'system.cpu.total.norm.pct': 0.6, - 'system.process.cpu.total.norm.pct': 0.7, - }).timestamp(timestamp) - .serialize() - ); - -const esEvents = toElasticsearchOutput(traceEvents.concat(metricsets)); -``` - -#### Generating metricsets - -`@elastic/apm-generator` can also automatically generate transaction metrics, span destination metrics and transaction breakdown metrics based on the generated trace events. If we expand on the previous example: - -```ts -import { getTransactionMetrics, getSpanDestinationMetrics, getBreakdownMetrics } from '@elastic/apm-generator'; - -const esEvents = toElasticsearchOutput([ - ...traceEvents, - ...getTransactionMetrics(traceEvents), - ...getSpanDestinationMetrics(traceEvents), - ...getBreakdownMetrics(traceEvents) -]); -``` - -### CLI - -Via the CLI, you can upload examples. The supported examples are listed in `src/lib/es.ts`. A `--target` option that specifies the Elasticsearch URL should be defined when running the `example` command. Here's an example: - -`$ node packages/elastic-apm-generator/src/scripts/es.js example simple-trace --target=http://admin:changeme@localhost:9200` - -The following options are supported: -- `to`: the end of the time range, in ISO format. By default, the current time will be used. -- `from`: the start of the time range, in ISO format. By default, `to` minus 15 minutes will be used. -- `apm-server-version`: the version used in the index names bootstrapped by APM Server, e.g. `7.16.0`. __If these indices do not exist, the script will exit with an error. It will not bootstrap the indices itself.__ - diff --git a/packages/elastic-apm-generator/src/scripts/es.ts b/packages/elastic-apm-generator/src/scripts/es.ts deleted file mode 100644 index d023ef7172892..0000000000000 --- a/packages/elastic-apm-generator/src/scripts/es.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 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 { inspect } from 'util'; -import { Client } from '@elastic/elasticsearch'; -import { chunk } from 'lodash'; -import pLimit from 'p-limit'; -import yargs from 'yargs/yargs'; -import { toElasticsearchOutput } from '..'; -import { simpleTrace } from './examples/01_simple_trace'; - -yargs(process.argv.slice(2)) - .command( - 'example', - 'run an example scenario', - (y) => { - return y - .positional('scenario', { - describe: 'scenario to run', - choices: ['simple-trace'], - demandOption: true, - }) - .option('target', { - describe: 'elasticsearch target, including username/password', - }) - .option('from', { describe: 'start of timerange' }) - .option('to', { describe: 'end of timerange' }) - .option('workers', { - default: 1, - describe: 'number of concurrently connected ES clients', - }) - .option('apm-server-version', { - describe: 'APM Server version override', - }) - .demandOption('target'); - }, - (argv) => { - let events: any[] = []; - const toDateString = (argv.to as string | undefined) || new Date().toISOString(); - const fromDateString = - (argv.from as string | undefined) || - new Date(new Date(toDateString).getTime() - 15 * 60 * 1000).toISOString(); - - const to = new Date(toDateString).getTime(); - const from = new Date(fromDateString).getTime(); - - switch (argv._[1]) { - case 'simple-trace': - events = simpleTrace(from, to); - break; - } - - const docs = toElasticsearchOutput(events, argv['apm-server-version'] as string); - - const client = new Client({ - node: argv.target as string, - }); - - const fn = pLimit(argv.workers); - - const batches = chunk(docs, 1000); - - // eslint-disable-next-line no-console - console.log( - 'Uploading', - docs.length, - 'docs in', - batches.length, - 'batches', - 'from', - fromDateString, - 'to', - toDateString - ); - - Promise.all( - batches.map((batch) => - fn(() => { - return client.bulk({ - require_alias: true, - body: batch.flatMap((doc) => { - return [{ index: { _index: doc._index } }, doc._source]; - }), - }); - }) - ) - ) - .then((results) => { - const errors = results - .flatMap((result) => result.body.items) - .filter((item) => !!item.index?.error) - .map((item) => item.index?.error); - - if (errors.length) { - // eslint-disable-next-line no-console - console.error(inspect(errors.slice(0, 10), { depth: null })); - throw new Error('Failed to upload some items'); - } - process.exit(); - }) - .catch((err) => { - // eslint-disable-next-line no-console - console.error(err); - process.exit(1); - }); - } - ) - .parse(); diff --git a/packages/elastic-apm-generator/BUILD.bazel b/packages/elastic-apm-synthtrace/BUILD.bazel similarity index 91% rename from packages/elastic-apm-generator/BUILD.bazel rename to packages/elastic-apm-synthtrace/BUILD.bazel index 6b46b2b9181e5..5d9510c6a81d5 100644 --- a/packages/elastic-apm-generator/BUILD.bazel +++ b/packages/elastic-apm-synthtrace/BUILD.bazel @@ -2,8 +2,8 @@ load("@npm//@bazel/typescript:index.bzl", "ts_config", "ts_project") load("@build_bazel_rules_nodejs//:index.bzl", "js_library", "pkg_npm") load("//src/dev/bazel:index.bzl", "jsts_transpiler") -PKG_BASE_NAME = "elastic-apm-generator" -PKG_REQUIRE_NAME = "@elastic/apm-generator" +PKG_BASE_NAME = "elastic-apm-synthtrace" +PKG_REQUIRE_NAME = "@elastic/apm-synthtrace" SOURCE_FILES = glob( [ @@ -25,6 +25,7 @@ NPM_MODULE_EXTRA_FILES = [ ] RUNTIME_DEPS = [ + "//packages/elastic-datemath", "@npm//@elastic/elasticsearch", "@npm//lodash", "@npm//moment", @@ -36,6 +37,7 @@ RUNTIME_DEPS = [ ] TYPES_DEPS = [ + "//packages/elastic-datemath", "@npm//@elastic/elasticsearch", "@npm//moment", "@npm//p-limit", diff --git a/packages/elastic-apm-synthtrace/README.md b/packages/elastic-apm-synthtrace/README.md new file mode 100644 index 0000000000000..8413ba58a5c42 --- /dev/null +++ b/packages/elastic-apm-synthtrace/README.md @@ -0,0 +1,115 @@ +# @elastic/apm-synthtrace + +`@elastic/apm-synthtrace` is an experimental tool to generate synthetic APM data. It is intended to be used for development and testing of the Elastic APM app in Kibana. + +At a high-level, the module works by modeling APM events/metricsets with [a fluent API](https://en.wikipedia.org/wiki/Fluent_interface). The models can then be serialized and converted to Elasticsearch documents. In the future we might support APM Server as an output as well. + +## Usage + +This section assumes that you've installed Kibana's dependencies by running `yarn kbn bootstrap` in the repository's root folder. + +This library can currently be used in two ways: + +- Imported as a Node.js module, for instance to be used in Kibana's functional test suite. +- With a command line interface, to index data based on a specified scenario. + +### Using the Node.js module + +#### Concepts + +- `Service`: a logical grouping for a monitored service. A `Service` object contains fields like `service.name`, `service.environment` and `agent.name`. +- `Instance`: a single instance of a monitored service. E.g., the workload for a monitored service might be spread across multiple containers. An `Instance` object contains fields like `service.node.name` and `container.id`. +- `Timerange`: an object that will return an array of timestamps based on an interval and a rate. These timestamps can be used to generate events/metricsets. +- `Transaction`, `Span`, `APMError` and `Metricset`: events/metricsets that occur on an instance. For more background, see the [explanation of the APM data model](https://www.elastic.co/guide/en/apm/get-started/7.15/apm-data-model.html) + +#### Example + +```ts +import { service, timerange, toElasticsearchOutput } from '@elastic/apm-synthtrace'; + +const instance = service('synth-go', 'production', 'go').instance('instance-a'); + +const from = new Date('2021-01-01T12:00:00.000Z').getTime(); +const to = new Date('2021-01-01T12:00:00.000Z').getTime(); + +const traceEvents = timerange(from, to) + .interval('1m') + .rate(10) + .flatMap((timestamp) => + instance + .transaction('GET /api/product/list') + .timestamp(timestamp) + .duration(1000) + .success() + .children( + instance + .span('GET apm-*/_search', 'db', 'elasticsearch') + .timestamp(timestamp + 50) + .duration(900) + .destination('elasticsearch') + .success() + ) + .serialize() + ); + +const metricsets = timerange(from, to) + .interval('30s') + .rate(1) + .flatMap((timestamp) => + instance + .appMetrics({ + 'system.memory.actual.free': 800, + 'system.memory.total': 1000, + 'system.cpu.total.norm.pct': 0.6, + 'system.process.cpu.total.norm.pct': 0.7, + }) + .timestamp(timestamp) + .serialize() + ); + +const esEvents = toElasticsearchOutput(traceEvents.concat(metricsets)); +``` + +#### Generating metricsets + +`@elastic/apm-synthtrace` can also automatically generate transaction metrics, span destination metrics and transaction breakdown metrics based on the generated trace events. If we expand on the previous example: + +```ts +import { + getTransactionMetrics, + getSpanDestinationMetrics, + getBreakdownMetrics, +} from '@elastic/apm-synthtrace'; + +const esEvents = toElasticsearchOutput([ + ...traceEvents, + ...getTransactionMetrics(traceEvents), + ...getSpanDestinationMetrics(traceEvents), + ...getBreakdownMetrics(traceEvents), +]); +``` + +### CLI + +Via the CLI, you can upload scenarios, either using a fixed time range or continuously generating data. Some examples are available in in `src/scripts/examples`. Here's an example for live data: + +`$ node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-synthtrace/src/examples/01_simple_trace.ts --target=http://admin:changeme@localhost:9200 --live` + +For a fixed time window: +`$ node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-synthtrace/src/examples/01_simple_trace.ts --target=http://admin:changeme@localhost:9200 --from=now-24h --to=now` + +The script will try to automatically find bootstrapped APM indices. **If these indices do not exist, the script will exit with an error. It will not bootstrap the indices itself.** + +The following options are supported: +| Option | Description | Default | +| -------------- | ------------------------------------------------------- | ------------ | +| `--from` | The start of the time window. | `now - 15m` | +| `--to` | The end of the time window. | `now` | +| `--live` | Continously ingest data | `false` | +| `--bucketSize` | Size of bucket for which to generate data. | `15m` | +| `--clean` | Clean APM indices before indexing new data. | `false` | +| `--interval` | The interval at which to index data. | `10s` | +| `--logLevel` | Log level. | `info` | +| `--lookback` | The lookback window for which data should be generated. | `15m` | +| `--target` | Elasticsearch target, including username/password. | **Required** | +| `--workers` | Amount of simultaneously connected ES clients. | `1` | diff --git a/packages/elastic-apm-generator/jest.config.js b/packages/elastic-apm-synthtrace/jest.config.js similarity index 89% rename from packages/elastic-apm-generator/jest.config.js rename to packages/elastic-apm-synthtrace/jest.config.js index 64aaa43741cc3..13d8643c5213c 100644 --- a/packages/elastic-apm-generator/jest.config.js +++ b/packages/elastic-apm-synthtrace/jest.config.js @@ -9,7 +9,7 @@ module.exports = { preset: '@kbn/test', rootDir: '../..', - roots: ['/packages/elastic-apm-generator'], + roots: ['/packages/elastic-apm-synthtrace'], setupFiles: [], setupFilesAfterEnv: [], }; diff --git a/packages/elastic-apm-generator/package.json b/packages/elastic-apm-synthtrace/package.json similarity index 85% rename from packages/elastic-apm-generator/package.json rename to packages/elastic-apm-synthtrace/package.json index 57dafd5d6431d..43699e4795586 100644 --- a/packages/elastic-apm-generator/package.json +++ b/packages/elastic-apm-synthtrace/package.json @@ -1,5 +1,5 @@ { - "name": "@elastic/apm-generator", + "name": "@elastic/apm-synthtrace", "version": "0.1.0", "description": "Elastic APM trace data generator", "license": "SSPL-1.0 OR Elastic License 2.0", diff --git a/packages/elastic-apm-synthtrace/src/.eslintrc.js b/packages/elastic-apm-synthtrace/src/.eslintrc.js new file mode 100644 index 0000000000000..2e3eef95f4bf3 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/.eslintrc.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 = { + rules: { + 'import/no-default-export': 'off', + }, +}; diff --git a/packages/elastic-apm-generator/src/index.ts b/packages/elastic-apm-synthtrace/src/index.ts similarity index 100% rename from packages/elastic-apm-generator/src/index.ts rename to packages/elastic-apm-synthtrace/src/index.ts diff --git a/packages/elastic-apm-generator/src/lib/apm_error.ts b/packages/elastic-apm-synthtrace/src/lib/apm_error.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/apm_error.ts rename to packages/elastic-apm-synthtrace/src/lib/apm_error.ts diff --git a/packages/elastic-apm-generator/src/lib/base_span.ts b/packages/elastic-apm-synthtrace/src/lib/base_span.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/base_span.ts rename to packages/elastic-apm-synthtrace/src/lib/base_span.ts diff --git a/packages/elastic-apm-generator/src/lib/defaults/get_observer_defaults.ts b/packages/elastic-apm-synthtrace/src/lib/defaults/get_observer_defaults.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/defaults/get_observer_defaults.ts rename to packages/elastic-apm-synthtrace/src/lib/defaults/get_observer_defaults.ts diff --git a/packages/elastic-apm-generator/src/lib/entity.ts b/packages/elastic-apm-synthtrace/src/lib/entity.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/entity.ts rename to packages/elastic-apm-synthtrace/src/lib/entity.ts diff --git a/packages/elastic-apm-generator/src/lib/instance.ts b/packages/elastic-apm-synthtrace/src/lib/instance.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/instance.ts rename to packages/elastic-apm-synthtrace/src/lib/instance.ts diff --git a/packages/elastic-apm-generator/src/lib/interval.ts b/packages/elastic-apm-synthtrace/src/lib/interval.ts similarity index 96% rename from packages/elastic-apm-generator/src/lib/interval.ts rename to packages/elastic-apm-synthtrace/src/lib/interval.ts index f13d54fd7415e..bafd1a06c5348 100644 --- a/packages/elastic-apm-generator/src/lib/interval.ts +++ b/packages/elastic-apm-synthtrace/src/lib/interval.ts @@ -21,7 +21,7 @@ export class Interval { throw new Error('Failed to parse interval'); } const timestamps: number[] = []; - while (now <= this.to) { + while (now < this.to) { timestamps.push(...new Array(rate).fill(now)); now = moment(now) .add(Number(args[1]), args[2] as any) diff --git a/packages/elastic-apm-generator/src/lib/metricset.ts b/packages/elastic-apm-synthtrace/src/lib/metricset.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/metricset.ts rename to packages/elastic-apm-synthtrace/src/lib/metricset.ts diff --git a/packages/elastic-apm-generator/src/lib/output/to_elasticsearch_output.ts b/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts similarity index 69% rename from packages/elastic-apm-generator/src/lib/output/to_elasticsearch_output.ts rename to packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts index d90ce8e01f83d..31f3e8c8ed270 100644 --- a/packages/elastic-apm-generator/src/lib/output/to_elasticsearch_output.ts +++ b/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts @@ -10,7 +10,25 @@ import { set } from 'lodash'; import { getObserverDefaults } from '../..'; import { Fields } from '../entity'; -export function toElasticsearchOutput(events: Fields[], versionOverride?: string) { +export interface ElasticsearchOutput { + _index: string; + _source: unknown; +} + +export interface ElasticsearchOutputWriteTargets { + transaction: string; + span: string; + error: string; + metric: string; +} + +export function toElasticsearchOutput({ + events, + writeTargets, +}: { + events: Fields[]; + writeTargets: ElasticsearchOutputWriteTargets; +}): ElasticsearchOutput[] { return events.map((event) => { const values = { ...event, @@ -29,7 +47,7 @@ export function toElasticsearchOutput(events: Fields[], versionOverride?: string set(document, key, val); } return { - _index: `apm-${versionOverride || values['observer.version']}-${values['processor.event']}`, + _index: writeTargets[event['processor.event'] as keyof ElasticsearchOutputWriteTargets], _source: document, }; }); diff --git a/packages/elastic-apm-generator/src/lib/serializable.ts b/packages/elastic-apm-synthtrace/src/lib/serializable.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/serializable.ts rename to packages/elastic-apm-synthtrace/src/lib/serializable.ts diff --git a/packages/elastic-apm-generator/src/lib/service.ts b/packages/elastic-apm-synthtrace/src/lib/service.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/service.ts rename to packages/elastic-apm-synthtrace/src/lib/service.ts diff --git a/packages/elastic-apm-generator/src/lib/span.ts b/packages/elastic-apm-synthtrace/src/lib/span.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/span.ts rename to packages/elastic-apm-synthtrace/src/lib/span.ts diff --git a/packages/elastic-apm-generator/src/lib/timerange.ts b/packages/elastic-apm-synthtrace/src/lib/timerange.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/timerange.ts rename to packages/elastic-apm-synthtrace/src/lib/timerange.ts diff --git a/packages/elastic-apm-generator/src/lib/transaction.ts b/packages/elastic-apm-synthtrace/src/lib/transaction.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/transaction.ts rename to packages/elastic-apm-synthtrace/src/lib/transaction.ts diff --git a/packages/elastic-apm-generator/src/lib/utils/aggregate.ts b/packages/elastic-apm-synthtrace/src/lib/utils/aggregate.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/utils/aggregate.ts rename to packages/elastic-apm-synthtrace/src/lib/utils/aggregate.ts diff --git a/packages/elastic-apm-generator/src/lib/utils/create_picker.ts b/packages/elastic-apm-synthtrace/src/lib/utils/create_picker.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/utils/create_picker.ts rename to packages/elastic-apm-synthtrace/src/lib/utils/create_picker.ts diff --git a/packages/elastic-apm-generator/src/lib/utils/generate_id.ts b/packages/elastic-apm-synthtrace/src/lib/utils/generate_id.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/utils/generate_id.ts rename to packages/elastic-apm-synthtrace/src/lib/utils/generate_id.ts diff --git a/packages/elastic-apm-generator/src/lib/utils/get_breakdown_metrics.ts b/packages/elastic-apm-synthtrace/src/lib/utils/get_breakdown_metrics.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/utils/get_breakdown_metrics.ts rename to packages/elastic-apm-synthtrace/src/lib/utils/get_breakdown_metrics.ts diff --git a/packages/elastic-apm-generator/src/lib/utils/get_span_destination_metrics.ts b/packages/elastic-apm-synthtrace/src/lib/utils/get_span_destination_metrics.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/utils/get_span_destination_metrics.ts rename to packages/elastic-apm-synthtrace/src/lib/utils/get_span_destination_metrics.ts diff --git a/packages/elastic-apm-generator/src/lib/utils/get_transaction_metrics.ts b/packages/elastic-apm-synthtrace/src/lib/utils/get_transaction_metrics.ts similarity index 100% rename from packages/elastic-apm-generator/src/lib/utils/get_transaction_metrics.ts rename to packages/elastic-apm-synthtrace/src/lib/utils/get_transaction_metrics.ts diff --git a/packages/elastic-apm-generator/src/scripts/examples/01_simple_trace.ts b/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts similarity index 94% rename from packages/elastic-apm-generator/src/scripts/examples/01_simple_trace.ts rename to packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts index f6aad154532c2..6b857391b4f96 100644 --- a/packages/elastic-apm-generator/src/scripts/examples/01_simple_trace.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts @@ -9,12 +9,12 @@ import { service, timerange, getTransactionMetrics, getSpanDestinationMetrics } from '../..'; import { getBreakdownMetrics } from '../../lib/utils/get_breakdown_metrics'; -export function simpleTrace(from: number, to: number) { +export default function ({ from, to }: { from: number; to: number }) { const instance = service('opbeans-go', 'production', 'go').instance('instance'); const range = timerange(from, to); - const transactionName = '240rpm/60% 1000ms'; + const transactionName = '240rpm/75% 1000ms'; const successfulTraceEvents = range .interval('1s') diff --git a/packages/elastic-apm-generator/src/scripts/es.js b/packages/elastic-apm-synthtrace/src/scripts/run.js similarity index 96% rename from packages/elastic-apm-generator/src/scripts/es.js rename to packages/elastic-apm-synthtrace/src/scripts/run.js index 9f99a5d19b8f8..426b247b6b623 100644 --- a/packages/elastic-apm-generator/src/scripts/es.js +++ b/packages/elastic-apm-synthtrace/src/scripts/run.js @@ -12,4 +12,4 @@ require('@babel/register')({ presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], }); -require('./es.ts'); +require('./run.ts'); diff --git a/packages/elastic-apm-synthtrace/src/scripts/run.ts b/packages/elastic-apm-synthtrace/src/scripts/run.ts new file mode 100644 index 0000000000000..ad453ac96ff10 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/run.ts @@ -0,0 +1,117 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 datemath from '@elastic/datemath'; +import yargs from 'yargs/yargs'; +import { cleanWriteTargets } from './utils/clean_write_targets'; +import { + bucketSizeOption, + cleanOption, + fileOption, + intervalOption, + targetOption, + workerOption, + logLevelOption, +} from './utils/common_options'; +import { intervalToMs } from './utils/interval_to_ms'; +import { getCommonResources } from './utils/get_common_resources'; +import { startHistoricalDataUpload } from './utils/start_historical_data_upload'; +import { startLiveDataUpload } from './utils/start_live_data_upload'; + +yargs(process.argv.slice(2)) + .command( + '*', + 'Generate data and index into Elasticsearch', + (y) => { + return y + .positional('file', fileOption) + .option('bucketSize', bucketSizeOption) + .option('workers', workerOption) + .option('interval', intervalOption) + .option('clean', cleanOption) + .option('target', targetOption) + .option('logLevel', logLevelOption) + .option('from', { + description: 'The start of the time window', + }) + .option('to', { + description: 'The end of the time window', + }) + .option('live', { + description: 'Generate and index data continuously', + boolean: true, + }) + .conflicts('to', 'live'); + }, + async (argv) => { + const { + scenario, + intervalInMs, + bucketSizeInMs, + target, + workers, + clean, + logger, + writeTargets, + client, + } = await getCommonResources(argv); + + if (clean) { + await cleanWriteTargets({ writeTargets, client, logger }); + } + + const to = datemath.parse(String(argv.to ?? 'now'))!.valueOf(); + const from = argv.from + ? datemath.parse(String(argv.from))!.valueOf() + : to - intervalToMs('15m'); + + const live = argv.live; + + logger.info( + `Starting data generation\n: ${JSON.stringify( + { + intervalInMs, + bucketSizeInMs, + workers, + target, + writeTargets, + from: new Date(from).toISOString(), + to: new Date(to).toISOString(), + live, + }, + null, + 2 + )}` + ); + + startHistoricalDataUpload({ + from, + to, + scenario, + intervalInMs, + bucketSizeInMs, + client, + workers, + writeTargets, + logger, + }); + + if (live) { + startLiveDataUpload({ + bucketSizeInMs, + client, + intervalInMs, + logger, + scenario, + start: to, + workers, + writeTargets, + }); + } + } + ) + .parse(); diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/clean_write_targets.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/clean_write_targets.ts new file mode 100644 index 0000000000000..efa24f164d51e --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/clean_write_targets.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Client } from '@elastic/elasticsearch'; +import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output'; +import { Logger } from './logger'; + +export async function cleanWriteTargets({ + writeTargets, + client, + logger, +}: { + writeTargets: ElasticsearchOutputWriteTargets; + client: Client; + logger: Logger; +}) { + const targets = Object.values(writeTargets); + + logger.info(`Cleaning indices: ${targets.join(', ')}`); + + const response = await client.deleteByQuery({ + index: targets, + allow_no_indices: true, + conflicts: 'proceed', + body: { + query: { + match_all: {}, + }, + }, + wait_for_completion: false, + }); + + const task = response.body.task; + + if (task) { + await new Promise((resolve, reject) => { + const pollForTaskCompletion = async () => { + const taskResponse = await client.tasks.get({ + task_id: String(task), + }); + + logger.debug( + `Polled for task:\n${JSON.stringify(taskResponse.body, ['completed', 'error'], 2)}` + ); + + if (taskResponse.body.completed) { + resolve(); + } else if (taskResponse.body.error) { + reject(taskResponse.body.error); + } else { + setTimeout(pollForTaskCompletion, 2500); + } + }; + + pollForTaskCompletion(); + }); + } +} diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/common_options.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/common_options.ts new file mode 100644 index 0000000000000..eba547114d533 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/common_options.ts @@ -0,0 +1,53 @@ +/* + * Copyright 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 fileOption = { + describe: 'File that contains the trace scenario', + demandOption: true, +}; + +const intervalOption = { + describe: 'The interval at which to index data', + default: '10s', +}; + +const targetOption = { + describe: 'Elasticsearch target, including username/password', + demandOption: true, +}; + +const bucketSizeOption = { + describe: 'Size of bucket for which to generate data', + default: '15m', +}; + +const workerOption = { + describe: 'Amount of simultaneously connected ES clients', + default: 1, +}; + +const cleanOption = { + describe: 'Clean APM indices before indexing new data', + default: false, + boolean: true as const, +}; + +const logLevelOption = { + describe: 'Log level', + default: 'info', +}; + +export { + fileOption, + intervalOption, + targetOption, + bucketSizeOption, + workerOption, + cleanOption, + logLevelOption, +}; diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts new file mode 100644 index 0000000000000..1288c1390e92c --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.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 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 { Client } from '@elastic/elasticsearch'; +import { getScenario } from './get_scenario'; +import { getWriteTargets } from './get_write_targets'; +import { intervalToMs } from './interval_to_ms'; +import { createLogger, LogLevel } from './logger'; + +export async function getCommonResources({ + file, + interval, + bucketSize, + workers, + target, + clean, + logLevel, +}: { + file: unknown; + interval: unknown; + bucketSize: unknown; + workers: unknown; + target: unknown; + clean: boolean; + logLevel: unknown; +}) { + let parsedLogLevel = LogLevel.info; + switch (logLevel) { + case 'info': + parsedLogLevel = LogLevel.info; + break; + + case 'debug': + parsedLogLevel = LogLevel.debug; + break; + + case 'quiet': + parsedLogLevel = LogLevel.quiet; + break; + } + + const logger = createLogger(parsedLogLevel); + + const intervalInMs = intervalToMs(interval); + if (!intervalInMs) { + throw new Error('Invalid interval'); + } + + const bucketSizeInMs = intervalToMs(bucketSize); + + if (!bucketSizeInMs) { + throw new Error('Invalid bucket size'); + } + + const client = new Client({ + node: String(target), + }); + + const [scenario, writeTargets] = await Promise.all([ + getScenario({ file, logger }), + getWriteTargets({ client }), + ]); + + return { + scenario, + writeTargets, + logger, + client, + intervalInMs, + bucketSizeInMs, + workers: Number(workers), + target: String(target), + clean, + }; +} diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_scenario.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_scenario.ts new file mode 100644 index 0000000000000..887969e8459cc --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_scenario.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 Path from 'path'; +import { Fields } from '../../lib/entity'; +import { Logger } from './logger'; + +export type Scenario = (options: { from: number; to: number }) => Fields[]; + +export function getScenario({ file, logger }: { file: unknown; logger: Logger }) { + const location = Path.join(process.cwd(), String(file)); + + logger.debug(`Loading scenario from ${location}`); + + return import(location).then((m) => { + if (m && m.default) { + return m.default; + } + throw new Error(`Could not find scenario at ${location}`); + }) as Promise; +} diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts new file mode 100644 index 0000000000000..3640e4efaf796 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Client } from '@elastic/elasticsearch'; +import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output'; + +export async function getWriteTargets({ + client, +}: { + client: Client; +}): Promise { + const [indicesResponse, datastreamsResponse] = await Promise.all([ + client.indices.getAlias({ + index: 'apm-*', + }), + client.indices.getDataStream({ + name: '*apm', + }), + ]); + + function getDataStreamName(filter: string) { + return datastreamsResponse.body.data_streams.find((stream) => stream.name.includes(filter)) + ?.name; + } + + function getAlias(filter: string) { + return Object.keys(indicesResponse.body) + .map((key) => { + return { + key, + writeIndexAlias: Object.entries(indicesResponse.body[key].aliases).find( + ([_, alias]) => alias.is_write_index + )?.[0], + }; + }) + .find(({ key }) => key.includes(filter))?.writeIndexAlias!; + } + + const targets = { + transaction: getDataStreamName('traces-apm') || getAlias('-transaction'), + span: getDataStreamName('traces-apm') || getAlias('-span'), + metric: getDataStreamName('metrics-apm') || getAlias('-metric'), + error: getDataStreamName('logs-apm') || getAlias('-error'), + }; + + if (!targets.transaction || !targets.span || !targets.metric || !targets.error) { + throw new Error('Write targets could not be determined'); + } + + return targets; +} diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/interval_to_ms.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/interval_to_ms.ts new file mode 100644 index 0000000000000..4cba832be3161 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/interval_to_ms.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. + */ + +export function intervalToMs(interval: unknown) { + const [, valueAsString, unit] = String(interval).split(/(.*)(s|m|h|d|w)/); + + const value = Number(valueAsString); + + switch (unit) { + case 's': + return value * 1000; + case 'm': + return value * 1000 * 60; + + case 'h': + return value * 1000 * 60 * 60; + + case 'd': + return value * 1000 * 60 * 60 * 24; + + case 'w': + return value * 1000 * 60 * 60 * 24 * 7; + } + + throw new Error('Could not parse interval'); +} diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/logger.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/logger.ts new file mode 100644 index 0000000000000..c9017cb08e663 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/logger.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. + */ + +export enum LogLevel { + debug = 0, + info = 1, + quiet = 2, +} + +export function createLogger(logLevel: LogLevel) { + return { + debug: (...args: any[]) => { + if (logLevel <= LogLevel.debug) { + // eslint-disable-next-line no-console + console.debug(...args); + } + }, + info: (...args: any[]) => { + if (logLevel <= LogLevel.info) { + // eslint-disable-next-line no-console + console.log(...args); + } + }, + }; +} + +export type Logger = ReturnType; diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts new file mode 100644 index 0000000000000..db14090dd1d8f --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { Client } from '@elastic/elasticsearch'; +import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output'; +import { Scenario } from './get_scenario'; +import { Logger } from './logger'; +import { uploadEvents } from './upload_events'; + +export async function startHistoricalDataUpload({ + from, + to, + scenario, + intervalInMs, + bucketSizeInMs, + client, + workers, + writeTargets, + logger, +}: { + from: number; + to: number; + scenario: Scenario; + intervalInMs: number; + bucketSizeInMs: number; + client: Client; + workers: number; + writeTargets: ElasticsearchOutputWriteTargets; + logger: Logger; +}) { + let requestedUntil: number = from; + function uploadNextBatch() { + const bucketFrom = requestedUntil; + const bucketTo = Math.min(to, bucketFrom + bucketSizeInMs); + + const events = scenario({ from: bucketFrom, to: bucketTo }); + + logger.info( + `Uploading: ${new Date(bucketFrom).toISOString()} to ${new Date(bucketTo).toISOString()}` + ); + + uploadEvents({ + events, + client, + workers, + writeTargets, + logger, + }).then(() => { + if (bucketTo >= to) { + return; + } + uploadNextBatch(); + }); + + requestedUntil = bucketTo; + } + + return uploadNextBatch(); +} diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts new file mode 100644 index 0000000000000..bf330732f343e --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts @@ -0,0 +1,75 @@ +/* + * Copyright 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 { Client } from '@elastic/elasticsearch'; +import { partition } from 'lodash'; +import { Fields } from '../../lib/entity'; +import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output'; +import { Scenario } from './get_scenario'; +import { Logger } from './logger'; +import { uploadEvents } from './upload_events'; + +export function startLiveDataUpload({ + start, + bucketSizeInMs, + intervalInMs, + workers, + writeTargets, + scenario, + client, + logger, +}: { + start: number; + bucketSizeInMs: number; + intervalInMs: number; + workers: number; + writeTargets: ElasticsearchOutputWriteTargets; + scenario: Scenario; + client: Client; + logger: Logger; +}) { + let queuedEvents: Fields[] = []; + let requestedUntil: number = start; + + function uploadNextBatch() { + const end = new Date().getTime(); + if (end > requestedUntil) { + const bucketFrom = requestedUntil; + const bucketTo = requestedUntil + bucketSizeInMs; + const nextEvents = scenario({ from: bucketFrom, to: bucketTo }); + logger.debug( + `Requesting ${new Date(bucketFrom).toISOString()} to ${new Date( + bucketTo + ).toISOString()}, events: ${nextEvents.length}` + ); + queuedEvents.push(...nextEvents); + requestedUntil = bucketTo; + } + + const [eventsToUpload, eventsToRemainInQueue] = partition( + queuedEvents, + (event) => event['@timestamp']! <= end + ); + + logger.info(`Uploading until ${new Date(end).toISOString()}, events: ${eventsToUpload.length}`); + + queuedEvents = eventsToRemainInQueue; + + uploadEvents({ + events: eventsToUpload, + client, + workers, + writeTargets, + logger, + }); + } + + setInterval(uploadNextBatch, intervalInMs); + + uploadNextBatch(); +} diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts new file mode 100644 index 0000000000000..89cf4d4602177 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import { Client } from '@elastic/elasticsearch'; +import { chunk } from 'lodash'; +import pLimit from 'p-limit'; +import { inspect } from 'util'; +import { Fields } from '../../lib/entity'; +import { + ElasticsearchOutputWriteTargets, + toElasticsearchOutput, +} from '../../lib/output/to_elasticsearch_output'; +import { Logger } from './logger'; + +export function uploadEvents({ + events, + client, + workers, + writeTargets, + logger, +}: { + events: Fields[]; + client: Client; + workers: number; + writeTargets: ElasticsearchOutputWriteTargets; + logger: Logger; +}) { + const esDocuments = toElasticsearchOutput({ events, writeTargets }); + const fn = pLimit(workers); + + const batches = chunk(esDocuments, 5000); + + logger.debug(`Uploading ${esDocuments.length} in ${batches.length} batches`); + + const time = new Date().getTime(); + + return Promise.all( + batches.map((batch) => + fn(() => { + return client.bulk({ + require_alias: true, + body: batch.flatMap((doc) => { + return [{ index: { _index: doc._index } }, doc._source]; + }), + }); + }) + ) + ) + .then((results) => { + const errors = results + .flatMap((result) => result.body.items) + .filter((item) => !!item.index?.error) + .map((item) => item.index?.error); + + if (errors.length) { + // eslint-disable-next-line no-console + console.error(inspect(errors.slice(0, 10), { depth: null })); + throw new Error('Failed to upload some items'); + } + + logger.debug(`Uploaded ${events.length} in ${new Date().getTime() - time}ms`); + }) + .catch((err) => { + // eslint-disable-next-line no-console + console.error(err); + process.exit(1); + }); +} diff --git a/packages/elastic-apm-generator/src/test/scenarios/01_simple_trace.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts similarity index 98% rename from packages/elastic-apm-generator/src/test/scenarios/01_simple_trace.test.ts rename to packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts index 733093ce0a71c..866a9745befc3 100644 --- a/packages/elastic-apm-generator/src/test/scenarios/01_simple_trace.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts @@ -18,7 +18,7 @@ describe('simple trace', () => { const range = timerange( new Date('2021-01-01T00:00:00.000Z').getTime(), - new Date('2021-01-01T00:15:00.000Z').getTime() - 1 + new Date('2021-01-01T00:15:00.000Z').getTime() ); events = range diff --git a/packages/elastic-apm-generator/src/test/scenarios/02_transaction_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts similarity index 98% rename from packages/elastic-apm-generator/src/test/scenarios/02_transaction_metrics.test.ts rename to packages/elastic-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts index 0b9f192d3d27d..58b28f71b9afc 100644 --- a/packages/elastic-apm-generator/src/test/scenarios/02_transaction_metrics.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/scenarios/02_transaction_metrics.test.ts @@ -19,7 +19,7 @@ describe('transaction metrics', () => { const range = timerange( new Date('2021-01-01T00:00:00.000Z').getTime(), - new Date('2021-01-01T00:15:00.000Z').getTime() - 1 + new Date('2021-01-01T00:15:00.000Z').getTime() ); events = getTransactionMetrics( diff --git a/packages/elastic-apm-generator/src/test/scenarios/03_span_destination_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts similarity index 98% rename from packages/elastic-apm-generator/src/test/scenarios/03_span_destination_metrics.test.ts rename to packages/elastic-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts index 158ccc5b5e714..0bf59f044bf03 100644 --- a/packages/elastic-apm-generator/src/test/scenarios/03_span_destination_metrics.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/scenarios/03_span_destination_metrics.test.ts @@ -19,7 +19,7 @@ describe('span destination metrics', () => { const range = timerange( new Date('2021-01-01T00:00:00.000Z').getTime(), - new Date('2021-01-01T00:15:00.000Z').getTime() - 1 + new Date('2021-01-01T00:15:00.000Z').getTime() ); events = getSpanDestinationMetrics( diff --git a/packages/elastic-apm-generator/src/test/scenarios/04_breakdown_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts similarity index 99% rename from packages/elastic-apm-generator/src/test/scenarios/04_breakdown_metrics.test.ts rename to packages/elastic-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts index aeb944f35faf6..469f56b99c5f2 100644 --- a/packages/elastic-apm-generator/src/test/scenarios/04_breakdown_metrics.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/scenarios/04_breakdown_metrics.test.ts @@ -26,7 +26,7 @@ describe('breakdown metrics', () => { const start = new Date('2021-01-01T00:00:00.000Z').getTime(); - const range = timerange(start, start + INTERVALS * 30 * 1000 - 1); + const range = timerange(start, start + INTERVALS * 30 * 1000); events = getBreakdownMetrics([ ...range diff --git a/packages/elastic-apm-generator/src/test/scenarios/05_transactions_with_errors.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts similarity index 100% rename from packages/elastic-apm-generator/src/test/scenarios/05_transactions_with_errors.test.ts rename to packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts diff --git a/packages/elastic-apm-generator/src/test/scenarios/06_application_metrics.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts similarity index 100% rename from packages/elastic-apm-generator/src/test/scenarios/06_application_metrics.test.ts rename to packages/elastic-apm-synthtrace/src/test/scenarios/06_application_metrics.test.ts diff --git a/packages/elastic-apm-generator/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap b/packages/elastic-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap similarity index 100% rename from packages/elastic-apm-generator/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap rename to packages/elastic-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap diff --git a/packages/elastic-apm-generator/src/test/to_elasticsearch_output.test.ts b/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts similarity index 76% rename from packages/elastic-apm-generator/src/test/to_elasticsearch_output.test.ts rename to packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts index c1a5d47654fc9..d15ea89083112 100644 --- a/packages/elastic-apm-generator/src/test/to_elasticsearch_output.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts @@ -9,6 +9,13 @@ import { Fields } from '../lib/entity'; import { toElasticsearchOutput } from '../lib/output/to_elasticsearch_output'; +const writeTargets = { + transaction: 'apm-8.0.0-transaction', + span: 'apm-8.0.0-span', + metric: 'apm-8.0.0-metric', + error: 'apm-8.0.0-error', +}; + describe('output to elasticsearch', () => { let event: Fields; @@ -21,13 +28,13 @@ describe('output to elasticsearch', () => { }); it('properly formats @timestamp', () => { - const doc = toElasticsearchOutput([event])[0] as any; + const doc = toElasticsearchOutput({ events: [event], writeTargets })[0] as any; expect(doc._source['@timestamp']).toEqual('2020-12-31T23:00:00.000Z'); }); it('formats a nested object', () => { - const doc = toElasticsearchOutput([event])[0] as any; + const doc = toElasticsearchOutput({ events: [event], writeTargets })[0] as any; expect(doc._source.processor).toEqual({ event: 'transaction', diff --git a/packages/elastic-apm-generator/tsconfig.json b/packages/elastic-apm-synthtrace/tsconfig.json similarity index 60% rename from packages/elastic-apm-generator/tsconfig.json rename to packages/elastic-apm-synthtrace/tsconfig.json index 534e8481dce9a..6ae9c20b4387b 100644 --- a/packages/elastic-apm-generator/tsconfig.json +++ b/packages/elastic-apm-synthtrace/tsconfig.json @@ -7,13 +7,8 @@ "outDir": "target_types", "rootDir": "./src", "sourceMap": true, - "sourceRoot": "../../../../packages/elastic-apm-generator/src", - "types": [ - "node", - "jest" - ] + "sourceRoot": "../../../../packages/elastic-apm-synthtrace/src", + "types": ["node", "jest"] }, - "include": [ - "./src/**/*.ts" - ] + "include": ["./src/**/*.ts"] } diff --git a/packages/kbn-monaco/src/xjson/grammar.test.ts b/packages/kbn-monaco/src/xjson/grammar.test.ts new file mode 100644 index 0000000000000..29d338cd71b0c --- /dev/null +++ b/packages/kbn-monaco/src/xjson/grammar.test.ts @@ -0,0 +1,189 @@ +/* + * Copyright 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 { createParser } from './grammar'; + +describe('createParser', () => { + let parser: ReturnType; + + beforeEach(() => { + parser = createParser(); + }); + + test('should create a xjson grammar parser', () => { + expect(createParser()).toBeInstanceOf(Function); + }); + + test('should return no annotations in case of valid json', () => { + expect( + parser(` + {"menu": { + "id": "file", + "value": "File", + "quotes": "'\\"", + "popup": { + "actions": [ + "new", + "open", + "close" + ], + "menuitem": [ + {"value": "New"}, + {"value": "Open"}, + {"value": "Close"} + ] + } + }} + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [], + } + `); + }); + + test('should support triple quotes', () => { + expect( + parser(` + {"menu": { + "id": """ + file + """, + "value": "File" + }} + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [], + } + `); + }); + + test('triple quotes should be correctly closed', () => { + expect( + parser(` + {"menu": { + "id": """" + file + "", + "value": "File" + }} + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [ + Object { + "at": 36, + "text": "Expected ',' instead of '\\"'", + "type": "error", + }, + ], + } + `); + }); + + test('an escaped quote can be appended to the end of triple quotes', () => { + expect( + parser(` + {"menu": { + "id": """ + file + \\"""", + "value": "File" + }} + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [], + } + `); + }); + + test('text values should be wrapper into quotes', () => { + expect( + parser(` + {"menu": { + "id": id, + "value": "File" + }} + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [ + Object { + "at": 36, + "text": "Unexpected 'i'", + "type": "error", + }, + ], + } + `); + }); + + test('check for close quotes', () => { + expect( + parser(` + {"menu": { + "id": "id, + "value": "File" + }} + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [ + Object { + "at": 52, + "text": "Expected ',' instead of 'v'", + "type": "error", + }, + ], + } + `); + }); + test('no duplicate keys', () => { + expect( + parser(` + {"menu": { + "id": "id", + "id": "File" + }} + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [ + Object { + "at": 53, + "text": "Duplicate key \\"id\\"", + "type": "warning", + }, + ], + } + `); + }); + + test('all curly quotes should be closed', () => { + expect( + parser(` + {"menu": { + "id": "id", + "name": "File" + } + `) + ).toMatchInlineSnapshot(` + Object { + "annotations": Array [ + Object { + "at": 82, + "text": "Expected ',' instead of ''", + "type": "error", + }, + ], + } + `); + }); +}); diff --git a/packages/kbn-monaco/src/xjson/grammar.ts b/packages/kbn-monaco/src/xjson/grammar.ts index 32c958e66d594..5d26e92f005ba 100644 --- a/packages/kbn-monaco/src/xjson/grammar.ts +++ b/packages/kbn-monaco/src/xjson/grammar.ts @@ -57,10 +57,6 @@ export const createParser = () => { text: m, }); }, - reset = function (newAt: number) { - ch = text.charAt(newAt); - at = newAt + 1; - }, next = function (c?: string) { return ( c && c !== ch && error("Expected '" + c + "' instead of '" + ch + "'"), @@ -69,15 +65,6 @@ export const createParser = () => { ch ); }, - nextUpTo = function (upTo: any, errorMessage: string) { - let currentAt = at, - i = text.indexOf(upTo, currentAt); - if (i < 0) { - error(errorMessage || "Expected '" + upTo + "'"); - } - reset(i + upTo.length); - return text.substring(currentAt, i); - }, peek = function (c: string) { return text.substr(at, c.length) === c; // nocommit - double check }, @@ -96,37 +83,50 @@ export const createParser = () => { (string += ch), next(); return (number = +string), isNaN(number) ? (error('Bad number'), void 0) : number; }, + stringLiteral = function () { + let quotes = '"""'; + let end = text.indexOf('\\"' + quotes, at + quotes.length); + + if (end >= 0) { + quotes = '\\"' + quotes; + } else { + end = text.indexOf(quotes, at + quotes.length); + } + + if (end >= 0) { + for (let l = end - at + quotes.length; l > 0; l--) { + next(); + } + } + + return next(); + }, string = function () { let hex: any, i: any, uffff: any, string = ''; + if ('"' === ch) { - if (peek('""')) { - // literal - next('"'); - next('"'); - return nextUpTo('"""', 'failed to find closing \'"""\''); - } else { - for (; next(); ) { - if ('"' === ch) return next(), string; - if ('\\' === ch) - if ((next(), 'u' === ch)) { - for ( - uffff = 0, i = 0; - 4 > i && ((hex = parseInt(next(), 16)), isFinite(hex)); - i += 1 - ) - uffff = 16 * uffff + hex; - string += String.fromCharCode(uffff); - } else { - if ('string' != typeof escapee[ch]) break; - string += escapee[ch]; - } - else string += ch; - } + for (; next(); ) { + if ('"' === ch) return next(), string; + if ('\\' === ch) + if ((next(), 'u' === ch)) { + for ( + uffff = 0, i = 0; + 4 > i && ((hex = parseInt(next(), 16)), isFinite(hex)); + i += 1 + ) + uffff = 16 * uffff + hex; + string += String.fromCharCode(uffff); + } else { + if ('string' != typeof escapee[ch]) break; + string += escapee[ch]; + } + else string += ch; } } + error('Bad string'); }, white = function () { @@ -165,9 +165,9 @@ export const createParser = () => { ((key = string()), white(), next(':'), - Object.hasOwnProperty.call(object, key) && + Object.hasOwnProperty.call(object, key!) && warning('Duplicate key "' + key + '"', latchKeyStart), - (object[key] = value()), + (object[key!] = value()), white(), '}' === ch) ) @@ -179,6 +179,9 @@ export const createParser = () => { }; return ( (value = function () { + if (peek('"""')) { + return stringLiteral(); + } switch ((white(), ch)) { case '{': return object(); diff --git a/packages/kbn-monaco/src/xjson/lexer_rules/xjson.ts b/packages/kbn-monaco/src/xjson/lexer_rules/xjson.ts index 2c8186ac7fa4f..f2ab22f8c97df 100644 --- a/packages/kbn-monaco/src/xjson/lexer_rules/xjson.ts +++ b/packages/kbn-monaco/src/xjson/lexer_rules/xjson.ts @@ -103,6 +103,7 @@ export const lexerRules: monaco.languages.IMonarchLanguage = { string_literal: [ [/"""/, { token: 'punctuation.end_triple_quote', next: '@pop' }], + [/\\""""/, { token: 'punctuation.end_triple_quote', next: '@pop' }], [/./, { token: 'multi_string' }], ], }, diff --git a/packages/kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js b/packages/kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js index 2ded0e509c253..09ed81b62a09d 100644 --- a/packages/kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js +++ b/packages/kbn-test/src/functional_tests/lib/babel_register_for_test_plugins.js @@ -6,23 +6,30 @@ * Side Public License, v 1. */ +const Fs = require('fs'); const Path = require('path'); -const { REPO_ROOT } = require('@kbn/dev-utils'); +const { REPO_ROOT: REPO_ROOT_FOLLOWING_SYMLINKS } = require('@kbn/dev-utils'); +const BASE_REPO_ROOT = Path.resolve( + Fs.realpathSync(Path.resolve(REPO_ROOT_FOLLOWING_SYMLINKS, 'package.json')), + '..' +); + +const transpileKbnPaths = [ + 'test', + 'x-pack/test', + 'examples', + 'x-pack/examples', + // TODO: should should probably remove this link back to the source + 'x-pack/plugins/task_manager/server/config.ts', + 'src/core/utils/default_app_categories.ts', +].map((path) => Path.resolve(BASE_REPO_ROOT, path)); // modifies all future calls to require() to automatically // compile the required source with babel require('@babel/register')({ ignore: [/[\/\\](node_modules|target|dist)[\/\\]/], - only: [ - Path.resolve(REPO_ROOT, 'test'), - Path.resolve(REPO_ROOT, 'x-pack/test'), - Path.resolve(REPO_ROOT, 'examples'), - Path.resolve(REPO_ROOT, 'x-pack/examples'), - // TODO: should should probably remove this link back to the source - Path.resolve(REPO_ROOT, 'x-pack/plugins/task_manager/server/config.ts'), - Path.resolve(REPO_ROOT, 'src/core/utils/default_app_categories.ts'), - ], + only: transpileKbnPaths, babelrc: false, presets: [require.resolve('@kbn/babel-preset/node_preset')], extensions: ['.js', '.ts', '.tsx'], diff --git a/src/cli_setup/utils.ts b/src/cli_setup/utils.ts index 65a46b8f5b278..21406bf7e57e0 100644 --- a/src/cli_setup/utils.ts +++ b/src/cli_setup/utils.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { getConfigPath } from '@kbn/utils'; +import { getConfigPath, getDataPath } from '@kbn/utils'; import inquirer from 'inquirer'; import { duration } from 'moment'; import { merge } from 'lodash'; @@ -30,7 +30,7 @@ const logger: Logger = { get: () => logger, }; -export const kibanaConfigWriter = new KibanaConfigWriter(getConfigPath(), logger); +export const kibanaConfigWriter = new KibanaConfigWriter(getConfigPath(), getDataPath(), logger); export const elasticsearch = new ElasticsearchService(logger).setup({ connectionCheckInterval: duration(Infinity), elasticsearch: { diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 6987b779d5d45..571b564f90329 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -644,6 +644,11 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` > } + buttonElement="button" className="euiCollapsibleNavGroup euiCollapsibleNavGroup--light euiCollapsibleNavGroup--withHeading" data-test-subj="collapsibleNavGroup-recentlyViewed" + element="div" id="generated-id" initialIsOpen={true} isLoading={false} @@ -685,28 +692,13 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` + + +
} + buttonElement="button" className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" data-test-subj="collapsibleNavGroup-kibana" + element="div" id="generated-id" initialIsOpen={true} isLoading={false} @@ -941,28 +977,13 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` + + +
} + buttonElement="button" className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" data-test-subj="collapsibleNavGroup-observability" + element="div" id="generated-id" initialIsOpen={true} isLoading={false} @@ -1233,28 +1298,13 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` + + +
} + buttonElement="button" className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" data-test-subj="collapsibleNavGroup-securitySolution" + element="div" id="generated-id" initialIsOpen={true} isLoading={false} @@ -1486,28 +1580,13 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` + + +
} + buttonElement="button" className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" data-test-subj="collapsibleNavGroup-management" + element="div" id="generated-id" initialIsOpen={true} isLoading={false} @@ -1700,28 +1823,13 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` + + +
{ diff --git a/src/core/public/doc_links/doc_links_service.ts b/src/core/public/doc_links/doc_links_service.ts index 87b05eeafc568..2bbb4703ecd19 100644 --- a/src/core/public/doc_links/doc_links_service.ts +++ b/src/core/public/doc_links/doc_links_service.ts @@ -480,6 +480,7 @@ export class DocLinksService { troubleshooting: `${FLEET_DOCS}fleet-troubleshooting.html`, elasticAgent: `${FLEET_DOCS}elastic-agent-installation.html`, datastreams: `${FLEET_DOCS}data-streams.html`, + datastreamsILM: `${FLEET_DOCS}data-streams.html#data-streams-ilm`, datastreamsNamingScheme: `${FLEET_DOCS}data-streams.html#data-streams-naming-scheme`, installElasticAgent: `${FLEET_DOCS}install-fleet-managed-elastic-agent.html`, upgradeElasticAgent: `${FLEET_DOCS}upgrade-elastic-agent.html`, @@ -499,7 +500,7 @@ export class DocLinksService { netGuide: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/client/net-api/${DOC_LINK_VERSION}/index.html`, perlGuide: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/client/perl-api/${DOC_LINK_VERSION}/index.html`, phpGuide: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/client/php-api/${DOC_LINK_VERSION}/index.html`, - pythonGuide: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/client/net-api/${DOC_LINK_VERSION}/index.html`, + pythonGuide: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/client/python-api/${DOC_LINK_VERSION}/index.html`, rubyOverview: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/client/ruby-api/${DOC_LINK_VERSION}/ruby_client.html`, rustGuide: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/client/rust-api/${DOC_LINK_VERSION}/index.html`, }, @@ -734,6 +735,7 @@ export interface DocLinksStart { readonly snapshotRestore: Record; readonly ingest: Record; readonly fleet: Readonly<{ + datastreamsILM: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 353e5aa4607e4..1992b2d9686ac 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -7,7 +7,6 @@ import { Action } from 'history'; import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import Boom from '@hapi/boom'; -import { ConfigDeprecationProvider } from '@kbn/config'; import { ConfigPath } from '@kbn/config'; import { DetailedPeerCertificate } from 'tls'; import { EnvironmentMode } from '@kbn/config'; @@ -698,6 +697,7 @@ export interface DocLinksStart { readonly snapshotRestore: Record; readonly ingest: Record; readonly fleet: Readonly<{ + datastreamsILM: string; guide: string; fleetServer: string; fleetServerAddFleetServer: string; diff --git a/src/core/server/core_usage_data/core_usage_data_service.test.ts b/src/core/server/core_usage_data/core_usage_data_service.test.ts index 3c05069d3cd07..209aece3f5719 100644 --- a/src/core/server/core_usage_data/core_usage_data_service.test.ts +++ b/src/core/server/core_usage_data/core_usage_data_service.test.ts @@ -17,7 +17,6 @@ import { mockCoreContext } from '../core_context.mock'; import { config as RawElasticsearchConfig } from '../elasticsearch/elasticsearch_config'; import { config as RawHttpConfig } from '../http/http_config'; import { config as RawLoggingConfig } from '../logging/logging_config'; -import { config as RawKibanaConfig } from '../kibana_config'; import { savedObjectsConfig as RawSavedObjectsConfig } from '../saved_objects/saved_objects_config'; import { httpServiceMock } from '../http/http_service.mock'; import { metricsServiceMock } from '../metrics/metrics_service.mock'; @@ -40,8 +39,6 @@ describe('CoreUsageDataService', () => { return new BehaviorSubject(RawLoggingConfig.schema.validate({})); } else if (path === 'savedObjects') { return new BehaviorSubject(RawSavedObjectsConfig.schema.validate({})); - } else if (path === 'kibana') { - return new BehaviorSubject(RawKibanaConfig.schema.validate({})); } return new BehaviorSubject({}); }; diff --git a/src/core/server/core_usage_data/core_usage_data_service.ts b/src/core/server/core_usage_data/core_usage_data_service.ts index 72b70824d305d..22dafc7e44e06 100644 --- a/src/core/server/core_usage_data/core_usage_data_service.ts +++ b/src/core/server/core_usage_data/core_usage_data_service.ts @@ -33,7 +33,6 @@ import type { } from './types'; import { isConfigured } from './is_configured'; import { ElasticsearchServiceStart } from '../elasticsearch'; -import { KibanaConfigType } from '../kibana_config'; import { coreUsageStatsType } from './core_usage_stats'; import { LEGACY_URL_ALIAS_TYPE } from '../saved_objects/object_types'; import { CORE_USAGE_STATS_TYPE } from './constants'; @@ -56,6 +55,8 @@ export interface StartDeps { exposedConfigsToUsage: ExposedConfigsToUsage; } +const kibanaIndex = '.kibana'; + /** * Because users can configure their Saved Object to any arbitrary index name, * we need to map customized index names back to a "standard" index name. @@ -74,19 +75,6 @@ const kibanaOrTaskManagerIndex = (index: string, kibanaConfigIndex: string) => { return index === kibanaConfigIndex ? '.kibana' : '.kibana_task_manager'; }; -/** - * This is incredibly hacky... The config service doesn't allow you to determine - * whether or not a config value has been changed from the default value, and the - * default value is defined in legacy code. - * - * This will be going away in 8.0, so please look away for a few months - * - * @param index The `kibana.index` setting from the `kibana.yml` - */ -const isCustomIndex = (index: string) => { - return index !== '.kibana'; -}; - export class CoreUsageDataService implements CoreService { @@ -98,7 +86,6 @@ export class CoreUsageDataService private soConfig?: SavedObjectsConfigType; private stop$: Subject; private opsMetrics?: OpsMetrics; - private kibanaConfig?: KibanaConfigType; private coreUsageStatsClient?: CoreUsageStatsClient; private deprecatedConfigPaths: ChangedDeprecatedPaths = { set: [], unset: [] }; private incrementUsageCounter: CoreIncrementUsageCounter = () => {}; // Initially set to noop @@ -133,8 +120,8 @@ export class CoreUsageDataService .getTypeRegistry() .getAllTypes() .reduce((acc, type) => { - const index = type.indexPattern ?? this.kibanaConfig!.index; - return index != null ? acc.add(index) : acc; + const index = type.indexPattern ?? kibanaIndex; + return acc.add(index); }, new Set()) .values() ).map((index) => { @@ -150,7 +137,7 @@ export class CoreUsageDataService .then(({ body }) => { const stats = body[0]; return { - alias: kibanaOrTaskManagerIndex(index, this.kibanaConfig!.index), + alias: kibanaOrTaskManagerIndex(index, kibanaIndex), docsCount: stats['docs.count'] ? parseInt(stats['docs.count'], 10) : 0, docsDeleted: stats['docs.deleted'] ? parseInt(stats['docs.deleted'], 10) : 0, storeSizeBytes: stats['store.size'] ? parseInt(stats['store.size'], 10) : 0, @@ -167,7 +154,7 @@ export class CoreUsageDataService // Note: this agg can be changed to use `savedObjectsRepository.find` in the future after `filters` is supported. // See src/core/server/saved_objects/service/lib/aggregations/aggs_types/bucket_aggs.ts for supported aggregations. const { body: resp } = await elasticsearch.client.asInternalUser.search({ - index: this.kibanaConfig!.index, + index: kibanaIndex, body: { track_total_hits: true, query: { match: { type: LEGACY_URL_ALIAS_TYPE } }, @@ -313,7 +300,7 @@ export class CoreUsageDataService }, savedObjects: { - customIndex: isCustomIndex(this.kibanaConfig!.index), + customIndex: false, maxImportPayloadBytes: this.soConfig.maxImportPayloadBytes.getValueInBytes(), maxImportExportSize: this.soConfig.maxImportExportSize, }, @@ -472,13 +459,6 @@ export class CoreUsageDataService this.soConfig = config; }); - this.configService - .atPath('kibana') - .pipe(takeUntil(this.stop$)) - .subscribe((config) => { - this.kibanaConfig = config; - }); - changedDeprecatedConfigPath$ .pipe(takeUntil(this.stop$)) .subscribe((deprecatedConfigPaths) => (this.deprecatedConfigPaths = deprecatedConfigPaths)); diff --git a/src/core/server/kibana_config.test.ts b/src/core/server/kibana_config.test.ts deleted file mode 100644 index 72ddb3b65081b..0000000000000 --- a/src/core/server/kibana_config.test.ts +++ /dev/null @@ -1,42 +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 { config } from './kibana_config'; -import { getDeprecationsFor } from './config/test_utils'; - -const CONFIG_PATH = 'kibana'; - -const applyKibanaDeprecations = (settings: Record = {}) => - getDeprecationsFor({ - provider: config.deprecations!, - settings, - path: CONFIG_PATH, - }); - -it('set correct defaults ', () => { - const configValue = config.schema.validate({}); - expect(configValue).toMatchInlineSnapshot(` - Object { - "enabled": true, - "index": ".kibana", - } - `); -}); - -describe('deprecations', () => { - ['.foo', '.kibana'].forEach((index) => { - it('logs a warning if index is set', () => { - const { messages } = applyKibanaDeprecations({ index }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "\\"kibana.index\\" is deprecated. Multitenancy by changing \\"kibana.index\\" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details", - ] - `); - }); - }); -}); diff --git a/src/core/server/kibana_config.ts b/src/core/server/kibana_config.ts deleted file mode 100644 index 859f25d7082f1..0000000000000 --- a/src/core/server/kibana_config.ts +++ /dev/null @@ -1,51 +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 { i18n } from '@kbn/i18n'; -import { schema, TypeOf } from '@kbn/config-schema'; -import { ConfigDeprecationProvider } from '@kbn/config'; - -export type KibanaConfigType = TypeOf; - -const deprecations: ConfigDeprecationProvider = () => [ - (settings, fromPath, addDeprecation) => { - const kibana = settings[fromPath]; - if (kibana?.index) { - addDeprecation({ - configPath: 'kibana.index', - title: i18n.translate('core.kibana.index.deprecationTitle', { - defaultMessage: `Setting "kibana.index" is deprecated`, - }), - message: i18n.translate('core.kibana.index.deprecationMessage', { - defaultMessage: `"kibana.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, - }), - documentationUrl: 'https://ela.st/kbn-remove-legacy-multitenancy', - correctiveActions: { - manualSteps: [ - i18n.translate('core.kibana.index.deprecationManualStep1', { - defaultMessage: `If you rely on this setting to achieve multitenancy you should use Spaces, cross-cluster replication, or cross-cluster search instead.`, - }), - i18n.translate('core.kibana.index.deprecationManualStep2', { - defaultMessage: `To migrate to Spaces, we encourage using saved object management to export your saved objects from a tenant into the default tenant in a space.`, - }), - ], - }, - }); - } - return settings; - }, -]; - -export const config = { - path: 'kibana', - schema: schema.object({ - enabled: schema.boolean({ defaultValue: true }), - index: schema.string({ defaultValue: '.kibana' }), - }), - deprecations, -}; diff --git a/src/core/server/mocks.ts b/src/core/server/mocks.ts index 8b4dee45a8e72..a2787369bd534 100644 --- a/src/core/server/mocks.ts +++ b/src/core/server/mocks.ts @@ -65,9 +65,6 @@ type MockedPluginInitializerConfig = jest.Mocked[ export function pluginInitializerContextConfigMock(config: T) { const globalConfig: SharedGlobalConfig = { - kibana: { - index: '.kibana-tests', - }, elasticsearch: { shardTimeout: duration('30s'), requestTimeout: duration('30s'), diff --git a/src/core/server/plugins/legacy_config.test.ts b/src/core/server/plugins/legacy_config.test.ts index 2a980e38a4e19..af8cff843edf0 100644 --- a/src/core/server/plugins/legacy_config.test.ts +++ b/src/core/server/plugins/legacy_config.test.ts @@ -41,9 +41,6 @@ describe('Legacy config', () => { const legacyConfig = getGlobalConfig(configService); expect(legacyConfig).toStrictEqual({ - kibana: { - index: '.kibana', - }, elasticsearch: { shardTimeout: duration(30, 's'), requestTimeout: duration(30, 's'), @@ -62,9 +59,6 @@ describe('Legacy config', () => { const legacyConfig = await getGlobalConfig$(configService).pipe(take(1)).toPromise(); expect(legacyConfig).toStrictEqual({ - kibana: { - index: '.kibana', - }, elasticsearch: { shardTimeout: duration(30, 's'), requestTimeout: duration(30, 's'), diff --git a/src/core/server/plugins/legacy_config.ts b/src/core/server/plugins/legacy_config.ts index f7e22cb4b376a..9dc4afc37515a 100644 --- a/src/core/server/plugins/legacy_config.ts +++ b/src/core/server/plugins/legacy_config.ts @@ -13,7 +13,6 @@ import { pick, deepFreeze } from '@kbn/std'; import { IConfigService } from '@kbn/config'; import { SharedGlobalConfig, SharedGlobalConfigKeys } from './types'; -import { KibanaConfigType, config as kibanaConfig } from '../kibana_config'; import { ElasticsearchConfigType, config as elasticsearchConfig, @@ -21,18 +20,15 @@ import { import { SavedObjectsConfigType, savedObjectsConfig } from '../saved_objects/saved_objects_config'; const createGlobalConfig = ({ - kibana, elasticsearch, path, savedObjects, }: { - kibana: KibanaConfigType; elasticsearch: ElasticsearchConfigType; path: PathConfigType; savedObjects: SavedObjectsConfigType; }): SharedGlobalConfig => { return deepFreeze({ - kibana: pick(kibana, SharedGlobalConfigKeys.kibana), elasticsearch: pick(elasticsearch, SharedGlobalConfigKeys.elasticsearch), path: pick(path, SharedGlobalConfigKeys.path), savedObjects: pick(savedObjects, SharedGlobalConfigKeys.savedObjects), @@ -41,7 +37,6 @@ const createGlobalConfig = ({ export const getGlobalConfig = (configService: IConfigService): SharedGlobalConfig => { return createGlobalConfig({ - kibana: configService.atPathSync(kibanaConfig.path), elasticsearch: configService.atPathSync(elasticsearchConfig.path), path: configService.atPathSync(pathConfig.path), savedObjects: configService.atPathSync(savedObjectsConfig.path), @@ -50,15 +45,13 @@ export const getGlobalConfig = (configService: IConfigService): SharedGlobalConf export const getGlobalConfig$ = (configService: IConfigService): Observable => { return combineLatest([ - configService.atPath(kibanaConfig.path), configService.atPath(elasticsearchConfig.path), configService.atPath(pathConfig.path), configService.atPath(savedObjectsConfig.path), ]).pipe( map( - ([kibana, elasticsearch, path, savedObjects]) => + ([elasticsearch, path, savedObjects]) => createGlobalConfig({ - kibana, elasticsearch, path, savedObjects, diff --git a/src/core/server/plugins/plugin_context.test.ts b/src/core/server/plugins/plugin_context.test.ts index 00da0fa43c40f..867d4d978314b 100644 --- a/src/core/server/plugins/plugin_context.test.ts +++ b/src/core/server/plugins/plugin_context.test.ts @@ -124,9 +124,6 @@ describe('createPluginInitializerContext', () => { .pipe(first()) .toPromise(); expect(configObject).toStrictEqual({ - kibana: { - index: '.kibana', - }, elasticsearch: { shardTimeout: duration(30, 's'), requestTimeout: duration(30, 's'), diff --git a/src/core/server/plugins/plugin_context.ts b/src/core/server/plugins/plugin_context.ts index bdb4efde9b1fb..28382d62e4ba7 100644 --- a/src/core/server/plugins/plugin_context.ts +++ b/src/core/server/plugins/plugin_context.ts @@ -197,6 +197,7 @@ export function createPluginSetupContext( setClientFactoryProvider: deps.savedObjects.setClientFactoryProvider, addClientWrapper: deps.savedObjects.addClientWrapper, registerType: deps.savedObjects.registerType, + getKibanaIndex: deps.savedObjects.getKibanaIndex, }, status: { core$: deps.status.core$, diff --git a/src/core/server/plugins/types.ts b/src/core/server/plugins/types.ts index a2e460a3e3c67..1d0dc62864fc9 100644 --- a/src/core/server/plugins/types.ts +++ b/src/core/server/plugins/types.ts @@ -13,7 +13,6 @@ import { PathConfigType } from '@kbn/utils'; import { ConfigPath, EnvironmentMode, PackageInfo, ConfigDeprecationProvider } from '../config'; import { LoggerFactory } from '../logging'; -import { KibanaConfigType } from '../kibana_config'; import { ElasticsearchConfigType } from '../elasticsearch/elasticsearch_config'; import { SavedObjectsConfigType } from '../saved_objects/saved_objects_config'; import { CorePreboot, CoreSetup, CoreStart } from '..'; @@ -364,7 +363,6 @@ export interface AsyncPlugin< export const SharedGlobalConfigKeys = { // We can add more if really needed - kibana: ['index'] as const, elasticsearch: ['shardTimeout', 'requestTimeout', 'pingTimeout'] as const, path: ['data'] as const, savedObjects: ['maxImportPayloadBytes'] as const, @@ -374,7 +372,6 @@ export const SharedGlobalConfigKeys = { * @public */ export type SharedGlobalConfig = RecursiveReadonly<{ - kibana: Pick; elasticsearch: Pick; path: Pick; savedObjects: Pick; diff --git a/src/core/server/saved_objects/deprecations/deprecation_factory.ts b/src/core/server/saved_objects/deprecations/deprecation_factory.ts index 670b43bfa7c77..60ee1b0193362 100644 --- a/src/core/server/saved_objects/deprecations/deprecation_factory.ts +++ b/src/core/server/saved_objects/deprecations/deprecation_factory.ts @@ -9,13 +9,12 @@ import type { RegisterDeprecationsConfig } from '../../deprecations'; import type { ISavedObjectTypeRegistry } from '../saved_objects_type_registry'; import type { SavedObjectConfig } from '../saved_objects_config'; -import type { KibanaConfigType } from '../../kibana_config'; import { getUnknownTypesDeprecations } from './unknown_object_types'; interface GetDeprecationProviderOptions { typeRegistry: ISavedObjectTypeRegistry; savedObjectsConfig: SavedObjectConfig; - kibanaConfig: KibanaConfigType; + kibanaIndex: string; kibanaVersion: string; } diff --git a/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts b/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts index 1f9ca741691d1..3f8fce0bc1c87 100644 --- a/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts +++ b/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts @@ -12,7 +12,6 @@ import { estypes } from '@elastic/elasticsearch'; import { deleteUnknownTypeObjects, getUnknownTypesDeprecations } from './unknown_object_types'; import { typeRegistryMock } from '../saved_objects_type_registry.mock'; import { elasticsearchClientMock } from '../../elasticsearch/client/mocks'; -import type { KibanaConfigType } from '../../kibana_config'; import { SavedObjectsType } from 'kibana/server'; const createSearchResponse = (count: number): estypes.SearchResponse => { @@ -30,7 +29,7 @@ describe('unknown saved object types deprecation', () => { let typeRegistry: ReturnType; let esClient: ReturnType; - let kibanaConfig: KibanaConfigType; + const kibanaIndex = '.kibana'; beforeEach(() => { typeRegistry = typeRegistryMock.create(); @@ -41,11 +40,6 @@ describe('unknown saved object types deprecation', () => { { name: 'bar' }, ] as SavedObjectsType[]); getIndexForTypeMock.mockImplementation(({ type }: { type: string }) => `${type}-index`); - - kibanaConfig = { - index: '.kibana', - enabled: true, - }; }); afterEach(() => { @@ -63,7 +57,7 @@ describe('unknown saved object types deprecation', () => { await getUnknownTypesDeprecations({ esClient, typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }); @@ -89,7 +83,7 @@ describe('unknown saved object types deprecation', () => { const deprecations = await getUnknownTypesDeprecations({ esClient, typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }); @@ -104,7 +98,7 @@ describe('unknown saved object types deprecation', () => { const deprecations = await getUnknownTypesDeprecations({ esClient, typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }); @@ -132,7 +126,7 @@ describe('unknown saved object types deprecation', () => { await deleteUnknownTypeObjects({ esClient, typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }); diff --git a/src/core/server/saved_objects/deprecations/unknown_object_types.ts b/src/core/server/saved_objects/deprecations/unknown_object_types.ts index 8cd650bac8a2d..1b34dcad64010 100644 --- a/src/core/server/saved_objects/deprecations/unknown_object_types.ts +++ b/src/core/server/saved_objects/deprecations/unknown_object_types.ts @@ -12,13 +12,12 @@ import type { DeprecationsDetails } from '../../deprecations'; import { IScopedClusterClient } from '../../elasticsearch'; import { ISavedObjectTypeRegistry } from '../saved_objects_type_registry'; import { SavedObjectsRawDocSource } from '../serialization'; -import type { KibanaConfigType } from '../../kibana_config'; import { getIndexForType } from '../service/lib'; interface UnknownTypesDeprecationOptions { typeRegistry: ISavedObjectTypeRegistry; esClient: IScopedClusterClient; - kibanaConfig: KibanaConfigType; + kibanaIndex: string; kibanaVersion: string; } @@ -29,11 +28,11 @@ const getTargetIndices = ({ types, typeRegistry, kibanaVersion, - kibanaConfig, + kibanaIndex, }: { types: string[]; typeRegistry: ISavedObjectTypeRegistry; - kibanaConfig: KibanaConfigType; + kibanaIndex: string; kibanaVersion: string; }) => { return [ @@ -43,7 +42,7 @@ const getTargetIndices = ({ type, typeRegistry, kibanaVersion, - defaultIndex: kibanaConfig.index, + defaultIndex: kibanaIndex, }) ) ), @@ -63,14 +62,14 @@ const getUnknownTypesQuery = (knownTypes: string[]): estypes.QueryDslQueryContai const getUnknownSavedObjects = async ({ typeRegistry, esClient, - kibanaConfig, + kibanaIndex, kibanaVersion, }: UnknownTypesDeprecationOptions) => { const knownTypes = getKnownTypes(typeRegistry); const targetIndices = getTargetIndices({ types: knownTypes, typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }); const query = getUnknownTypesQuery(knownTypes); @@ -133,21 +132,21 @@ export const getUnknownTypesDeprecations = async ( interface DeleteUnknownTypesOptions { typeRegistry: ISavedObjectTypeRegistry; esClient: IScopedClusterClient; - kibanaConfig: KibanaConfigType; + kibanaIndex: string; kibanaVersion: string; } export const deleteUnknownTypeObjects = async ({ esClient, typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }: DeleteUnknownTypesOptions) => { const knownTypes = getKnownTypes(typeRegistry); const targetIndices = getTargetIndices({ types: knownTypes, typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }); const query = getUnknownTypesQuery(knownTypes); diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts index c397559b52570..90274de557fdf 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts @@ -16,6 +16,7 @@ import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import { SavedObjectsType } from '../../types'; import { DocumentMigrator } from '../core/document_migrator'; import { ByteSizeValue } from '@kbn/config-schema'; + jest.mock('../core/document_migrator', () => { return { // Create a mock for spying on the constructor @@ -304,10 +305,7 @@ const mockOptions = () => { migrations: {}, }, ]), - kibanaConfig: { - enabled: true, - index: '.my-index', - } as KibanaMigratorOptions['kibanaConfig'], + kibanaIndex: '.my-index', soMigrationsConfig: { batchSize: 20, maxBatchSizeBytes: ByteSizeValue.parse('20mb'), diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts index d3755f8c7e666..a812339cef07e 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.ts @@ -13,7 +13,6 @@ import { BehaviorSubject } from 'rxjs'; import Semver from 'semver'; -import { KibanaConfigType } from '../../../kibana_config'; import { ElasticsearchClient } from '../../../elasticsearch'; import { Logger } from '../../../logging'; import { IndexMapping, SavedObjectsTypeMappingDefinitions } from '../../mappings'; @@ -35,7 +34,7 @@ export interface KibanaMigratorOptions { client: ElasticsearchClient; typeRegistry: ISavedObjectTypeRegistry; soMigrationsConfig: SavedObjectsMigrationConfigType; - kibanaConfig: KibanaConfigType; + kibanaIndex: string; kibanaVersion: string; logger: Logger; migrationsRetryDelay?: number; @@ -55,7 +54,7 @@ export interface KibanaMigratorStatus { export class KibanaMigrator { private readonly client: ElasticsearchClient; private readonly documentMigrator: VersionedTransformer; - private readonly kibanaConfig: KibanaConfigType; + private readonly kibanaIndex: string; private readonly log: Logger; private readonly mappingProperties: SavedObjectsTypeMappingDefinitions; private readonly typeRegistry: ISavedObjectTypeRegistry; @@ -76,14 +75,14 @@ export class KibanaMigrator { constructor({ client, typeRegistry, - kibanaConfig, + kibanaIndex, soMigrationsConfig, kibanaVersion, logger, migrationsRetryDelay, }: KibanaMigratorOptions) { this.client = client; - this.kibanaConfig = kibanaConfig; + this.kibanaIndex = kibanaIndex; this.soMigrationsConfig = soMigrationsConfig; this.typeRegistry = typeRegistry; this.serializer = new SavedObjectsSerializer(this.typeRegistry); @@ -148,9 +147,8 @@ export class KibanaMigrator { } private runMigrationsInternal() { - const kibanaIndexName = this.kibanaConfig.index; const indexMap = createIndexMap({ - kibanaIndexName, + kibanaIndexName: this.kibanaIndex, indexMap: this.mappingProperties, registry: this.typeRegistry, }); diff --git a/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts b/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts index 2b6d64bef4f1a..97100980a37b3 100644 --- a/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts +++ b/src/core/server/saved_objects/routes/deprecations/delete_unknown_types.ts @@ -9,16 +9,15 @@ import { IRouter } from '../../../http'; import { catchAndReturnBoomErrors } from '../utils'; import { deleteUnknownTypeObjects } from '../../deprecations'; -import { KibanaConfigType } from '../../../kibana_config'; interface RouteDependencies { - kibanaConfig: KibanaConfigType; + kibanaIndex: string; kibanaVersion: string; } export const registerDeleteUnknownTypesRoute = ( router: IRouter, - { kibanaConfig, kibanaVersion }: RouteDependencies + { kibanaIndex, kibanaVersion }: RouteDependencies ) => { router.post( { @@ -29,7 +28,7 @@ export const registerDeleteUnknownTypesRoute = ( await deleteUnknownTypeObjects({ esClient: context.core.elasticsearch.client, typeRegistry: context.core.savedObjects.typeRegistry, - kibanaConfig, + kibanaIndex, kibanaVersion, }); return res.ok({ diff --git a/src/core/server/saved_objects/routes/index.ts b/src/core/server/saved_objects/routes/index.ts index a85070867ae8f..41ad9ff24c30c 100644 --- a/src/core/server/saved_objects/routes/index.ts +++ b/src/core/server/saved_objects/routes/index.ts @@ -28,7 +28,6 @@ import { registerLegacyImportRoute } from './legacy_import_export/import'; import { registerLegacyExportRoute } from './legacy_import_export/export'; import { registerBulkResolveRoute } from './bulk_resolve'; import { registerDeleteUnknownTypesRoute } from './deprecations'; -import { KibanaConfigType } from '../../kibana_config'; export function registerRoutes({ http, @@ -37,7 +36,7 @@ export function registerRoutes({ config, migratorPromise, kibanaVersion, - kibanaConfig, + kibanaIndex, }: { http: InternalHttpServiceSetup; coreUsageData: InternalCoreUsageDataSetup; @@ -45,7 +44,7 @@ export function registerRoutes({ config: SavedObjectConfig; migratorPromise: Promise; kibanaVersion: string; - kibanaConfig: KibanaConfigType; + kibanaIndex: string; }) { const router = http.createRouter('/api/saved_objects/'); @@ -74,5 +73,5 @@ export function registerRoutes({ const internalRouter = http.createRouter('/internal/saved_objects/'); registerMigrateRoute(internalRouter, migratorPromise); - registerDeleteUnknownTypesRoute(internalRouter, { kibanaConfig, kibanaVersion }); + registerDeleteUnknownTypesRoute(internalRouter, { kibanaIndex, kibanaVersion }); } diff --git a/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts b/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts index 0c7fbdda89fbf..ef1c711536b00 100644 --- a/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts +++ b/src/core/server/saved_objects/routes/integration_tests/delete_unknown_types.test.ts @@ -12,17 +12,13 @@ import { registerDeleteUnknownTypesRoute } from '../deprecations'; import { elasticsearchServiceMock } from '../../../../../core/server/elasticsearch/elasticsearch_service.mock'; import { typeRegistryMock } from '../../saved_objects_type_registry.mock'; import { setupServer } from '../test_utils'; -import { KibanaConfigType } from '../../../kibana_config'; import { SavedObjectsType } from 'kibana/server'; type SetupServerReturn = UnwrapPromise>; describe('POST /internal/saved_objects/deprecations/_delete_unknown_types', () => { const kibanaVersion = '8.0.0'; - const kibanaConfig: KibanaConfigType = { - enabled: true, - index: '.kibana', - }; + const kibanaIndex = '.kibana'; let server: SetupServerReturn['server']; let httpSetup: SetupServerReturn['httpSetup']; @@ -45,7 +41,7 @@ describe('POST /internal/saved_objects/deprecations/_delete_unknown_types', () = const router = httpSetup.createRouter('/internal/saved_objects/'); registerDeleteUnknownTypesRoute(router, { kibanaVersion, - kibanaConfig, + kibanaIndex, }); await server.start(); diff --git a/src/core/server/saved_objects/saved_objects_config.test.ts b/src/core/server/saved_objects/saved_objects_config.test.ts deleted file mode 100644 index 06b9e9661b746..0000000000000 --- a/src/core/server/saved_objects/saved_objects_config.test.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 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 { savedObjectsMigrationConfig } from './saved_objects_config'; -import { getDeprecationsFor } from '../config/test_utils'; - -const applyMigrationsDeprecations = (settings: Record = {}) => - getDeprecationsFor({ - provider: savedObjectsMigrationConfig.deprecations!, - settings, - path: 'migrations', - }); - -describe('migrations config', function () { - describe('deprecations', () => { - it('logs a warning if migrations.enableV2 is set: true', () => { - const { messages } = applyMigrationsDeprecations({ enableV2: true }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "You no longer need to configure \\"migrations.enableV2\\".", - ] - `); - }); - - it('logs a warning if migrations.enableV2 is set: false', () => { - const { messages } = applyMigrationsDeprecations({ enableV2: false }); - expect(messages).toMatchInlineSnapshot(` - Array [ - "You no longer need to configure \\"migrations.enableV2\\".", - ] - `); - }); - }); - - it('does not log a warning if migrations.enableV2 is not set', () => { - const { messages } = applyMigrationsDeprecations({ batchSize: 1_000 }); - expect(messages).toMatchInlineSnapshot(`Array []`); - }); -}); diff --git a/src/core/server/saved_objects/saved_objects_config.ts b/src/core/server/saved_objects/saved_objects_config.ts index 02fbd974da4ae..e5dc64186f66d 100644 --- a/src/core/server/saved_objects/saved_objects_config.ts +++ b/src/core/server/saved_objects/saved_objects_config.ts @@ -7,7 +7,6 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import { ConfigDeprecationProvider } from '../config'; import type { ServiceConfigDescriptor } from '../internal_types'; const migrationSchema = schema.object({ @@ -21,13 +20,10 @@ const migrationSchema = schema.object({ export type SavedObjectsMigrationConfigType = TypeOf; -const migrationDeprecations: ConfigDeprecationProvider = ({ unused }) => [unused('enableV2')]; - export const savedObjectsMigrationConfig: ServiceConfigDescriptor = { path: 'migrations', schema: migrationSchema, - deprecations: migrationDeprecations, }; const soSchema = schema.object({ diff --git a/src/core/server/saved_objects/saved_objects_service.mock.ts b/src/core/server/saved_objects/saved_objects_service.mock.ts index cd7310e226f63..fd04d917ebb9c 100644 --- a/src/core/server/saved_objects/saved_objects_service.mock.ts +++ b/src/core/server/saved_objects/saved_objects_service.mock.ts @@ -60,8 +60,11 @@ const createSetupContractMock = () => { setClientFactoryProvider: jest.fn(), addClientWrapper: jest.fn(), registerType: jest.fn(), + getKibanaIndex: jest.fn(), }; + setupContract.getKibanaIndex.mockReturnValue('.kibana'); + return setupContract; }; diff --git a/src/core/server/saved_objects/saved_objects_service.ts b/src/core/server/saved_objects/saved_objects_service.ts index 534718bd683b8..33d75c38f4369 100644 --- a/src/core/server/saved_objects/saved_objects_service.ts +++ b/src/core/server/saved_objects/saved_objects_service.ts @@ -23,7 +23,6 @@ import { InternalElasticsearchServiceStart, } from '../elasticsearch'; import { InternalDeprecationsServiceSetup } from '../deprecations'; -import { KibanaConfigType } from '../kibana_config'; import { SavedObjectsConfigType, SavedObjectsMigrationConfigType, @@ -47,6 +46,8 @@ import { calculateStatus$ } from './status'; import { registerCoreObjectTypes } from './object_types'; import { getSavedObjectsDeprecationsProvider } from './deprecations'; +const kibanaIndex = '.kibana'; + /** * Saved Objects is Kibana's data persistence mechanism allowing plugins to * use Elasticsearch for storing and querying state. The SavedObjectsServiceSetup API exposes methods @@ -144,6 +145,11 @@ export interface SavedObjectsServiceSetup { * ``` */ registerType: (type: SavedObjectsType) => void; + + /** + * Returns the default index used for saved objects. + */ + getKibanaIndex: () => string; } /** @@ -302,14 +308,9 @@ export class SavedObjectsService .toPromise(); this.config = new SavedObjectConfig(savedObjectsConfig, savedObjectsMigrationConfig); - const kibanaConfig = await this.coreContext.configService - .atPath('kibana') - .pipe(first()) - .toPromise(); - deprecations.getRegistry('savedObjects').registerDeprecations( getSavedObjectsDeprecationsProvider({ - kibanaConfig, + kibanaIndex, savedObjectsConfig: this.config, kibanaVersion: this.coreContext.env.packageInfo.version, typeRegistry: this.typeRegistry, @@ -324,7 +325,7 @@ export class SavedObjectsService logger: this.logger, config: this.config, migratorPromise: this.migrator$.pipe(first()).toPromise(), - kibanaConfig, + kibanaIndex, kibanaVersion: this.coreContext.env.packageInfo.version, }); @@ -361,6 +362,7 @@ export class SavedObjectsService this.typeRegistry.registerType(type); }, getTypeRegistry: () => this.typeRegistry, + getKibanaIndex: () => kibanaIndex, }; } @@ -374,14 +376,9 @@ export class SavedObjectsService this.logger.debug('Starting SavedObjects service'); - const kibanaConfig = await this.coreContext.configService - .atPath('kibana') - .pipe(first()) - .toPromise(); const client = elasticsearch.client; const migrator = this.createMigrator( - kibanaConfig, this.config.migration, elasticsearch.client.asInternalUser, migrationsRetryDelay @@ -442,7 +439,7 @@ export class SavedObjectsService return SavedObjectsRepository.createRepository( migrator, this.typeRegistry, - kibanaConfig.index, + kibanaIndex, esClient, this.logger.get('repository'), includedHiddenTypes @@ -498,7 +495,6 @@ export class SavedObjectsService public async stop() {} private createMigrator( - kibanaConfig: KibanaConfigType, soMigrationsConfig: SavedObjectsMigrationConfigType, client: ElasticsearchClient, migrationsRetryDelay?: number @@ -508,7 +504,7 @@ export class SavedObjectsService logger: this.logger, kibanaVersion: this.coreContext.env.packageInfo.version, soMigrationsConfig, - kibanaConfig, + kibanaIndex, client, migrationsRetryDelay, }); diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 9e50a3008293b..632fea5c6660d 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2704,6 +2704,7 @@ export class SavedObjectsSerializer { // @public export interface SavedObjectsServiceSetup { addClientWrapper: (priority: number, id: string, factory: SavedObjectsClientWrapperFactory) => void; + getKibanaIndex: () => string; registerType: (type: SavedObjectsType) => void; setClientFactoryProvider: (clientFactoryProvider: SavedObjectsClientFactoryProvider) => void; } @@ -2977,7 +2978,6 @@ export interface ShardsResponse { // @public (undocumented) export type SharedGlobalConfig = RecursiveReadonly<{ - kibana: Pick; elasticsearch: Pick; path: Pick; savedObjects: Pick; @@ -3052,9 +3052,8 @@ export const validBodyOutput: readonly ["data", "stream"]; // // src/core/server/elasticsearch/client/types.ts:94:7 - (ae-forgotten-export) The symbol "Explanation" needs to be exported by the entry point index.d.ts // src/core/server/http/router/response.ts:302:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:377:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:377:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:380:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts -// src/core/server/plugins/types.ts:486:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "create" +// src/core/server/plugins/types.ts:375:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts +// src/core/server/plugins/types.ts:377:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts +// src/core/server/plugins/types.ts:483:5 - (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "create" ``` diff --git a/src/core/server/server.ts b/src/core/server/server.ts index 2d3b87207fcbe..e8c7ce6abb029 100644 --- a/src/core/server/server.ts +++ b/src/core/server/server.ts @@ -36,7 +36,6 @@ import { config as cspConfig } from './csp'; import { config as elasticsearchConfig } from './elasticsearch'; import { config as httpConfig } from './http'; import { config as loggingConfig } from './logging'; -import { config as kibanaConfig } from './kibana_config'; import { savedObjectsConfig, savedObjectsMigrationConfig } from './saved_objects'; import { config as uiSettingsConfig } from './ui_settings'; import { config as statusConfig } from './status'; @@ -373,7 +372,6 @@ export class Server { loggingConfig, httpConfig, pluginsConfig, - kibanaConfig, savedObjectsConfig, savedObjectsMigrationConfig, uiSettingsConfig, diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index 235a5fbe1a1a3..3a38789fbcac6 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -343,7 +343,6 @@ kibana_vars=( xpack.security.authc.saml.realm xpack.security.authc.selector.enabled xpack.security.cookieName - xpack.security.enabled xpack.security.encryptionKey xpack.security.loginAssistanceMessage xpack.security.loginHelp diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index efa54e74fdf2f..305eeb9a6a358 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -75,6 +75,6 @@ export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint '@elastic/ems-client@7.16.0': ['Elastic License 2.0'], - '@elastic/eui@39.1.1': ['SSPL-1.0 OR Elastic License 2.0'], + '@elastic/eui@40.0.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx index c3b4075690261..3237eb106e4ec 100644 --- a/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx +++ b/src/plugins/dashboard/public/application/hooks/use_dashboard_app_state.test.tsx @@ -206,7 +206,9 @@ describe('Dashboard container lifecycle', () => { }); }); -describe('Dashboard initial state', () => { +// FLAKY: https://github.com/elastic/kibana/issues/116050 +// FLAKY: https://github.com/elastic/kibana/issues/105018 +describe.skip('Dashboard initial state', () => { it('Extracts state from Dashboard Saved Object', async () => { const { renderHookResult, embeddableFactoryResult } = renderDashboardAppStateHook({}); const getResult = () => renderHookResult.result.current; @@ -276,7 +278,8 @@ describe('Dashboard initial state', () => { }); }); -describe('Dashboard state sync', () => { +// FLAKY: https://github.com/elastic/kibana/issues/116043 +describe.skip('Dashboard state sync', () => { let defaultDashboardAppStateHookResult: RenderDashboardStateHookReturn; const getResult = () => defaultDashboardAppStateHookResult.renderHookResult.result.current; diff --git a/src/plugins/data/common/constants.ts b/src/plugins/data/common/constants.ts index e141bfbef3c89..1c457fdb64ce2 100644 --- a/src/plugins/data/common/constants.ts +++ b/src/plugins/data/common/constants.ts @@ -35,4 +35,5 @@ export const UI_SETTINGS = { AUTOCOMPLETE_USE_TIMERANGE: 'autocomplete:useTimeRange', AUTOCOMPLETE_VALUE_SUGGESTION_METHOD: 'autocomplete:valueSuggestionMethod', DATE_FORMAT: 'dateFormat', + DATEFORMAT_TZ: 'dateFormat:tz', } as const; diff --git a/src/plugins/data/common/query/persistable_state.test.ts b/src/plugins/data/common/query/persistable_state.test.ts index 807cc72a071be..93f14a0fc2e08 100644 --- a/src/plugins/data/common/query/persistable_state.test.ts +++ b/src/plugins/data/common/query/persistable_state.test.ts @@ -8,6 +8,7 @@ import { extract, inject } from './persistable_state'; import { Filter } from '@kbn/es-query'; +import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../../common'; describe('filter manager persistable state tests', () => { const filters: Filter[] = [ @@ -15,13 +16,15 @@ describe('filter manager persistable state tests', () => { ]; describe('reference injection', () => { test('correctly inserts reference to filter', () => { - const updatedFilters = inject(filters, [{ type: 'index_pattern', name: 'test', id: '123' }]); + const updatedFilters = inject(filters, [ + { type: DATA_VIEW_SAVED_OBJECT_TYPE, name: 'test', id: '123' }, + ]); expect(updatedFilters[0]).toHaveProperty('meta.index', '123'); }); test('drops index setting if reference is missing', () => { const updatedFilters = inject(filters, [ - { type: 'index_pattern', name: 'test123', id: '123' }, + { type: DATA_VIEW_SAVED_OBJECT_TYPE, name: 'test123', id: '123' }, ]); expect(updatedFilters[0]).toHaveProperty('meta.index', undefined); }); diff --git a/src/plugins/data/common/query/persistable_state.ts b/src/plugins/data/common/query/persistable_state.ts index 934d481685db4..177aae391c4fb 100644 --- a/src/plugins/data/common/query/persistable_state.ts +++ b/src/plugins/data/common/query/persistable_state.ts @@ -8,7 +8,9 @@ import uuid from 'uuid'; import { Filter } from '@kbn/es-query'; +import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../../common'; import { SavedObjectReference } from '../../../../core/types'; +import { MigrateFunctionsObject } from '../../../kibana_utils/common'; export const extract = (filters: Filter[]) => { const references: SavedObjectReference[] = []; @@ -16,7 +18,7 @@ export const extract = (filters: Filter[]) => { if (filter.meta?.index) { const id = uuid(); references.push({ - type: 'index_pattern', + type: DATA_VIEW_SAVED_OBJECT_TYPE, name: id, id: filter.meta.index, }); @@ -54,6 +56,10 @@ export const telemetry = (filters: Filter[], collector: unknown) => { return {}; }; -export const getAllMigrations = () => { +export const migrateToLatest = (filters: Filter[], version: string) => { + return filters; +}; + +export const getAllMigrations = (): MigrateFunctionsObject => { return {}; }; diff --git a/src/plugins/data/common/query/types.ts b/src/plugins/data/common/query/types.ts index c1861beb1ed90..fea59ea558a35 100644 --- a/src/plugins/data/common/query/types.ts +++ b/src/plugins/data/common/query/types.ts @@ -6,6 +6,25 @@ * Side Public License, v 1. */ -export * from './timefilter/types'; +import type { Query, Filter } from '@kbn/es-query'; +import type { RefreshInterval, TimeRange } from './timefilter/types'; -export { Query } from '@kbn/es-query'; +export type { RefreshInterval, TimeRange, TimeRangeBounds } from './timefilter/types'; +export type { Query } from '@kbn/es-query'; + +export type SavedQueryTimeFilter = TimeRange & { + refreshInterval: RefreshInterval; +}; + +export interface SavedQuery { + id: string; + attributes: SavedQueryAttributes; +} + +export interface SavedQueryAttributes { + title: string; + description: string; + query: Query; + filters?: Filter[]; + timefilter?: SavedQueryTimeFilter; +} diff --git a/src/plugins/data/common/search/aggs/param_types/json.test.ts b/src/plugins/data/common/search/aggs/param_types/json.test.ts index 1b3af5b92c26b..8e71cf4657e1f 100644 --- a/src/plugins/data/common/search/aggs/param_types/json.test.ts +++ b/src/plugins/data/common/search/aggs/param_types/json.test.ts @@ -67,10 +67,34 @@ describe('JSON', function () { aggParam.write(aggConfig, output); expect(aggConfig.params).toHaveProperty(paramName); - expect(output.params).toEqual({ - existing: 'true', - new_param: 'should exist in output', - }); + expect(output.params).toMatchInlineSnapshot(` + Object { + "existing": "true", + "new_param": "should exist in output", + } + `); + }); + + it('should append param when valid JSON with triple quotes', () => { + const aggParam = initAggParam(); + const jsonData = `{ + "a": """ + multiline string - line 1 + """ + }`; + + aggConfig.params[paramName] = jsonData; + + aggParam.write(aggConfig, output); + expect(aggConfig.params).toHaveProperty(paramName); + + expect(output.params).toMatchInlineSnapshot(` + Object { + "a": " + multiline string - line 1 + ", + } + `); }); it('should not overwrite existing params', () => { diff --git a/src/plugins/data/common/search/aggs/param_types/json.ts b/src/plugins/data/common/search/aggs/param_types/json.ts index 1678b6586ce80..f499286140af1 100644 --- a/src/plugins/data/common/search/aggs/param_types/json.ts +++ b/src/plugins/data/common/search/aggs/param_types/json.ts @@ -11,6 +11,17 @@ import _ from 'lodash'; import { IAggConfig } from '../agg_config'; import { BaseParamType } from './base'; +function collapseLiteralStrings(xjson: string) { + const tripleQuotes = '"""'; + const splitData = xjson.split(tripleQuotes); + + for (let idx = 1; idx < splitData.length - 1; idx += 2) { + splitData[idx] = JSON.stringify(splitData[idx]); + } + + return splitData.join(''); +} + export class JsonParamType extends BaseParamType { constructor(config: Record) { super(config); @@ -26,9 +37,8 @@ export class JsonParamType extends BaseParamType { return; } - // handle invalid Json input try { - paramJson = JSON.parse(param); + paramJson = JSON.parse(collapseLiteralStrings(param)); } catch (err) { return; } diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 4a55cc2a0d511..25f649f69a052 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -130,7 +130,7 @@ export class DataPublicPlugin core: CoreStart, { uiActions, fieldFormats, dataViews }: DataStartDependencies ): DataPublicPluginStart { - const { uiSettings, notifications, savedObjects, overlays } = core; + const { uiSettings, notifications, overlays } = core; setNotifications(notifications); setOverlays(overlays); setUiSettings(uiSettings); @@ -138,7 +138,7 @@ export class DataPublicPlugin const query = this.queryService.start({ storage: this.storage, - savedObjectsClient: savedObjects.client, + http: core.http, uiSettings, }); diff --git a/src/plugins/data/public/query/query_service.ts b/src/plugins/data/public/query/query_service.ts index 5104a934fdec8..314f13e3524db 100644 --- a/src/plugins/data/public/query/query_service.ts +++ b/src/plugins/data/public/query/query_service.ts @@ -7,7 +7,7 @@ */ import { share } from 'rxjs/operators'; -import { IUiSettingsClient, SavedObjectsClientContract } from 'src/core/public'; +import { HttpStart, IUiSettingsClient } from 'src/core/public'; import { IStorageWrapper } from 'src/plugins/kibana_utils/public'; import { buildEsQuery } from '@kbn/es-query'; import { FilterManager } from './filter_manager'; @@ -15,7 +15,7 @@ import { createAddToQueryLog } from './lib'; import { TimefilterService, TimefilterSetup } from './timefilter'; import { createSavedQueryService } from './saved_query/saved_query_service'; import { createQueryStateObservable } from './state_sync/create_global_query_observable'; -import { QueryStringManager, QueryStringContract } from './query_string'; +import { QueryStringContract, QueryStringManager } from './query_string'; import { getEsQueryConfig, TimeRange } from '../../common'; import { getUiSettings } from '../services'; import { NowProviderInternalContract } from '../now_provider'; @@ -33,9 +33,9 @@ interface QueryServiceSetupDependencies { } interface QueryServiceStartDependencies { - savedObjectsClient: SavedObjectsClientContract; storage: IStorageWrapper; uiSettings: IUiSettingsClient; + http: HttpStart; } export class QueryService { @@ -70,7 +70,7 @@ export class QueryService { }; } - public start({ savedObjectsClient, storage, uiSettings }: QueryServiceStartDependencies) { + public start({ storage, uiSettings, http }: QueryServiceStartDependencies) { return { addToQueryLog: createAddToQueryLog({ storage, @@ -78,7 +78,7 @@ export class QueryService { }), filterManager: this.filterManager, queryString: this.queryStringManager, - savedQueries: createSavedQueryService(savedObjectsClient), + savedQueries: createSavedQueryService(http), state$: this.state$, timefilter: this.timefilter, getEsQuery: (indexPattern: IndexPattern, timeRange?: TimeRange) => { diff --git a/src/plugins/data/public/query/saved_query/saved_query_service.test.ts b/src/plugins/data/public/query/saved_query/saved_query_service.test.ts index 673a86df98881..047051c302083 100644 --- a/src/plugins/data/public/query/saved_query/saved_query_service.test.ts +++ b/src/plugins/data/public/query/saved_query/saved_query_service.test.ts @@ -7,8 +7,20 @@ */ import { createSavedQueryService } from './saved_query_service'; -import { FilterStateStore } from '../../../common'; -import { SavedQueryAttributes } from './types'; +import { httpServiceMock } from '../../../../../core/public/mocks'; +import { SavedQueryAttributes } from '../../../common'; + +const http = httpServiceMock.createStartContract(); + +const { + deleteSavedQuery, + getSavedQuery, + findSavedQueries, + createQuery, + updateQuery, + getAllSavedQueries, + getSavedQueryCount, +} = createSavedQueryService(http); const savedQueryAttributes: SavedQueryAttributes = { title: 'foo', @@ -17,416 +29,90 @@ const savedQueryAttributes: SavedQueryAttributes = { language: 'kuery', query: 'response:200', }, -}; -const savedQueryAttributesBar: SavedQueryAttributes = { - title: 'bar', - description: 'baz', - query: { - language: 'kuery', - query: 'response:200', - }, -}; - -const savedQueryAttributesWithFilters: SavedQueryAttributes = { - ...savedQueryAttributes, - filters: [ - { - query: { match_all: {} }, - $state: { store: FilterStateStore.APP_STATE }, - meta: { - disabled: false, - negate: false, - alias: null, - }, - }, - ], - timefilter: { - to: 'now', - from: 'now-15m', - refreshInterval: { - pause: false, - value: 0, - }, - }, + filters: [], }; -const mockSavedObjectsClient = { - create: jest.fn(), - error: jest.fn(), - find: jest.fn(), - resolve: jest.fn(), - delete: jest.fn(), -}; - -const { - deleteSavedQuery, - getSavedQuery, - findSavedQueries, - saveQuery, - getAllSavedQueries, - getSavedQueryCount, -} = createSavedQueryService( - // @ts-ignore - mockSavedObjectsClient -); - describe('saved query service', () => { afterEach(() => { - mockSavedObjectsClient.create.mockReset(); - mockSavedObjectsClient.find.mockReset(); - mockSavedObjectsClient.resolve.mockReset(); - mockSavedObjectsClient.delete.mockReset(); + http.post.mockReset(); + http.get.mockReset(); + http.delete.mockReset(); }); - describe('saveQuery', function () { - it('should create a saved object for the given attributes', async () => { - mockSavedObjectsClient.create.mockReturnValue({ - id: 'foo', - attributes: savedQueryAttributes, + describe('createQuery', function () { + it('should post the stringified given attributes', async () => { + await createQuery(savedQueryAttributes); + expect(http.post).toBeCalled(); + expect(http.post).toHaveBeenCalledWith('/api/saved_query/_create', { + body: '{"title":"foo","description":"bar","query":{"language":"kuery","query":"response:200"},"filters":[]}', }); - - const response = await saveQuery(savedQueryAttributes); - expect(mockSavedObjectsClient.create).toHaveBeenCalledWith('query', savedQueryAttributes, { - id: 'foo', - }); - expect(response).toEqual({ id: 'foo', attributes: savedQueryAttributes }); }); + }); - it('should allow overwriting an existing saved query', async () => { - mockSavedObjectsClient.create.mockReturnValue({ - id: 'foo', - attributes: savedQueryAttributes, - }); - - const response = await saveQuery(savedQueryAttributes, { overwrite: true }); - expect(mockSavedObjectsClient.create).toHaveBeenCalledWith('query', savedQueryAttributes, { - id: 'foo', - overwrite: true, + describe('updateQuery', function () { + it('should put the ID & stringified given attributes', async () => { + await updateQuery('foo', savedQueryAttributes); + expect(http.put).toBeCalled(); + expect(http.put).toHaveBeenCalledWith('/api/saved_query/foo', { + body: '{"title":"foo","description":"bar","query":{"language":"kuery","query":"response:200"},"filters":[]}', }); - expect(response).toEqual({ id: 'foo', attributes: savedQueryAttributes }); }); + }); - it('should optionally accept filters and timefilters in object format', async () => { - const serializedSavedQueryAttributesWithFilters = { - ...savedQueryAttributesWithFilters, - filters: savedQueryAttributesWithFilters.filters, - timefilter: savedQueryAttributesWithFilters.timefilter, - }; - - mockSavedObjectsClient.create.mockReturnValue({ - id: 'foo', - attributes: serializedSavedQueryAttributesWithFilters, + describe('getAllSavedQueries', function () { + it('should post and extract the saved queries from the response', async () => { + http.post.mockResolvedValue({ + total: 0, + savedQueries: [{ attributes: savedQueryAttributes }], }); - - const response = await saveQuery(savedQueryAttributesWithFilters); - - expect(mockSavedObjectsClient.create).toHaveBeenCalledWith( - 'query', - serializedSavedQueryAttributesWithFilters, - { id: 'foo' } - ); - expect(response).toEqual({ id: 'foo', attributes: savedQueryAttributesWithFilters }); - }); - - it('should throw an error when saved objects client returns error', async () => { - mockSavedObjectsClient.create.mockReturnValue({ - error: { - error: '123', - message: 'An Error', - }, + const result = await getAllSavedQueries(); + expect(http.post).toBeCalled(); + expect(http.post).toHaveBeenCalledWith('/api/saved_query/_find', { + body: '{"perPage":10000}', }); - - let error = null; - try { - await saveQuery(savedQueryAttributes); - } catch (e) { - error = e; - } - expect(error).not.toBe(null); - }); - it('should throw an error if the saved query does not have a title', async () => { - let error = null; - try { - await saveQuery({ ...savedQueryAttributes, title: '' }); - } catch (e) { - error = e; - } - expect(error).not.toBe(null); + expect(result).toEqual([{ attributes: savedQueryAttributes }]); }); }); - describe('findSavedQueries', function () { - it('should find and return saved queries without search text or pagination parameters', async () => { - mockSavedObjectsClient.find.mockReturnValue({ - savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], - total: 5, - }); - - const response = await findSavedQueries(); - expect(response.queries).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); - }); - it('should return the total count along with the requested queries', async () => { - mockSavedObjectsClient.find.mockReturnValue({ - savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], - total: 5, - }); - - const response = await findSavedQueries(); - expect(response.total).toEqual(5); - }); - - it('should find and return saved queries with search text matching the title field', async () => { - mockSavedObjectsClient.find.mockReturnValue({ - savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], - total: 5, - }); - const response = await findSavedQueries('foo'); - expect(mockSavedObjectsClient.find).toHaveBeenCalledWith({ - page: 1, - perPage: 50, - search: 'foo', - searchFields: ['title^5', 'description'], - sortField: '_score', - type: 'query', - }); - expect(response.queries).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); - }); - it('should find and return parsed filters and timefilters items', async () => { - const serializedSavedQueryAttributesWithFilters = { - ...savedQueryAttributesWithFilters, - filters: savedQueryAttributesWithFilters.filters, - timefilter: savedQueryAttributesWithFilters.timefilter, - }; - mockSavedObjectsClient.find.mockReturnValue({ - savedObjects: [{ id: 'foo', attributes: serializedSavedQueryAttributesWithFilters }], - total: 5, - }); - const response = await findSavedQueries('bar'); - expect(response.queries).toEqual([ - { id: 'foo', attributes: savedQueryAttributesWithFilters }, - ]); - }); - it('should return an array of saved queries', async () => { - mockSavedObjectsClient.find.mockReturnValue({ - savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], - total: 5, + describe('findSavedQueries', function () { + it('should post and return the total & saved queries', async () => { + http.post.mockResolvedValue({ + total: 0, + savedQueries: [{ attributes: savedQueryAttributes }], }); - const response = await findSavedQueries(); - expect(response.queries).toEqual( - expect.objectContaining([ - { - attributes: { - description: 'bar', - query: { language: 'kuery', query: 'response:200' }, - title: 'foo', - }, - id: 'foo', - }, - ]) - ); - }); - it('should accept perPage and page properties', async () => { - mockSavedObjectsClient.find.mockReturnValue({ - savedObjects: [ - { id: 'foo', attributes: savedQueryAttributes }, - { id: 'bar', attributes: savedQueryAttributesBar }, - ], - total: 5, + const result = await findSavedQueries(); + expect(http.post).toBeCalled(); + expect(http.post).toHaveBeenCalledWith('/api/saved_query/_find', { + body: '{"page":1,"perPage":50,"search":""}', }); - const response = await findSavedQueries(undefined, 2, 1); - expect(mockSavedObjectsClient.find).toHaveBeenCalledWith({ - page: 1, - perPage: 2, - search: '', - searchFields: ['title^5', 'description'], - sortField: '_score', - type: 'query', + expect(result).toEqual({ + queries: [{ attributes: savedQueryAttributes }], + total: 0, }); - expect(response.queries).toEqual( - expect.objectContaining([ - { - attributes: { - description: 'bar', - query: { language: 'kuery', query: 'response:200' }, - title: 'foo', - }, - id: 'foo', - }, - { - attributes: { - description: 'baz', - query: { language: 'kuery', query: 'response:200' }, - title: 'bar', - }, - id: 'bar', - }, - ]) - ); }); }); describe('getSavedQuery', function () { - it('should retrieve a saved query by id', async () => { - mockSavedObjectsClient.resolve.mockReturnValue({ - saved_object: { - id: 'foo', - attributes: savedQueryAttributes, - }, - outcome: 'exactMatch', - }); - - const response = await getSavedQuery('foo'); - expect(response).toEqual({ id: 'foo', attributes: savedQueryAttributes }); - }); - it('should only return saved queries', async () => { - mockSavedObjectsClient.resolve.mockReturnValue({ - saved_object: { - id: 'foo', - attributes: savedQueryAttributes, - }, - outcome: 'exactMatch', - }); - - await getSavedQuery('foo'); - expect(mockSavedObjectsClient.resolve).toHaveBeenCalledWith('query', 'foo'); - }); - - it('should parse a json query', async () => { - mockSavedObjectsClient.resolve.mockReturnValue({ - saved_object: { - id: 'food', - attributes: { - title: 'food', - description: 'bar', - query: { - language: 'kuery', - query: '{"x": "y"}', - }, - }, - }, - outcome: 'exactMatch', - }); - - const response = await getSavedQuery('food'); - expect(response.attributes.query.query).toEqual({ x: 'y' }); - }); - - it('should handle null string', async () => { - mockSavedObjectsClient.resolve.mockReturnValue({ - saved_object: { - id: 'food', - attributes: { - title: 'food', - description: 'bar', - query: { - language: 'kuery', - query: 'null', - }, - }, - }, - outcome: 'exactMatch', - }); - - const response = await getSavedQuery('food'); - expect(response.attributes.query.query).toEqual('null'); - }); - - it('should handle null quoted string', async () => { - mockSavedObjectsClient.resolve.mockReturnValue({ - saved_object: { - id: 'food', - attributes: { - title: 'food', - description: 'bar', - query: { - language: 'kuery', - query: '"null"', - }, - }, - }, - outcome: 'exactMatch', - }); - - const response = await getSavedQuery('food'); - expect(response.attributes.query.query).toEqual('"null"'); - }); - - it('should not lose quotes', async () => { - mockSavedObjectsClient.resolve.mockReturnValue({ - saved_object: { - id: 'food', - attributes: { - title: 'food', - description: 'bar', - query: { - language: 'kuery', - query: '"Bob"', - }, - }, - }, - outcome: 'exactMatch', - }); - - const response = await getSavedQuery('food'); - expect(response.attributes.query.query).toEqual('"Bob"'); - }); - - it('should throw if conflict', async () => { - mockSavedObjectsClient.resolve.mockReturnValue({ - saved_object: { - id: 'foo', - attributes: savedQueryAttributes, - }, - outcome: 'conflict', - }); - - const result = getSavedQuery('food'); - expect(result).rejects.toMatchInlineSnapshot( - `[Error: Multiple saved queries found with ID: food (legacy URL alias conflict)]` - ); + it('should get the given ID', async () => { + await getSavedQuery('my_id'); + expect(http.get).toBeCalled(); + expect(http.get).toHaveBeenCalledWith('/api/saved_query/my_id'); }); }); describe('deleteSavedQuery', function () { - it('should delete the saved query for the given ID', async () => { - await deleteSavedQuery('foo'); - expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith('query', 'foo'); - }); - }); - - describe('getAllSavedQueries', function () { - it('should return all the saved queries', async () => { - mockSavedObjectsClient.find.mockReturnValue({ - savedObjects: [{ id: 'foo', attributes: savedQueryAttributes }], - }); - const response = await getAllSavedQueries(); - expect(response).toEqual( - expect.objectContaining([ - { - attributes: { - description: 'bar', - query: { language: 'kuery', query: 'response:200' }, - title: 'foo', - }, - id: 'foo', - }, - ]) - ); - expect(mockSavedObjectsClient.find).toHaveBeenCalledWith({ - page: 1, - perPage: 0, - type: 'query', - }); + it('should delete the given ID', async () => { + await deleteSavedQuery('my_id'); + expect(http.delete).toBeCalled(); + expect(http.delete).toHaveBeenCalledWith('/api/saved_query/my_id'); }); }); describe('getSavedQueryCount', function () { - it('should return the total number of saved queries', async () => { - mockSavedObjectsClient.find.mockReturnValue({ - total: 1, - }); - const response = await getSavedQueryCount(); - expect(response).toEqual(1); + it('should get the total', async () => { + await getSavedQueryCount(); + expect(http.get).toBeCalled(); + expect(http.get).toHaveBeenCalledWith('/api/saved_query/_count'); }); }); }); diff --git a/src/plugins/data/public/query/saved_query/saved_query_service.ts b/src/plugins/data/public/query/saved_query/saved_query_service.ts index 89a357a66d370..8ec9167a3a0c2 100644 --- a/src/plugins/data/public/query/saved_query/saved_query_service.ts +++ b/src/plugins/data/public/query/saved_query/saved_query_service.ts @@ -6,163 +6,61 @@ * Side Public License, v 1. */ -import { isObject } from 'lodash'; -import { SavedObjectsClientContract, SavedObjectAttributes } from 'src/core/public'; -import { SavedQueryAttributes, SavedQuery, SavedQueryService } from './types'; - -type SerializedSavedQueryAttributes = SavedObjectAttributes & - SavedQueryAttributes & { - query: { - query: string; - language: string; - }; +import { HttpStart } from 'src/core/public'; +import { SavedQuery } from './types'; +import { SavedQueryAttributes } from '../../../common'; + +export const createSavedQueryService = (http: HttpStart) => { + const createQuery = async (attributes: SavedQueryAttributes, { overwrite = false } = {}) => { + const savedQuery = await http.post('/api/saved_query/_create', { + body: JSON.stringify(attributes), + }); + return savedQuery; }; -export const createSavedQueryService = ( - savedObjectsClient: SavedObjectsClientContract -): SavedQueryService => { - const saveQuery = async (attributes: SavedQueryAttributes, { overwrite = false } = {}) => { - if (!attributes.title.length) { - // title is required extra check against circumventing the front end - throw new Error('Cannot create saved query without a title'); - } - - const query = { - query: - typeof attributes.query.query === 'string' - ? attributes.query.query - : JSON.stringify(attributes.query.query), - language: attributes.query.language, - }; - - const queryObject: SerializedSavedQueryAttributes = { - title: attributes.title.trim(), // trim whitespace before save as an extra precaution against circumventing the front end - description: attributes.description, - query, - }; - - if (attributes.filters) { - queryObject.filters = attributes.filters; - } - - if (attributes.timefilter) { - queryObject.timefilter = attributes.timefilter; - } - - let rawQueryResponse; - if (!overwrite) { - rawQueryResponse = await savedObjectsClient.create('query', queryObject, { - id: attributes.title, - }); - } else { - rawQueryResponse = await savedObjectsClient.create('query', queryObject, { - id: attributes.title, - overwrite: true, - }); - } - - if (rawQueryResponse.error) { - throw new Error(rawQueryResponse.error.message); - } - - return parseSavedQueryObject(rawQueryResponse); + const updateQuery = async (id: string, attributes: SavedQueryAttributes) => { + const savedQuery = await http.put(`/api/saved_query/${id}`, { + body: JSON.stringify(attributes), + }); + return savedQuery; }; + // we have to tell the saved objects client how many to fetch, otherwise it defaults to fetching 20 per page const getAllSavedQueries = async (): Promise => { - const count = await getSavedQueryCount(); - const response = await savedObjectsClient.find({ - type: 'query', - perPage: count, - page: 1, + const { savedQueries } = await http.post('/api/saved_query/_find', { + body: JSON.stringify({ perPage: 10000 }), }); - return response.savedObjects.map( - (savedObject: { id: string; attributes: SerializedSavedQueryAttributes }) => - parseSavedQueryObject(savedObject) - ); + return savedQueries; }; + // findSavedQueries will do a 'match_all' if no search string is passed in const findSavedQueries = async ( - searchText: string = '', + search: string = '', perPage: number = 50, - activePage: number = 1 + page: number = 1 ): Promise<{ total: number; queries: SavedQuery[] }> => { - const response = await savedObjectsClient.find({ - type: 'query', - search: searchText, - searchFields: ['title^5', 'description'], - sortField: '_score', - perPage, - page: activePage, + const { total, savedQueries: queries } = await http.post('/api/saved_query/_find', { + body: JSON.stringify({ page, perPage, search }), }); - return { - total: response.total, - queries: response.savedObjects.map( - (savedObject: { id: string; attributes: SerializedSavedQueryAttributes }) => - parseSavedQueryObject(savedObject) - ), - }; - }; - - const getSavedQuery = async (id: string): Promise => { - const { saved_object: savedObject, outcome } = - await savedObjectsClient.resolve('query', id); - if (outcome === 'conflict') { - throw new Error(`Multiple saved queries found with ID: ${id} (legacy URL alias conflict)`); - } else if (savedObject.error) { - throw new Error(savedObject.error.message); - } - return parseSavedQueryObject(savedObject); + return { total, queries }; }; - const deleteSavedQuery = async (id: string) => { - return await savedObjectsClient.delete('query', id); + const getSavedQuery = (id: string): Promise => { + return http.get(`/api/saved_query/${id}`); }; - const parseSavedQueryObject = (savedQuery: { - id: string; - attributes: SerializedSavedQueryAttributes; - }) => { - let queryString: string | object = savedQuery.attributes.query.query; - - try { - const parsedQueryString: object = JSON.parse(savedQuery.attributes.query.query); - if (isObject(parsedQueryString)) { - queryString = parsedQueryString; - } - } catch (e) {} // eslint-disable-line no-empty - - const savedQueryItems: SavedQueryAttributes = { - title: savedQuery.attributes.title || '', - description: savedQuery.attributes.description || '', - query: { - query: queryString, - language: savedQuery.attributes.query.language, - }, - }; - if (savedQuery.attributes.filters) { - savedQueryItems.filters = savedQuery.attributes.filters; - } - if (savedQuery.attributes.timefilter) { - savedQueryItems.timefilter = savedQuery.attributes.timefilter; - } - return { - id: savedQuery.id, - attributes: savedQueryItems, - }; + const deleteSavedQuery = (id: string) => { + return http.delete(`/api/saved_query/${id}`); }; const getSavedQueryCount = async (): Promise => { - const response = await savedObjectsClient.find({ - type: 'query', - perPage: 0, - page: 1, - }); - return response.total; + return http.get('/api/saved_query/_count'); }; return { - saveQuery, + createQuery, + updateQuery, getAllSavedQueries, findSavedQueries, getSavedQuery, diff --git a/src/plugins/data/public/query/saved_query/types.ts b/src/plugins/data/public/query/saved_query/types.ts index bd53bb7d77b30..0f1763433e72a 100644 --- a/src/plugins/data/public/query/saved_query/types.ts +++ b/src/plugins/data/public/query/saved_query/types.ts @@ -26,10 +26,8 @@ export interface SavedQueryAttributes { } export interface SavedQueryService { - saveQuery: ( - attributes: SavedQueryAttributes, - config?: { overwrite: boolean } - ) => Promise; + createQuery: (attributes: SavedQueryAttributes) => Promise; + updateQuery: (id: string, attributes: SavedQueryAttributes) => Promise; getAllSavedQueries: () => Promise; findSavedQueries: ( searchText?: string, diff --git a/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts index b4ec4934233d0..857a932d9157b 100644 --- a/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts +++ b/src/plugins/data/public/query/state_sync/connect_to_query_state.test.ts @@ -74,7 +74,7 @@ describe('connect_to_global_state', () => { queryServiceStart = queryService.start({ uiSettings: setupMock.uiSettings, storage: new Storage(new StubBrowserStorage()), - savedObjectsClient: startMock.savedObjects.client, + http: startMock.http, }); filterManager = queryServiceStart.filterManager; timeFilter = queryServiceStart.timefilter.timefilter; @@ -308,7 +308,7 @@ describe('connect_to_app_state', () => { queryServiceStart = queryService.start({ uiSettings: setupMock.uiSettings, storage: new Storage(new StubBrowserStorage()), - savedObjectsClient: startMock.savedObjects.client, + http: startMock.http, }); filterManager = queryServiceStart.filterManager; @@ -487,7 +487,7 @@ describe('filters with different state', () => { queryServiceStart = queryService.start({ uiSettings: setupMock.uiSettings, storage: new Storage(new StubBrowserStorage()), - savedObjectsClient: startMock.savedObjects.client, + http: startMock.http, }); filterManager = queryServiceStart.filterManager; diff --git a/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts index 73f78eb98968d..2e48a11efd69c 100644 --- a/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts +++ b/src/plugins/data/public/query/state_sync/sync_state_with_url.test.ts @@ -68,7 +68,7 @@ describe('sync_query_state_with_url', () => { queryServiceStart = queryService.start({ uiSettings: startMock.uiSettings, storage: new Storage(new StubBrowserStorage()), - savedObjectsClient: startMock.savedObjects.client, + http: startMock.http, }); filterManager = queryServiceStart.filterManager; timefilter = queryServiceStart.timefilter.timefilter; diff --git a/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx b/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx index d0221658f3e08..c7a79658fac88 100644 --- a/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx +++ b/src/plugins/data/public/ui/saved_query_form/save_query_form.tsx @@ -24,10 +24,9 @@ import { import { i18n } from '@kbn/i18n'; import { sortBy, isEqual } from 'lodash'; import { SavedQuery, SavedQueryService } from '../..'; -import { SavedQueryAttributes } from '../../query'; interface Props { - savedQuery?: SavedQueryAttributes; + savedQuery?: SavedQuery; savedQueryService: SavedQueryService; onSave: (savedQueryMeta: SavedQueryMeta) => void; onClose: () => void; @@ -36,6 +35,7 @@ interface Props { } export interface SavedQueryMeta { + id?: string; title: string; description: string; shouldIncludeFilters: boolean; @@ -50,18 +50,18 @@ export function SaveQueryForm({ showFilterOption = true, showTimeFilterOption = true, }: Props) { - const [title, setTitle] = useState(savedQuery ? savedQuery.title : ''); + const [title, setTitle] = useState(savedQuery?.attributes.title ?? ''); const [enabledSaveButton, setEnabledSaveButton] = useState(Boolean(savedQuery)); - const [description, setDescription] = useState(savedQuery ? savedQuery.description : ''); + const [description, setDescription] = useState(savedQuery?.attributes.description ?? ''); const [savedQueries, setSavedQueries] = useState([]); const [shouldIncludeFilters, setShouldIncludeFilters] = useState( - savedQuery ? !!savedQuery.filters : true + Boolean(savedQuery?.attributes.filters ?? true) ); // Defaults to false because saved queries are meant to be as portable as possible and loading // a saved query with a time filter will override whatever the current value of the global timepicker // is. We expect this option to be used rarely and only when the user knows they want this behavior. const [shouldIncludeTimefilter, setIncludeTimefilter] = useState( - savedQuery ? !!savedQuery.timefilter : false + Boolean(savedQuery?.attributes.timefilter ?? false) ); const [formErrors, setFormErrors] = useState([]); @@ -82,7 +82,7 @@ export function SaveQueryForm({ useEffect(() => { const fetchQueries = async () => { const allSavedQueries = await savedQueryService.getAllSavedQueries(); - const sortedAllSavedQueries = sortBy(allSavedQueries, 'attributes.title') as SavedQuery[]; + const sortedAllSavedQueries = sortBy(allSavedQueries, 'attributes.title'); setSavedQueries(sortedAllSavedQueries); }; fetchQueries(); @@ -109,13 +109,22 @@ export function SaveQueryForm({ const onClickSave = useCallback(() => { if (validate()) { onSave({ + id: savedQuery?.id, title, description, shouldIncludeFilters, shouldIncludeTimefilter, }); } - }, [validate, onSave, title, description, shouldIncludeFilters, shouldIncludeTimefilter]); + }, [ + validate, + onSave, + savedQuery?.id, + title, + description, + shouldIncludeFilters, + shouldIncludeTimefilter, + ]); const onInputChange = useCallback((event) => { setEnabledSaveButton(Boolean(event.target.value)); diff --git a/src/plugins/data/public/ui/search_bar/search_bar.tsx b/src/plugins/data/public/ui/search_bar/search_bar.tsx index db0bebf97578b..bd48dcd6cd34c 100644 --- a/src/plugins/data/public/ui/search_bar/search_bar.tsx +++ b/src/plugins/data/public/ui/search_bar/search_bar.tsx @@ -245,11 +245,12 @@ class SearchBarUI extends Component { try { let response; if (this.props.savedQuery && !saveAsNew) { - response = await this.savedQueryService.saveQuery(savedQueryAttributes, { - overwrite: true, - }); + response = await this.savedQueryService.updateQuery( + savedQueryMeta.id!, + savedQueryAttributes + ); } else { - response = await this.savedQueryService.saveQuery(savedQueryAttributes); + response = await this.savedQueryService.createQuery(savedQueryAttributes); } this.services.notifications.toasts.addSuccess( @@ -423,7 +424,7 @@ class SearchBarUI extends Component { {this.state.showSaveQueryModal ? ( this.setState({ showSaveQueryModal: false })} diff --git a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts index 09e64ba7f4310..423ebbdcd43c7 100644 --- a/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts +++ b/src/plugins/data/server/kql_telemetry/kql_telemetry_service.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { first } from 'rxjs/operators'; import { CoreSetup, Plugin, PluginInitializerContext } from 'kibana/server'; import { registerKqlTelemetryRoute } from './route'; import { UsageCollectionSetup } from '../../../usage_collection/server'; @@ -28,15 +27,13 @@ export class KqlTelemetryService implements Plugin { ); if (usageCollection) { - this.initializerContext.config.legacy.globalConfig$ - .pipe(first()) - .toPromise() - .then((config) => makeKQLUsageCollector(usageCollection, config.kibana.index)) - .catch((e) => { - this.initializerContext.logger - .get('kql-telemetry') - .warn(`Registering KQL telemetry collector failed: ${e}`); - }); + try { + makeKQLUsageCollector(usageCollection, savedObjects.getKibanaIndex()); + } catch (e) { + this.initializerContext.logger + .get('kql-telemetry') + .warn(`Registering KQL telemetry collector failed: ${e}`); + } } } diff --git a/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts b/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts index f3b5865bd0893..39ea7d6ab2dec 100644 --- a/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts +++ b/src/plugins/data/server/kql_telemetry/usage_collector/make_kql_usage_collector.ts @@ -9,10 +9,7 @@ import { fetchProvider, Usage } from './fetch'; import { UsageCollectionSetup } from '../../../../usage_collection/server'; -export async function makeKQLUsageCollector( - usageCollection: UsageCollectionSetup, - kibanaIndex: string -) { +export function makeKQLUsageCollector(usageCollection: UsageCollectionSetup, kibanaIndex: string) { const kqlUsageCollector = usageCollection.makeUsageCollector({ type: 'kql', fetch: fetchProvider(kibanaIndex), diff --git a/src/plugins/data/server/query/query_service.ts b/src/plugins/data/server/query/query_service.ts index 1bf5ff901e90f..173abeda0c951 100644 --- a/src/plugins/data/server/query/query_service.ts +++ b/src/plugins/data/server/query/query_service.ts @@ -8,11 +8,21 @@ import { CoreSetup, Plugin } from 'kibana/server'; import { querySavedObjectType } from '../saved_objects'; -import { extract, inject, telemetry, getAllMigrations } from '../../common/query/persistable_state'; +import { extract, getAllMigrations, inject, telemetry } from '../../common/query/persistable_state'; +import { registerSavedQueryRoutes } from './routes'; +import { + registerSavedQueryRouteHandlerContext, + SavedQueryRouteHandlerContext, +} from './route_handler_context'; export class QueryService implements Plugin { public setup(core: CoreSetup) { core.savedObjects.registerType(querySavedObjectType); + core.http.registerRouteHandlerContext( + 'savedQuery', + registerSavedQueryRouteHandlerContext + ); + registerSavedQueryRoutes(core); return { filterManager: { diff --git a/src/plugins/data/server/query/route_handler_context.test.ts b/src/plugins/data/server/query/route_handler_context.test.ts new file mode 100644 index 0000000000000..cc7686a06cb67 --- /dev/null +++ b/src/plugins/data/server/query/route_handler_context.test.ts @@ -0,0 +1,566 @@ +/* + * Copyright 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 { coreMock } from '../../../../core/server/mocks'; +import { + DATA_VIEW_SAVED_OBJECT_TYPE, + FilterStateStore, + SavedObject, + SavedQueryAttributes, +} from '../../common'; +import { registerSavedQueryRouteHandlerContext } from './route_handler_context'; +import { SavedObjectsFindResponse, SavedObjectsUpdateResponse } from 'kibana/server'; + +const mockContext = { + core: coreMock.createRequestHandlerContext(), +}; +const { + core: { + savedObjects: { client: mockSavedObjectsClient }, + }, +} = mockContext; +const context = registerSavedQueryRouteHandlerContext(mockContext); + +const savedQueryAttributes: SavedQueryAttributes = { + title: 'foo', + description: 'bar', + query: { + language: 'kuery', + query: 'response:200', + }, + filters: [], +}; +const savedQueryAttributesBar: SavedQueryAttributes = { + title: 'bar', + description: 'baz', + query: { + language: 'kuery', + query: 'response:200', + }, +}; + +const savedQueryAttributesWithFilters: SavedQueryAttributes = { + ...savedQueryAttributes, + filters: [ + { + query: { match_all: {} }, + $state: { store: FilterStateStore.APP_STATE }, + meta: { + index: 'my-index', + disabled: false, + negate: false, + alias: null, + }, + }, + ], + timefilter: { + to: 'now', + from: 'now-15m', + refreshInterval: { + pause: false, + value: 0, + }, + }, +}; + +const savedQueryReferences = [ + { + type: DATA_VIEW_SAVED_OBJECT_TYPE, + name: 'my-index', + id: 'my-index', + }, +]; + +describe('saved query route handler context', () => { + beforeEach(() => { + mockSavedObjectsClient.create.mockClear(); + mockSavedObjectsClient.resolve.mockClear(); + mockSavedObjectsClient.find.mockClear(); + mockSavedObjectsClient.delete.mockClear(); + }); + + describe('create', function () { + it('should create a saved object for the given attributes', async () => { + const mockResponse: SavedObject = { + id: 'foo', + type: 'query', + attributes: savedQueryAttributes, + references: [], + }; + mockSavedObjectsClient.create.mockResolvedValue(mockResponse); + + const response = await context.create(savedQueryAttributes); + + expect(mockSavedObjectsClient.create).toHaveBeenCalledWith('query', savedQueryAttributes, { + references: [], + }); + expect(response).toEqual({ + id: 'foo', + attributes: savedQueryAttributes, + }); + }); + + it('should optionally accept query in object format', async () => { + const savedQueryAttributesWithQueryObject: SavedQueryAttributes = { + ...savedQueryAttributes, + query: { + language: 'lucene', + query: { match_all: {} }, + }, + }; + const mockResponse: SavedObject = { + id: 'foo', + type: 'query', + attributes: savedQueryAttributesWithQueryObject, + references: [], + }; + mockSavedObjectsClient.create.mockResolvedValue(mockResponse); + + const { attributes } = await context.create(savedQueryAttributesWithQueryObject); + + expect(attributes).toEqual(savedQueryAttributesWithQueryObject); + }); + + it('should optionally accept filters and timefilters in object format', async () => { + const serializedSavedQueryAttributesWithFilters = { + ...savedQueryAttributesWithFilters, + filters: savedQueryAttributesWithFilters.filters, + timefilter: savedQueryAttributesWithFilters.timefilter, + }; + const mockResponse: SavedObject = { + id: 'foo', + type: 'query', + attributes: serializedSavedQueryAttributesWithFilters, + references: [], + }; + mockSavedObjectsClient.create.mockResolvedValue(mockResponse); + + await context.create(savedQueryAttributesWithFilters); + + const [[type, attributes]] = mockSavedObjectsClient.create.mock.calls; + const { filters = [], timefilter } = attributes as SavedQueryAttributes; + expect(type).toEqual('query'); + expect(filters.length).toBe(1); + expect(timefilter).toEqual(savedQueryAttributesWithFilters.timefilter); + }); + + it('should throw an error when saved objects client returns error', async () => { + mockSavedObjectsClient.create.mockResolvedValue({ + error: { + error: '123', + message: 'An Error', + }, + } as SavedObject); + + const response = context.create(savedQueryAttributes); + + expect(response).rejects.toMatchInlineSnapshot(`[Error: An Error]`); + }); + + it('should throw an error if the saved query does not have a title', async () => { + const response = context.create({ ...savedQueryAttributes, title: '' }); + expect(response).rejects.toMatchInlineSnapshot( + `[Error: Cannot create saved query without a title]` + ); + }); + }); + + describe('update', function () { + it('should update a saved object for the given attributes', async () => { + const mockResponse: SavedObject = { + id: 'foo', + type: 'query', + attributes: savedQueryAttributes, + references: [], + }; + mockSavedObjectsClient.update.mockResolvedValue(mockResponse); + + const response = await context.update('foo', savedQueryAttributes); + + expect(mockSavedObjectsClient.update).toHaveBeenCalledWith( + 'query', + 'foo', + savedQueryAttributes, + { + references: [], + } + ); + expect(response).toEqual({ + id: 'foo', + attributes: savedQueryAttributes, + }); + }); + + it('should throw an error when saved objects client returns error', async () => { + mockSavedObjectsClient.update.mockResolvedValue({ + error: { + error: '123', + message: 'An Error', + }, + } as SavedObjectsUpdateResponse); + + const response = context.update('foo', savedQueryAttributes); + + expect(response).rejects.toMatchInlineSnapshot(`[Error: An Error]`); + }); + + it('should throw an error if the saved query does not have a title', async () => { + const response = context.create({ ...savedQueryAttributes, title: '' }); + expect(response).rejects.toMatchInlineSnapshot( + `[Error: Cannot create saved query without a title]` + ); + }); + }); + + describe('find', function () { + it('should find and return saved queries without search text or pagination parameters', async () => { + const mockResponse: SavedObjectsFindResponse = { + page: 0, + per_page: 0, + saved_objects: [ + { + id: 'foo', + type: 'query', + score: 0, + attributes: savedQueryAttributes, + references: [], + }, + ], + total: 5, + }; + mockSavedObjectsClient.find.mockResolvedValue(mockResponse); + + const response = await context.find(); + + expect(response.savedQueries).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); + }); + + it('should return the total count along with the requested queries', async () => { + const mockResponse: SavedObjectsFindResponse = { + page: 0, + per_page: 0, + saved_objects: [ + { id: 'foo', type: 'query', score: 0, attributes: savedQueryAttributes, references: [] }, + ], + total: 5, + }; + mockSavedObjectsClient.find.mockResolvedValue(mockResponse); + + const response = await context.find(); + + expect(response.total).toEqual(5); + }); + + it('should find and return saved queries with search text matching the title field', async () => { + const mockResponse: SavedObjectsFindResponse = { + page: 0, + per_page: 0, + saved_objects: [ + { id: 'foo', type: 'query', score: 0, attributes: savedQueryAttributes, references: [] }, + ], + total: 5, + }; + mockSavedObjectsClient.find.mockResolvedValue(mockResponse); + + const response = await context.find({ search: 'foo' }); + + expect(mockSavedObjectsClient.find).toHaveBeenCalledWith({ + page: 1, + perPage: 50, + search: 'foo', + type: 'query', + }); + expect(response.savedQueries).toEqual([{ id: 'foo', attributes: savedQueryAttributes }]); + }); + + it('should find and return parsed filters and timefilters items', async () => { + const mockResponse: SavedObjectsFindResponse = { + page: 0, + per_page: 0, + saved_objects: [ + { + id: 'foo', + type: 'query', + score: 0, + attributes: savedQueryAttributesWithFilters, + references: savedQueryReferences, + }, + ], + total: 5, + }; + mockSavedObjectsClient.find.mockResolvedValue(mockResponse); + + const response = await context.find({ search: 'bar' }); + + expect(response.savedQueries).toEqual([ + { id: 'foo', attributes: savedQueryAttributesWithFilters }, + ]); + }); + + it('should return an array of saved queries', async () => { + const mockResponse: SavedObjectsFindResponse = { + page: 0, + per_page: 0, + saved_objects: [ + { id: 'foo', type: 'query', score: 0, attributes: savedQueryAttributes, references: [] }, + ], + total: 5, + }; + mockSavedObjectsClient.find.mockResolvedValue(mockResponse); + + const response = await context.find(); + + expect(response.savedQueries).toEqual( + expect.objectContaining([ + { + attributes: { + description: 'bar', + query: { language: 'kuery', query: 'response:200' }, + filters: [], + title: 'foo', + }, + id: 'foo', + }, + ]) + ); + }); + + it('should accept perPage and page properties', async () => { + const mockResponse: SavedObjectsFindResponse = { + page: 0, + per_page: 0, + saved_objects: [ + { id: 'foo', type: 'query', score: 0, attributes: savedQueryAttributes, references: [] }, + { + id: 'bar', + type: 'query', + score: 0, + attributes: savedQueryAttributesBar, + references: [], + }, + ], + total: 5, + }; + mockSavedObjectsClient.find.mockResolvedValue(mockResponse); + + const response = await context.find({ + page: 1, + perPage: 2, + }); + + expect(mockSavedObjectsClient.find).toHaveBeenCalledWith({ + page: 1, + perPage: 2, + search: '', + type: 'query', + }); + expect(response.savedQueries).toEqual( + expect.objectContaining([ + { + attributes: { + description: 'bar', + query: { language: 'kuery', query: 'response:200' }, + filters: [], + title: 'foo', + }, + id: 'foo', + }, + { + attributes: { + description: 'baz', + query: { language: 'kuery', query: 'response:200' }, + filters: [], + title: 'bar', + }, + id: 'bar', + }, + ]) + ); + }); + }); + + describe('get', function () { + it('should retrieve a saved query by id', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'foo', + type: 'query', + attributes: savedQueryAttributes, + references: [], + }, + outcome: 'exactMatch', + }); + + const response = await context.get('foo'); + expect(response).toEqual({ id: 'foo', attributes: savedQueryAttributes }); + }); + + it('should only return saved queries', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'foo', + type: 'query', + attributes: savedQueryAttributes, + references: [], + }, + outcome: 'exactMatch', + }); + + await context.get('foo'); + expect(mockSavedObjectsClient.resolve).toHaveBeenCalledWith('query', 'foo'); + }); + + it('should parse a json query', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'food', + type: 'query', + attributes: { + title: 'food', + description: 'bar', + query: { + language: 'kuery', + query: '{"x": "y"}', + }, + }, + references: [], + }, + outcome: 'exactMatch', + }); + + const response = await context.get('food'); + expect(response.attributes.query.query).toEqual({ x: 'y' }); + }); + + it('should handle null string', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'food', + type: 'query', + attributes: { + title: 'food', + description: 'bar', + query: { + language: 'kuery', + query: 'null', + }, + }, + references: [], + }, + outcome: 'exactMatch', + }); + + const response = await context.get('food'); + expect(response.attributes.query.query).toEqual('null'); + }); + + it('should handle null quoted string', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'food', + type: 'query', + attributes: { + title: 'food', + description: 'bar', + query: { + language: 'kuery', + query: '"null"', + }, + }, + references: [], + }, + outcome: 'exactMatch', + }); + + const response = await context.get('food'); + expect(response.attributes.query.query).toEqual('"null"'); + }); + + it('should not lose quotes', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'food', + type: 'query', + attributes: { + title: 'food', + description: 'bar', + query: { + language: 'kuery', + query: '"Bob"', + }, + }, + references: [], + }, + outcome: 'exactMatch', + }); + + const response = await context.get('food'); + expect(response.attributes.query.query).toEqual('"Bob"'); + }); + + it('should inject references', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'food', + type: 'query', + attributes: savedQueryAttributesWithFilters, + references: [ + { + id: 'my-new-index', + type: DATA_VIEW_SAVED_OBJECT_TYPE, + name: 'my-index', + }, + ], + }, + outcome: 'exactMatch', + }); + + const response = await context.get('food'); + expect(response.attributes.filters[0].meta.index).toBe('my-new-index'); + }); + + it('should throw if conflict', async () => { + mockSavedObjectsClient.resolve.mockResolvedValue({ + saved_object: { + id: 'foo', + type: 'query', + attributes: savedQueryAttributes, + references: [], + }, + outcome: 'conflict', + }); + + const result = context.get('food'); + expect(result).rejects.toMatchInlineSnapshot( + `[Error: Multiple saved queries found with ID: food (legacy URL alias conflict)]` + ); + }); + }); + + describe('delete', function () { + it('should delete the saved query for the given ID', async () => { + await context.delete('foo'); + expect(mockSavedObjectsClient.delete).toHaveBeenCalledWith('query', 'foo'); + }); + }); + + describe('count', function () { + it('should return the total number of saved queries', async () => { + mockSavedObjectsClient.find.mockResolvedValue({ + total: 1, + page: 0, + per_page: 0, + saved_objects: [], + }); + + const response = await context.count(); + + expect(response).toEqual(1); + }); + }); +}); diff --git a/src/plugins/data/server/query/route_handler_context.ts b/src/plugins/data/server/query/route_handler_context.ts new file mode 100644 index 0000000000000..3c60b33559b72 --- /dev/null +++ b/src/plugins/data/server/query/route_handler_context.ts @@ -0,0 +1,155 @@ +/* + * Copyright 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 { RequestHandlerContext, SavedObject } from 'kibana/server'; +import { isFilters } from '@kbn/es-query'; +import { isQuery, SavedQueryAttributes } from '../../common'; +import { extract, inject } from '../../common/query/persistable_state'; + +function injectReferences({ + id, + attributes, + references, +}: Pick, 'id' | 'attributes' | 'references'>) { + const { query } = attributes; + if (typeof query.query === 'string') { + try { + const parsed = JSON.parse(query.query); + query.query = parsed instanceof Object ? parsed : query.query; + } catch (e) { + // Just keep it as a string + } + } + const filters = inject(attributes.filters ?? [], references); + return { id, attributes: { ...attributes, filters } }; +} + +function extractReferences({ + title, + description, + query, + filters = [], + timefilter, +}: SavedQueryAttributes) { + const { state: extractedFilters, references } = extract(filters); + + const attributes: SavedQueryAttributes = { + title: title.trim(), + description: description.trim(), + query: { + ...query, + query: typeof query.query === 'string' ? query.query : JSON.stringify(query.query), + }, + filters: extractedFilters, + ...(timefilter && { timefilter }), + }; + + return { attributes, references }; +} + +function verifySavedQuery({ title, query, filters = [] }: SavedQueryAttributes) { + if (!isQuery(query)) { + throw new Error(`Invalid query: ${query}`); + } + + if (!isFilters(filters)) { + throw new Error(`Invalid filters: ${filters}`); + } + + if (!title.trim().length) { + throw new Error('Cannot create saved query without a title'); + } +} + +export function registerSavedQueryRouteHandlerContext(context: RequestHandlerContext) { + const createSavedQuery = async (attrs: SavedQueryAttributes) => { + verifySavedQuery(attrs); + const { attributes, references } = extractReferences(attrs); + + const savedObject = await context.core.savedObjects.client.create( + 'query', + attributes, + { + references, + } + ); + + // TODO: Handle properly + if (savedObject.error) throw new Error(savedObject.error.message); + + return injectReferences(savedObject); + }; + + const updateSavedQuery = async (id: string, attrs: SavedQueryAttributes) => { + verifySavedQuery(attrs); + const { attributes, references } = extractReferences(attrs); + + const savedObject = await context.core.savedObjects.client.update( + 'query', + id, + attributes, + { + references, + } + ); + + // TODO: Handle properly + if (savedObject.error) throw new Error(savedObject.error.message); + + return injectReferences({ id, attributes, references }); + }; + + const getSavedQuery = async (id: string) => { + const { saved_object: savedObject, outcome } = + await context.core.savedObjects.client.resolve('query', id); + if (outcome === 'conflict') { + throw new Error(`Multiple saved queries found with ID: ${id} (legacy URL alias conflict)`); + } else if (savedObject.error) { + throw new Error(savedObject.error.message); + } + return injectReferences(savedObject); + }; + + const getSavedQueriesCount = async () => { + const { total } = await context.core.savedObjects.client.find({ + type: 'query', + }); + return total; + }; + + const findSavedQueries = async ({ page = 1, perPage = 50, search = '' } = {}) => { + const { total, saved_objects: savedObjects } = + await context.core.savedObjects.client.find({ + type: 'query', + page, + perPage, + search, + }); + + const savedQueries = savedObjects.map(injectReferences); + + return { total, savedQueries }; + }; + + const deleteSavedQuery = (id: string) => { + return context.core.savedObjects.client.delete('query', id); + }; + + return { + create: createSavedQuery, + update: updateSavedQuery, + get: getSavedQuery, + count: getSavedQueriesCount, + find: findSavedQueries, + delete: deleteSavedQuery, + }; +} + +export interface SavedQueryRouteHandlerContext extends RequestHandlerContext { + savedQuery: ReturnType; +} diff --git a/src/plugins/data/server/query/routes.ts b/src/plugins/data/server/query/routes.ts new file mode 100644 index 0000000000000..cdf9e6f43dccc --- /dev/null +++ b/src/plugins/data/server/query/routes.ts @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { schema } from '@kbn/config-schema'; +import { CoreSetup } from 'kibana/server'; +import { SavedQueryRouteHandlerContext } from './route_handler_context'; + +const SAVED_QUERY_PATH = '/api/saved_query'; +const SAVED_QUERY_ID_CONFIG = schema.object({ + id: schema.string(), +}); +const SAVED_QUERY_ATTRS_CONFIG = schema.object({ + title: schema.string(), + description: schema.string(), + query: schema.object({ + query: schema.oneOf([schema.string(), schema.object({}, { unknowns: 'allow' })]), + language: schema.string(), + }), + filters: schema.maybe(schema.arrayOf(schema.any())), + timefilter: schema.maybe(schema.any()), +}); + +export function registerSavedQueryRoutes({ http }: CoreSetup): void { + const router = http.createRouter(); + + router.post( + { + path: `${SAVED_QUERY_PATH}/_create`, + validate: { + body: SAVED_QUERY_ATTRS_CONFIG, + }, + }, + async (context, request, response) => { + try { + const body = await context.savedQuery.create(request.body); + return response.ok({ body }); + } catch (e) { + // TODO: Handle properly + return response.customError(e); + } + } + ); + + router.put( + { + path: `${SAVED_QUERY_PATH}/{id}`, + validate: { + params: SAVED_QUERY_ID_CONFIG, + body: SAVED_QUERY_ATTRS_CONFIG, + }, + }, + async (context, request, response) => { + const { id } = request.params; + try { + const body = await context.savedQuery.update(id, request.body); + return response.ok({ body }); + } catch (e) { + // TODO: Handle properly + return response.customError(e); + } + } + ); + + router.get( + { + path: `${SAVED_QUERY_PATH}/{id}`, + validate: { + params: SAVED_QUERY_ID_CONFIG, + }, + }, + async (context, request, response) => { + const { id } = request.params; + try { + const body = await context.savedQuery.get(id); + return response.ok({ body }); + } catch (e) { + // TODO: Handle properly + return response.customError(e); + } + } + ); + + router.get( + { + path: `${SAVED_QUERY_PATH}/_count`, + validate: {}, + }, + async (context, request, response) => { + try { + const count = await context.savedQuery.count(); + return response.ok({ body: `${count}` }); + } catch (e) { + // TODO: Handle properly + return response.customError(e); + } + } + ); + + router.post( + { + path: `${SAVED_QUERY_PATH}/_find`, + validate: { + body: schema.object({ + search: schema.string({ defaultValue: '' }), + perPage: schema.number({ defaultValue: 50 }), + page: schema.number({ defaultValue: 1 }), + }), + }, + }, + async (context, request, response) => { + try { + const body = await context.savedQuery.find(request.body); + return response.ok({ body }); + } catch (e) { + // TODO: Handle properly + return response.customError(e); + } + } + ); + + router.delete( + { + path: `${SAVED_QUERY_PATH}/{id}`, + validate: { + params: SAVED_QUERY_ID_CONFIG, + }, + }, + async (context, request, response) => { + const { id } = request.params; + try { + const body = await context.savedQuery.delete(id); + return response.ok({ body }); + } catch (e) { + // TODO: Handle properly + return response.customError(e); + } + } + ); +} diff --git a/src/plugins/data/server/saved_objects/migrations/query.ts b/src/plugins/data/server/saved_objects/migrations/query.ts new file mode 100644 index 0000000000000..9640725e3edd4 --- /dev/null +++ b/src/plugins/data/server/saved_objects/migrations/query.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { mapValues } from 'lodash'; +import { SavedObject } from 'kibana/server'; +import { SavedQueryAttributes } from '../../../common'; +import { extract, getAllMigrations } from '../../../common/query/persistable_state'; +import { mergeMigrationFunctionMaps } from '../../../../kibana_utils/common'; + +const extractFilterReferences = (doc: SavedObject) => { + const { state: filters, references } = extract(doc.attributes.filters ?? []); + return { + ...doc, + attributes: { + ...doc.attributes, + filters, + }, + references, + }; +}; + +const filterMigrations = mapValues(getAllMigrations(), (migrate) => { + return (doc: SavedObject) => ({ + ...doc, + attributes: { + ...doc.attributes, + filters: migrate(doc.attributes.filters), + }, + }); +}); + +export const savedQueryMigrations = mergeMigrationFunctionMaps( + { + '7.16.0': extractFilterReferences, + }, + filterMigrations +); diff --git a/src/plugins/data/server/saved_objects/query.ts b/src/plugins/data/server/saved_objects/query.ts index bc6225255b5e6..6fd34f4802726 100644 --- a/src/plugins/data/server/saved_objects/query.ts +++ b/src/plugins/data/server/saved_objects/query.ts @@ -7,6 +7,7 @@ */ import { SavedObjectsType } from 'kibana/server'; +import { savedQueryMigrations } from './migrations/query'; export const querySavedObjectType: SavedObjectsType = { name: 'query', @@ -38,5 +39,5 @@ export const querySavedObjectType: SavedObjectsType = { timefilter: { type: 'object', enabled: false }, }, }, - migrations: {}, + migrations: savedQueryMigrations, }; diff --git a/src/plugins/data/server/search/collectors/fetch.ts b/src/plugins/data/server/search/collectors/fetch.ts index 8c4b79b290565..a2d1917fc4770 100644 --- a/src/plugins/data/server/search/collectors/fetch.ts +++ b/src/plugins/data/server/search/collectors/fetch.ts @@ -6,21 +6,18 @@ * Side Public License, v 1. */ -import { Observable } from 'rxjs'; -import { first } from 'rxjs/operators'; -import { SharedGlobalConfig } from 'kibana/server'; import { CollectorFetchContext } from 'src/plugins/usage_collection/server'; import { CollectedUsage, ReportedUsage } from './register'; + interface SearchTelemetry { 'search-telemetry': CollectedUsage; } -export function fetchProvider(config$: Observable) { +export function fetchProvider(kibanaIndex: string) { return async ({ esClient }: CollectorFetchContext): Promise => { - const config = await config$.pipe(first()).toPromise(); const { body: esResponse } = await esClient.search( { - index: config.kibana.index, + index: kibanaIndex, body: { query: { term: { type: { value: 'search-telemetry' } } }, }, diff --git a/src/plugins/data/server/search/collectors/register.ts b/src/plugins/data/server/search/collectors/register.ts index a370377c30eea..a70b9760122a9 100644 --- a/src/plugins/data/server/search/collectors/register.ts +++ b/src/plugins/data/server/search/collectors/register.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { PluginInitializerContext } from 'kibana/server'; import { UsageCollectionSetup } from '../../../../usage_collection/server'; import { fetchProvider } from './fetch'; @@ -22,15 +21,12 @@ export interface ReportedUsage { averageDuration: number | null; } -export async function registerUsageCollector( - usageCollection: UsageCollectionSetup, - context: PluginInitializerContext -) { +export function registerUsageCollector(usageCollection: UsageCollectionSetup, kibanaIndex: string) { try { const collector = usageCollection.makeUsageCollector({ type: 'search', isReady: () => true, - fetch: fetchProvider(context.config.legacy.globalConfig$), + fetch: fetchProvider(kibanaIndex), schema: { successCount: { type: 'long' }, errorCount: { type: 'long' }, diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index 04db51fdce7fb..d3b1c57b67779 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -184,7 +184,7 @@ export class SearchService implements Plugin { core.savedObjects.registerType(searchTelemetry); if (usageCollection) { - registerUsageCollector(usageCollection, this.initializerContext); + registerUsageCollector(usageCollection, core.savedObjects.getKibanaIndex()); } expressions.registerFunction(getEsaggs({ getStartServices: core.getStartServices })); diff --git a/src/plugins/data_views/server/saved_objects/data_views.ts b/src/plugins/data_views/server/saved_objects/data_views.ts index 5bb85a9bb6e98..ca7592732c3ee 100644 --- a/src/plugins/data_views/server/saved_objects/data_views.ts +++ b/src/plugins/data_views/server/saved_objects/data_views.ts @@ -13,7 +13,8 @@ import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../../common'; export const dataViewSavedObjectType: SavedObjectsType = { name: DATA_VIEW_SAVED_OBJECT_TYPE, hidden: false, - namespaceType: 'single', + namespaceType: 'multiple-isolated', + convertToMultiNamespaceTypeVersion: '8.0.0', management: { displayName: 'Data view', icon: 'indexPatternApp', diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts index b30fcf972eda5..32704d95423f7 100644 --- a/src/plugins/discover/common/index.ts +++ b/src/plugins/discover/common/index.ts @@ -19,5 +19,6 @@ export const DOC_TABLE_LEGACY = 'doc_table:legacy'; export const MODIFY_COLUMNS_ON_SWITCH = 'discover:modifyColumnsOnSwitch'; export const SEARCH_FIELDS_FROM_SOURCE = 'discover:searchFieldsFromSource'; export const MAX_DOC_FIELDS_DISPLAYED = 'discover:maxDocFieldsDisplayed'; +export const SHOW_FIELD_STATISTICS = 'discover:showFieldStatistics'; export const SHOW_MULTIFIELDS = 'discover:showMultiFields'; export const SEARCH_EMBEDDABLE_TYPE = 'search'; diff --git a/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.test.tsx b/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.test.tsx index 15f6e619c8650..f7a383be76b9e 100644 --- a/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.test.tsx +++ b/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.test.tsx @@ -19,6 +19,7 @@ import { discoverServiceMock } from '../../../../../__mocks__/services'; import { FetchStatus } from '../../../../types'; import { Chart } from './point_series'; import { DiscoverChart } from './discover_chart'; +import { VIEW_MODE } from '../view_mode_toggle'; setHeaderActionMenuMounter(jest.fn()); @@ -94,6 +95,8 @@ function getProps(timefield?: string) { state: { columns: [] }, stateContainer: {} as GetStateReturn, timefield, + viewMode: VIEW_MODE.DOCUMENT_LEVEL, + setDiscoverViewMode: jest.fn(), }; } diff --git a/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.tsx b/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.tsx index b6509356c8c41..166c2272a00f4 100644 --- a/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.tsx +++ b/src/plugins/discover/public/application/apps/main/components/chart/discover_chart.tsx @@ -23,6 +23,8 @@ import { DiscoverHistogram } from './histogram'; import { DataCharts$, DataTotalHits$ } from '../../services/use_saved_search'; import { DiscoverServices } from '../../../../../build_services'; import { useChartPanels } from './use_chart_panels'; +import { VIEW_MODE, DocumentViewModeToggle } from '../view_mode_toggle'; +import { SHOW_FIELD_STATISTICS } from '../../../../../../common'; const DiscoverHistogramMemoized = memo(DiscoverHistogram); export const CHART_HIDDEN_KEY = 'discover:chartHidden'; @@ -36,6 +38,8 @@ export function DiscoverChart({ state, stateContainer, timefield, + viewMode, + setDiscoverViewMode, }: { resetSavedSearch: () => void; savedSearch: SavedSearch; @@ -45,8 +49,11 @@ export function DiscoverChart({ state: AppState; stateContainer: GetStateReturn; timefield?: string; + viewMode: VIEW_MODE; + setDiscoverViewMode: (viewMode: VIEW_MODE) => void; }) { const [showChartOptionsPopover, setShowChartOptionsPopover] = useState(false); + const showViewModeToggle = services.uiSettings.get(SHOW_FIELD_STATISTICS) ?? false; const { data, storage } = services; @@ -108,6 +115,16 @@ export function DiscoverChart({ onResetQuery={resetSavedSearch} /> + + {showViewModeToggle && ( + + + + )} + {timefield && ( - Time + time + + + diff --git a/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx b/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx index d313e95c1ebb1..f04454d33e9f2 100644 --- a/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx +++ b/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/helpers.tsx @@ -28,7 +28,7 @@ export interface ColumnProps { export function getTimeColumn(timeFieldName: string): ColumnProps { return { name: timeFieldName, - displayName: 'Time', + displayName: timeFieldName, isSortable: true, isRemoveable: false, colLeftIdx: -1, diff --git a/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/table_header.tsx b/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/table_header.tsx index f891e809ee702..1877c014ddcbd 100644 --- a/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/table_header.tsx +++ b/src/plugins/discover/public/application/apps/main/components/doc_table/components/table_header/table_header.tsx @@ -45,6 +45,8 @@ export function TableHeader({ void; onMoveColumn?: (name: string, idx: number) => void; @@ -54,6 +56,8 @@ export function TableHeaderColumn({ displayName, isRemoveable, isSortable, + isTimeColumn, + customLabel, name, onChangeSortOrder, onMoveColumn, @@ -65,6 +69,14 @@ export function TableHeaderColumn({ const curColSort = sortOrder.find((pair) => pair[0] === name); const curColSortDir = (curColSort && curColSort[1]) || ''; + const timeAriaLabel = i18n.translate( + 'discover.docTable.tableHeader.timeFieldIconTooltipAriaLabel', + { defaultMessage: 'Primary time field.' } + ); + const timeTooltip = i18n.translate('discover.docTable.tableHeader.timeFieldIconTooltip', { + defaultMessage: 'This field represents the time that events occurred.', + }); + // If this is the _score column, and _score is not one of the columns inside the sort, show a // warning that the _score will not be retrieved from Elasticsearch const showScoreSortWarning = name === '_score' && !curColSort; @@ -183,7 +195,15 @@ export function TableHeaderColumn({ {showScoreSortWarning && } - {displayName} + {customLabel ?? displayName} + {isTimeColumn && ( + + )} {buttons .filter((button) => button.active) .map((button, idx) => ( diff --git a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.scss b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.scss index 743f0fa5ec9fd..37ff50e333124 100644 --- a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.scss +++ b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.scss @@ -4,6 +4,10 @@ discover-app { flex-grow: 1; } +.dscAppWrapper { + overflow-y: hidden; +} + .dscPage { @include euiBreakpoint('m', 'l', 'xl') { @include kibanaFullBodyHeight(); diff --git a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx index 6c6393daf30a3..a0799777a3947 100644 --- a/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/apps/main/components/layout/discover_layout.tsx @@ -6,9 +6,8 @@ * Side Public License, v 1. */ import './discover_layout.scss'; -import React, { useState, useMemo, useCallback, useEffect, useRef } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { - EuiSpacer, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, @@ -17,6 +16,7 @@ import { EuiPage, EuiPageBody, EuiPageContent, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { METRIC_TYPE } from '@kbn/analytics'; @@ -26,7 +26,7 @@ import { LoadingSpinner } from '../loading_spinner/loading_spinner'; import { esFilters, IndexPatternField } from '../../../../../../../data/public'; import { DiscoverSidebarResponsive } from '../sidebar'; import { DiscoverLayoutProps } from './types'; -import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../../../common'; +import { SEARCH_FIELDS_FROM_SOURCE, SHOW_FIELD_STATISTICS } from '../../../../../../common'; import { popularizeField } from '../../../../helpers/popularize_field'; import { DiscoverTopNav } from '../top_nav/discover_topnav'; import { DocViewFilterFn, ElasticSearchHit } from '../../../../doc_views/doc_views_types'; @@ -43,6 +43,8 @@ import { SavedSearchURLConflictCallout, useSavedSearchAliasMatchRedirect, } from '../../../../../saved_searches'; +import { DiscoverDataVisualizerGrid } from '../../../../components/data_visualizer_grid'; +import { VIEW_MODE } from '../view_mode_toggle'; /** * Local storage key for sidebar persistence state @@ -52,6 +54,7 @@ export const SIDEBAR_CLOSED_KEY = 'discover:sidebarClosed'; const SidebarMemoized = React.memo(DiscoverSidebarResponsive); const TopNavMemoized = React.memo(DiscoverTopNav); const DiscoverChartMemoized = React.memo(DiscoverChart); +const DataVisualizerGridMemoized = React.memo(DiscoverDataVisualizerGrid); export function DiscoverLayout({ indexPattern, @@ -83,6 +86,19 @@ export function DiscoverLayout({ const { main$, charts$, totalHits$ } = savedSearchData$; const [expandedDoc, setExpandedDoc] = useState(undefined); const [inspectorSession, setInspectorSession] = useState(undefined); + + const viewMode = useMemo(() => { + if (uiSettings.get(SHOW_FIELD_STATISTICS) !== true) return VIEW_MODE.DOCUMENT_LEVEL; + return state.viewMode ?? VIEW_MODE.DOCUMENT_LEVEL; + }, [uiSettings, state.viewMode]); + + const setDiscoverViewMode = useCallback( + (mode: VIEW_MODE) => { + stateContainer.setAppState({ viewMode: mode }); + }, + [stateContainer] + ); + const fetchCounter = useRef(0); const dataState: DataMainMsg = useDataState(main$); @@ -213,6 +229,7 @@ export function DiscoverLayout({ trackUiMetric={trackUiMetric} useNewFieldsApi={useNewFieldsApi} onEditRuntimeField={onEditRuntimeField} + viewMode={viewMode} /> @@ -279,22 +296,36 @@ export function DiscoverLayout({ services={services} stateContainer={stateContainer} timefield={timeField} + viewMode={viewMode} + setDiscoverViewMode={setDiscoverViewMode} /> - - + {viewMode === VIEW_MODE.DOCUMENT_LEVEL ? ( + + ) : ( + + )} )} diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx index f2919f6a9bfd4..89e7b50187630 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx @@ -19,6 +19,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, + EuiHorizontalRule, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { UiCounterMetricType } from '@kbn/analytics'; @@ -251,6 +252,11 @@ export interface DiscoverFieldProps { * @param fieldName name of the field to delete */ onDeleteField?: (fieldName: string) => void; + + /** + * Optionally show or hide field stats in the popover + */ + showFieldStats?: boolean; } function DiscoverFieldComponent({ @@ -266,6 +272,7 @@ function DiscoverFieldComponent({ multiFields, onEditField, onDeleteField, + showFieldStats, }: DiscoverFieldProps) { const [infoIsOpen, setOpen] = useState(false); @@ -362,15 +369,27 @@ function DiscoverFieldComponent({ const details = getDetails(field); return ( <> - + {showFieldStats && ( + <> + +
+ {i18n.translate('discover.fieldChooser.discoverField.fieldTopValuesLabel', { + defaultMessage: 'Top 5 values', + })} +
+
+ + + )} + {multiFields && ( <> - + {showFieldStats && } )} + {(showFieldStats || multiFields) && } ); }; - return ( {popoverTitle} - -
- {i18n.translate('discover.fieldChooser.discoverField.fieldTopValuesLabel', { - defaultMessage: 'Top 5 values', - })} -
-
{infoIsOpen && renderPopover()}
); diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx index baf740531e6bf..e974a67aef60d 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx @@ -7,7 +7,7 @@ */ import React, { useEffect, useState } from 'react'; -import { EuiButton, EuiPopoverFooter } from '@elastic/eui'; +import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics'; import type { IndexPattern, IndexPatternField } from 'src/plugins/data/common'; @@ -46,21 +46,19 @@ export const DiscoverFieldVisualize: React.FC = React.memo( }; return ( - - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - - - - + // eslint-disable-next-line @elastic/eui/href-or-on-click + + + ); } ); diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.test.tsx index a550dbd59b9fa..03616c136df3e 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.test.tsx @@ -22,6 +22,7 @@ import { DiscoverSidebarComponent as DiscoverSidebar } from './discover_sidebar' import { ElasticSearchHit } from '../../../../doc_views/doc_views_types'; import { discoverServiceMock as mockDiscoverServices } from '../../../../../__mocks__/services'; import { stubLogstashIndexPattern } from '../../../../../../../data/common/stubs'; +import { VIEW_MODE } from '../view_mode_toggle'; jest.mock('../../../../../kibana_services', () => ({ getServices: () => mockDiscoverServices, @@ -65,6 +66,7 @@ function getCompProps(): DiscoverSidebarProps { setFieldFilter: jest.fn(), onEditRuntimeField: jest.fn(), editField: jest.fn(), + viewMode: VIEW_MODE.DOCUMENT_LEVEL, }; } diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.tsx index 0bd8c59b90c01..d13860eab0d24 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar.tsx @@ -40,6 +40,7 @@ import { getIndexPatternFieldList } from './lib/get_index_pattern_field_list'; import { DiscoverSidebarResponsiveProps } from './discover_sidebar_responsive'; import { DiscoverIndexPatternManagement } from './discover_index_pattern_management'; import { ElasticSearchHit } from '../../../../doc_views/doc_views_types'; +import { VIEW_MODE } from '../view_mode_toggle'; /** * Default number of available fields displayed and added on scroll @@ -77,6 +78,10 @@ export interface DiscoverSidebarProps extends Omit(null); @@ -205,6 +211,8 @@ export function DiscoverSidebarComponent({ return result; }, [fields]); + const showFieldStats = useMemo(() => viewMode === VIEW_MODE.DOCUMENT_LEVEL, [viewMode]); + const calculateMultiFields = () => { if (!useNewFieldsApi || !fields) { return undefined; @@ -407,6 +415,7 @@ export function DiscoverSidebarComponent({ multiFields={multiFields?.get(field.name)} onEditField={canEditIndexPatternField ? editField : undefined} onDeleteField={canEditIndexPatternField ? deleteField : undefined} + showFieldStats={showFieldStats} /> ); @@ -466,6 +475,7 @@ export function DiscoverSidebarComponent({ multiFields={multiFields?.get(field.name)} onEditField={canEditIndexPatternField ? editField : undefined} onDeleteField={canEditIndexPatternField ? deleteField : undefined} + showFieldStats={showFieldStats} /> ); @@ -494,6 +504,7 @@ export function DiscoverSidebarComponent({ multiFields={multiFields?.get(field.name)} onEditField={canEditIndexPatternField ? editField : undefined} onDeleteField={canEditIndexPatternField ? deleteField : undefined} + showFieldStats={showFieldStats} /> ); diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.test.tsx index ded7897d2a9e5..4e4fed8c65bf7 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -26,6 +26,7 @@ import { ElasticSearchHit } from '../../../../doc_views/doc_views_types'; import { FetchStatus } from '../../../../types'; import { DataDocuments$ } from '../../services/use_saved_search'; import { stubLogstashIndexPattern } from '../../../../../../../data/common/stubs'; +import { VIEW_MODE } from '../view_mode_toggle'; const mockServices = { history: () => ({ @@ -103,6 +104,7 @@ function getCompProps(): DiscoverSidebarResponsiveProps { state: {}, trackUiMetric: jest.fn(), onEditRuntimeField: jest.fn(), + viewMode: VIEW_MODE.DOCUMENT_LEVEL, }; } diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx index 90357b73c6881..368a2b2e92d34 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_sidebar_responsive.tsx @@ -37,6 +37,7 @@ import { AppState } from '../../services/discover_state'; import { DiscoverIndexPatternManagement } from './discover_index_pattern_management'; import { DataDocuments$ } from '../../services/use_saved_search'; import { calcFieldCounts } from '../../utils/calc_field_counts'; +import { VIEW_MODE } from '../view_mode_toggle'; export interface DiscoverSidebarResponsiveProps { /** @@ -106,6 +107,10 @@ export interface DiscoverSidebarResponsiveProps { * callback to execute on edit runtime field */ onEditRuntimeField: () => void; + /** + * Discover view mode + */ + viewMode: VIEW_MODE; } /** diff --git a/src/plugins/discover/public/application/apps/main/components/top_nav/get_top_nav_links.ts b/src/plugins/discover/public/application/apps/main/components/top_nav/get_top_nav_links.ts index 44d2999947f41..653e878ad01bb 100644 --- a/src/plugins/discover/public/application/apps/main/components/top_nav/get_top_nav_links.ts +++ b/src/plugins/discover/public/application/apps/main/components/top_nav/get_top_nav_links.ts @@ -16,6 +16,7 @@ import { SavedSearch } from '../../../../../saved_searches'; import { onSaveSearch } from './on_save_search'; import { GetStateReturn } from '../../services/discover_state'; import { openOptionsPopover } from './open_options_popover'; +import type { TopNavMenuData } from '../../../../../../../navigation/public'; /** * Helper function to build the top nav links @@ -38,7 +39,7 @@ export const getTopNavLinks = ({ onOpenInspector: () => void; searchSource: ISearchSource; onOpenSavedSearch: (id: string) => void; -}) => { +}): TopNavMenuData[] => { const options = { id: 'options', label: i18n.translate('discover.localMenu.localMenu.optionsTitle', { diff --git a/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/_index.scss b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/_index.scss new file mode 100644 index 0000000000000..a76c3453de32a --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/_index.scss @@ -0,0 +1 @@ +@import 'view_mode_toggle'; diff --git a/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/_view_mode_toggle.scss b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/_view_mode_toggle.scss new file mode 100644 index 0000000000000..1009ab0511957 --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/_view_mode_toggle.scss @@ -0,0 +1,12 @@ +.dscViewModeToggle { + padding-right: $euiSize; +} + +.fieldStatsButton { + display: flex; + align-items: center; +} + +.fieldStatsBetaBadge { + margin-left: $euiSizeXS; +} diff --git a/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/constants.ts b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/constants.ts new file mode 100644 index 0000000000000..d03c0710d12b3 --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/constants.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export enum VIEW_MODE { + DOCUMENT_LEVEL = 'documents', + AGGREGATED_LEVEL = 'aggregated', +} diff --git a/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/index.ts b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/index.ts new file mode 100644 index 0000000000000..95b76f5879d19 --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/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 { DocumentViewModeToggle } from './view_mode_toggle'; +export { VIEW_MODE } from './constants'; diff --git a/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/view_mode_toggle.tsx b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/view_mode_toggle.tsx new file mode 100644 index 0000000000000..3aa24c05e98d4 --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/components/view_mode_toggle/view_mode_toggle.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 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 { EuiButtonGroup, EuiBetaBadge } from '@elastic/eui'; +import React, { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { VIEW_MODE } from './constants'; +import './_index.scss'; + +export const DocumentViewModeToggle = ({ + viewMode, + setDiscoverViewMode, +}: { + viewMode: VIEW_MODE; + setDiscoverViewMode: (viewMode: VIEW_MODE) => void; +}) => { + const toggleButtons = useMemo( + () => [ + { + id: VIEW_MODE.DOCUMENT_LEVEL, + label: i18n.translate('discover.viewModes.document.label', { + defaultMessage: 'Documents', + }), + 'data-test-subj': 'dscViewModeDocumentButton', + }, + { + id: VIEW_MODE.AGGREGATED_LEVEL, + label: ( +
+ + +
+ ), + }, + ], + [] + ); + + return ( + setDiscoverViewMode(id as VIEW_MODE)} + data-test-subj={'dscViewModeToggle'} + /> + ); +}; diff --git a/src/plugins/discover/public/application/apps/main/services/discover_state.ts b/src/plugins/discover/public/application/apps/main/services/discover_state.ts index 16eb622c4a7c4..9a61fdc996e3b 100644 --- a/src/plugins/discover/public/application/apps/main/services/discover_state.ts +++ b/src/plugins/discover/public/application/apps/main/services/discover_state.ts @@ -35,6 +35,7 @@ import { DiscoverGridSettings } from '../../../components/discover_grid/types'; import { DISCOVER_APP_URL_GENERATOR, DiscoverUrlGeneratorState } from '../../../../url_generator'; import { SavedSearch } from '../../../../saved_searches'; import { handleSourceColumnState } from '../../../helpers/state_helpers'; +import { VIEW_MODE } from '../components/view_mode_toggle'; export interface AppState { /** @@ -73,6 +74,14 @@ export interface AppState { * id of the used saved query */ savedQuery?: string; + /** + * Table view: Documents vs Field Statistics + */ + viewMode?: VIEW_MODE; + /** + * Hide mini distribution/preview charts when in Field Statistics mode + */ + hideAggregatedPreview?: boolean; } interface GetStateParams { diff --git a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts index 45447fe642ad4..6cf34fd8cb024 100644 --- a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts +++ b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.test.ts @@ -31,6 +31,7 @@ describe('getStateDefaults', () => { "default_column", ], "filters": undefined, + "hideAggregatedPreview": undefined, "hideChart": undefined, "index": "index-pattern-with-timefield-id", "interval": "auto", @@ -42,6 +43,7 @@ describe('getStateDefaults', () => { "desc", ], ], + "viewMode": undefined, } `); }); @@ -61,12 +63,14 @@ describe('getStateDefaults', () => { "default_column", ], "filters": undefined, + "hideAggregatedPreview": undefined, "hideChart": undefined, "index": "the-index-pattern-id", "interval": "auto", "query": undefined, "savedQuery": undefined, "sort": Array [], + "viewMode": undefined, } `); }); diff --git a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts index 6fa4dda2eab19..50dab0273d461 100644 --- a/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts +++ b/src/plugins/discover/public/application/apps/main/utils/get_state_defaults.ts @@ -60,6 +60,8 @@ export function getStateDefaults({ interval: 'auto', filters: cloneDeep(searchSource.getOwnField('filter')), hideChart: chartHidden ? chartHidden : undefined, + viewMode: undefined, + hideAggregatedPreview: undefined, savedQuery: undefined, } as AppState; if (savedSearch.grid) { @@ -68,6 +70,13 @@ export function getStateDefaults({ if (savedSearch.hideChart !== undefined) { defaultState.hideChart = savedSearch.hideChart; } + if (savedSearch.viewMode) { + defaultState.viewMode = savedSearch.viewMode; + } + + if (savedSearch.hideAggregatedPreview) { + defaultState.hideAggregatedPreview = savedSearch.hideAggregatedPreview; + } return defaultState; } diff --git a/src/plugins/discover/public/application/apps/main/utils/persist_saved_search.ts b/src/plugins/discover/public/application/apps/main/utils/persist_saved_search.ts index 584fbe14cb59e..fa566fd485942 100644 --- a/src/plugins/discover/public/application/apps/main/utils/persist_saved_search.ts +++ b/src/plugins/discover/public/application/apps/main/utils/persist_saved_search.ts @@ -52,6 +52,14 @@ export async function persistSavedSearch( savedSearch.hideChart = state.hideChart; } + if (state.viewMode) { + savedSearch.viewMode = state.viewMode; + } + + if (state.hideAggregatedPreview) { + savedSearch.hideAggregatedPreview = state.hideAggregatedPreview; + } + try { const id = await saveSavedSearch(savedSearch, saveOptions, services.core.savedObjects.client); if (id) { diff --git a/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx b/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx new file mode 100644 index 0000000000000..5492fac014b74 --- /dev/null +++ b/src/plugins/discover/public/application/components/data_visualizer_grid/data_visualizer_grid.tsx @@ -0,0 +1,196 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useEffect, useMemo, useRef, useState } from 'react'; +import { Filter } from '@kbn/es-query'; +import { IndexPatternField, IndexPattern, DataView, Query } from '../../../../../data/common'; +import { DiscoverServices } from '../../../build_services'; +import { + EmbeddableInput, + EmbeddableOutput, + ErrorEmbeddable, + IEmbeddable, + isErrorEmbeddable, +} from '../../../../../embeddable/public'; +import { SavedSearch } from '../../../saved_searches'; +import { GetStateReturn } from '../../apps/main/services/discover_state'; + +export interface DataVisualizerGridEmbeddableInput extends EmbeddableInput { + indexPattern: IndexPattern; + savedSearch?: SavedSearch; + query?: Query; + visibleFieldNames?: string[]; + filters?: Filter[]; + showPreviewByDefault?: boolean; + /** + * Callback to add a filter to filter bar + */ + onAddFilter?: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; +} +export interface DataVisualizerGridEmbeddableOutput extends EmbeddableOutput { + showDistributions?: boolean; +} + +export interface DiscoverDataVisualizerGridProps { + /** + * Determines which columns are displayed + */ + columns: string[]; + /** + * The used index pattern + */ + indexPattern: DataView; + /** + * Saved search description + */ + searchDescription?: string; + /** + * Saved search title + */ + searchTitle?: string; + /** + * Discover plugin services + */ + services: DiscoverServices; + /** + * Optional saved search + */ + savedSearch?: SavedSearch; + /** + * Optional query to update the table content + */ + query?: Query; + /** + * Filters query to update the table content + */ + filters?: Filter[]; + stateContainer?: GetStateReturn; + /** + * Callback to add a filter to filter bar + */ + onAddFilter?: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; +} + +export const DiscoverDataVisualizerGrid = (props: DiscoverDataVisualizerGridProps) => { + const { + services, + indexPattern, + savedSearch, + query, + columns, + filters, + stateContainer, + onAddFilter, + } = props; + const { uiSettings } = services; + + const [embeddable, setEmbeddable] = useState< + | ErrorEmbeddable + | IEmbeddable + | undefined + >(); + const embeddableRoot: React.RefObject = useRef(null); + + const showPreviewByDefault = useMemo( + () => + stateContainer ? !stateContainer.appStateContainer.getState().hideAggregatedPreview : true, + [stateContainer] + ); + + useEffect(() => { + const sub = embeddable?.getOutput$().subscribe((output: DataVisualizerGridEmbeddableOutput) => { + if (output.showDistributions !== undefined && stateContainer) { + stateContainer.setAppState({ hideAggregatedPreview: !output.showDistributions }); + } + }); + + return () => { + sub?.unsubscribe(); + }; + }, [embeddable, stateContainer]); + + useEffect(() => { + if (embeddable && !isErrorEmbeddable(embeddable)) { + // Update embeddable whenever one of the important input changes + embeddable.updateInput({ + indexPattern, + savedSearch, + query, + filters, + visibleFieldNames: columns, + onAddFilter, + }); + embeddable.reload(); + } + }, [embeddable, indexPattern, savedSearch, query, columns, filters, onAddFilter]); + + useEffect(() => { + if (showPreviewByDefault && embeddable && !isErrorEmbeddable(embeddable)) { + // Update embeddable whenever one of the important input changes + embeddable.updateInput({ + showPreviewByDefault, + }); + embeddable.reload(); + } + }, [showPreviewByDefault, uiSettings, embeddable]); + + useEffect(() => { + return () => { + // Clean up embeddable upon unmounting + embeddable?.destroy(); + }; + }, [embeddable]); + + useEffect(() => { + let unmounted = false; + const loadEmbeddable = async () => { + if (services.embeddable) { + const factory = services.embeddable.getEmbeddableFactory< + DataVisualizerGridEmbeddableInput, + DataVisualizerGridEmbeddableOutput + >('data_visualizer_grid'); + if (factory) { + // Initialize embeddable with information available at mount + const initializedEmbeddable = await factory.create({ + id: 'discover_data_visualizer_grid', + indexPattern, + savedSearch, + query, + showPreviewByDefault, + onAddFilter, + }); + if (!unmounted) { + setEmbeddable(initializedEmbeddable); + } + } + } + }; + loadEmbeddable(); + return () => { + unmounted = true; + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [services.embeddable, showPreviewByDefault]); + + // We can only render after embeddable has already initialized + useEffect(() => { + if (embeddableRoot.current && embeddable) { + embeddable.render(embeddableRoot.current); + } + }, [embeddable, embeddableRoot, uiSettings]); + + return ( +
+ ); +}; diff --git a/src/plugins/discover/public/application/components/data_visualizer_grid/field_stats_table_embeddable.tsx b/src/plugins/discover/public/application/components/data_visualizer_grid/field_stats_table_embeddable.tsx new file mode 100644 index 0000000000000..099f45bf988cc --- /dev/null +++ b/src/plugins/discover/public/application/components/data_visualizer_grid/field_stats_table_embeddable.tsx @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { I18nProvider } from '@kbn/i18n/react'; +import { + DiscoverDataVisualizerGrid, + DiscoverDataVisualizerGridProps, +} from './data_visualizer_grid'; + +export function FieldStatsTableEmbeddable(renderProps: DiscoverDataVisualizerGridProps) { + return ( + + + + ); +} diff --git a/src/plugins/discover/public/application/components/data_visualizer_grid/index.ts b/src/plugins/discover/public/application/components/data_visualizer_grid/index.ts new file mode 100644 index 0000000000000..dc85495a7c2ec --- /dev/null +++ b/src/plugins/discover/public/application/components/data_visualizer_grid/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 { DiscoverDataVisualizerGrid } from './data_visualizer_grid'; diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.test.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.test.tsx index 46e30dd23525b..e5ea657032403 100644 --- a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.test.tsx +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.test.tsx @@ -117,7 +117,15 @@ describe('Discover grid columns ', function () { [Function], [Function], ], - "display": "Time (timestamp)", + "display": + timestamp + + + , "id": "timestamp", "initialWidth": 190, "isSortable": true, diff --git a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx index 2f4c0b5167df8..5eb55a8e99cde 100644 --- a/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx +++ b/src/plugins/discover/public/application/components/discover_grid/discover_grid_columns.tsx @@ -6,9 +6,9 @@ * Side Public License, v 1. */ -import React from 'react'; +import React, { Fragment } from 'react'; import { i18n } from '@kbn/i18n'; -import { EuiDataGridColumn, EuiScreenReaderOnly } from '@elastic/eui'; +import { EuiDataGridColumn, EuiIconTip, EuiScreenReaderOnly } from '@elastic/eui'; import { ExpandButton } from './discover_grid_expand_button'; import { DiscoverGridSettings } from './types'; import type { IndexPattern } from '../../../../../data/common'; @@ -57,9 +57,6 @@ export function buildEuiGridColumn( defaultColumns: boolean, isSortEnabled: boolean ) { - const timeString = i18n.translate('discover.timeLabel', { - defaultMessage: 'Time', - }); const indexPatternField = indexPattern.getFieldByName(columnName); const column: EuiDataGridColumn = { id: columnName, @@ -88,7 +85,23 @@ export function buildEuiGridColumn( }; if (column.id === indexPattern.timeFieldName) { - column.display = `${timeString} (${indexPattern.timeFieldName})`; + const primaryTimeAriaLabel = i18n.translate( + 'discover.docTable.tableHeader.timeFieldIconTooltipAriaLabel', + { defaultMessage: 'Primary time field.' } + ); + const primaryTimeTooltip = i18n.translate( + 'discover.docTable.tableHeader.timeFieldIconTooltip', + { + defaultMessage: 'This field represents the time that events occurred.', + } + ); + + column.display = ( + + {indexPatternField?.customLabel ?? indexPattern.timeFieldName}{' '} + + + ); column.initialWidth = defaultTimeColumnWidth; } if (columnWidth > 0) { diff --git a/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx b/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx index 89c47559d7b4c..808962dc8319d 100644 --- a/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx +++ b/src/plugins/discover/public/application/embeddable/saved_search_embeddable.tsx @@ -19,12 +19,12 @@ import { SEARCH_EMBEDDABLE_TYPE } from './constants'; import { APPLY_FILTER_TRIGGER, esFilters, FilterManager } from '../../../../data/public'; import { DiscoverServices } from '../../build_services'; import { - Query, - TimeRange, Filter, IndexPattern, - ISearchSource, IndexPatternField, + ISearchSource, + Query, + TimeRange, } from '../../../../data/common'; import { ElasticSearchHit } from '../doc_views/doc_views_types'; import { SavedSearchEmbeddableComponent } from './saved_search_embeddable_component'; @@ -35,6 +35,7 @@ import { DOC_TABLE_LEGACY, SAMPLE_SIZE_SETTING, SEARCH_FIELDS_FROM_SOURCE, + SHOW_FIELD_STATISTICS, SORT_DEFAULT_ORDER_SETTING, } from '../../../common'; import * as columnActions from '../apps/main/components/doc_table/actions/columns'; @@ -45,6 +46,8 @@ import { DocTableProps } from '../apps/main/components/doc_table/doc_table_wrapp import { getDefaultSort } from '../apps/main/components/doc_table'; import { SortOrder } from '../apps/main/components/doc_table/components/table_header/helpers'; import { updateSearchSource } from './helpers/update_search_source'; +import { VIEW_MODE } from '../apps/main/components/view_mode_toggle'; +import { FieldStatsTableEmbeddable } from '../components/data_visualizer_grid/field_stats_table_embeddable'; export type SearchProps = Partial & Partial & { @@ -379,6 +382,28 @@ export class SavedSearchEmbeddable if (!this.searchProps) { return; } + + if ( + this.services.uiSettings.get(SHOW_FIELD_STATISTICS) === true && + this.savedSearch.viewMode === VIEW_MODE.AGGREGATED_LEVEL && + searchProps.services && + searchProps.indexPattern && + Array.isArray(searchProps.columns) + ) { + ReactDOM.render( + , + domNode + ); + return; + } const useLegacyTable = this.services.uiSettings.get(DOC_TABLE_LEGACY); const props = { searchProps, diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts index ac16b6b3cc2ba..a6b175e34bd13 100644 --- a/src/plugins/discover/public/build_services.ts +++ b/src/plugins/discover/public/build_services.ts @@ -37,6 +37,7 @@ import { UrlForwardingStart } from '../../url_forwarding/public'; import { NavigationPublicPluginStart } from '../../navigation/public'; import { IndexPatternFieldEditorStart } from '../../index_pattern_field_editor/public'; import { FieldFormatsStart } from '../../field_formats/public'; +import { EmbeddableStart } from '../../embeddable/public'; import type { SpacesApi } from '../../../../x-pack/plugins/spaces/public'; @@ -47,6 +48,7 @@ export interface DiscoverServices { core: CoreStart; data: DataPublicPluginStart; docLinks: DocLinksStart; + embeddable: EmbeddableStart; history: () => History; theme: ChartsPluginStart['theme']; filterManager: FilterManager; @@ -83,6 +85,7 @@ export function buildServices( core, data: plugins.data, docLinks: core.docLinks, + embeddable: plugins.embeddable, theme: plugins.charts.theme, fieldFormats: plugins.fieldFormats, filterManager: plugins.data.query.filterManager, diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx index e170e61f7ebc5..c91bcf3897e14 100644 --- a/src/plugins/discover/public/plugin.tsx +++ b/src/plugins/discover/public/plugin.tsx @@ -348,6 +348,11 @@ export class DiscoverPlugin await depsStart.data.indexPatterns.clearCache(); const { renderApp } = await import('./application'); + + // FIXME: Temporarily hide overflow-y in Discover app when Field Stats table is shown + // due to EUI bug https://github.com/elastic/eui/pull/5152 + params.element.classList.add('dscAppWrapper'); + const unmount = renderApp(params.element); return () => { unlistenParentHistory(); diff --git a/src/plugins/discover/public/saved_searches/get_saved_searches.test.ts b/src/plugins/discover/public/saved_searches/get_saved_searches.test.ts index 755831e7009ed..560e16b12e5ed 100644 --- a/src/plugins/discover/public/saved_searches/get_saved_searches.test.ts +++ b/src/plugins/discover/public/saved_searches/get_saved_searches.test.ts @@ -101,6 +101,7 @@ describe('getSavedSearch', () => { ], "description": "description", "grid": Object {}, + "hideAggregatedPreview": undefined, "hideChart": false, "id": "ccf1af80-2297-11ec-86e0-1155ffb9c7a7", "searchSource": Object { @@ -138,6 +139,7 @@ describe('getSavedSearch', () => { ], ], "title": "test1", + "viewMode": undefined, } `); }); diff --git a/src/plugins/discover/public/saved_searches/saved_searches_utils.test.ts b/src/plugins/discover/public/saved_searches/saved_searches_utils.test.ts index 12c73e86b3dc4..82510340f30f1 100644 --- a/src/plugins/discover/public/saved_searches/saved_searches_utils.test.ts +++ b/src/plugins/discover/public/saved_searches/saved_searches_utils.test.ts @@ -54,6 +54,7 @@ describe('saved_searches_utils', () => { ], "description": "foo", "grid": Object {}, + "hideAggregatedPreview": undefined, "hideChart": true, "id": "id", "searchSource": SearchSource { @@ -74,6 +75,7 @@ describe('saved_searches_utils', () => { "sharingSavedObjectProps": Object {}, "sort": Array [], "title": "saved search", + "viewMode": undefined, } `); }); @@ -122,6 +124,7 @@ describe('saved_searches_utils', () => { ], "description": "description", "grid": Object {}, + "hideAggregatedPreview": undefined, "hideChart": true, "kibanaSavedObjectMeta": Object { "searchSourceJSON": "{}", @@ -133,6 +136,7 @@ describe('saved_searches_utils', () => { ], ], "title": "title", + "viewMode": undefined, } `); }); diff --git a/src/plugins/discover/public/saved_searches/saved_searches_utils.ts b/src/plugins/discover/public/saved_searches/saved_searches_utils.ts index 98ab2267a875e..064ee6afe0e99 100644 --- a/src/plugins/discover/public/saved_searches/saved_searches_utils.ts +++ b/src/plugins/discover/public/saved_searches/saved_searches_utils.ts @@ -41,6 +41,8 @@ export const fromSavedSearchAttributes = ( description: attributes.description, grid: attributes.grid, hideChart: attributes.hideChart, + viewMode: attributes.viewMode, + hideAggregatedPreview: attributes.hideAggregatedPreview, }); export const toSavedSearchAttributes = ( @@ -54,4 +56,6 @@ export const toSavedSearchAttributes = ( description: savedSearch.description ?? '', grid: savedSearch.grid ?? {}, hideChart: savedSearch.hideChart ?? false, + viewMode: savedSearch.viewMode, + hideAggregatedPreview: savedSearch.hideAggregatedPreview, }); diff --git a/src/plugins/discover/public/saved_searches/types.ts b/src/plugins/discover/public/saved_searches/types.ts index 10a6282063d38..b3a67ea57e769 100644 --- a/src/plugins/discover/public/saved_searches/types.ts +++ b/src/plugins/discover/public/saved_searches/types.ts @@ -8,6 +8,7 @@ import type { ISearchSource } from '../../../data/public'; import { DiscoverGridSettingsColumn } from '../application/components/discover_grid/types'; +import { VIEW_MODE } from '../application/apps/main/components/view_mode_toggle'; /** @internal **/ export interface SavedSearchAttributes { @@ -22,6 +23,8 @@ export interface SavedSearchAttributes { kibanaSavedObjectMeta: { searchSourceJSON: string; }; + viewMode?: VIEW_MODE; + hideAggregatedPreview?: boolean; } /** @internal **/ @@ -44,4 +47,6 @@ export interface SavedSearch { aliasTargetId?: string; errorJSON?: string; }; + viewMode?: VIEW_MODE; + hideAggregatedPreview?: boolean; } diff --git a/src/plugins/discover/server/saved_objects/search.ts b/src/plugins/discover/server/saved_objects/search.ts index 6a85685407612..23d9312e82897 100644 --- a/src/plugins/discover/server/saved_objects/search.ts +++ b/src/plugins/discover/server/saved_objects/search.ts @@ -32,7 +32,9 @@ export const searchSavedObjectType: SavedObjectsType = { properties: { columns: { type: 'keyword', index: false, doc_values: false }, description: { type: 'text' }, + viewMode: { type: 'keyword', index: false, doc_values: false }, hideChart: { type: 'boolean', index: false, doc_values: false }, + hideAggregatedPreview: { type: 'boolean', index: false, doc_values: false }, hits: { type: 'integer', index: false, doc_values: false }, kibanaSavedObjectMeta: { properties: { diff --git a/src/plugins/discover/server/ui_settings.ts b/src/plugins/discover/server/ui_settings.ts index d6a105bdb6263..529ba0d1beef1 100644 --- a/src/plugins/discover/server/ui_settings.ts +++ b/src/plugins/discover/server/ui_settings.ts @@ -26,6 +26,7 @@ import { SEARCH_FIELDS_FROM_SOURCE, MAX_DOC_FIELDS_DISPLAYED, SHOW_MULTIFIELDS, + SHOW_FIELD_STATISTICS, } from '../common'; export const getUiSettings: () => Record = () => ({ @@ -172,6 +173,7 @@ export const getUiSettings: () => Record = () => ({ name: 'discover:useLegacyDataGrid', }, }, + [MODIFY_COLUMNS_ON_SWITCH]: { name: i18n.translate('discover.advancedSettings.discover.modifyColumnsOnSwitchTitle', { defaultMessage: 'Modify columns when changing data views', @@ -201,6 +203,24 @@ export const getUiSettings: () => Record = () => ({ category: ['discover'], schema: schema.boolean(), }, + [SHOW_FIELD_STATISTICS]: { + name: i18n.translate('discover.advancedSettings.discover.showFieldStatistics', { + defaultMessage: 'Show field statistics', + }), + description: i18n.translate( + 'discover.advancedSettings.discover.showFieldStatisticsDescription', + { + defaultMessage: `Enable "Field statistics" table in Discover.`, + } + ), + value: false, + category: ['discover'], + schema: schema.boolean(), + metric: { + type: METRIC_TYPE.CLICK, + name: 'discover:showFieldStatistics', + }, + }, [SHOW_MULTIFIELDS]: { name: i18n.translate('discover.advancedSettings.discover.showMultifields', { defaultMessage: 'Show multi-fields', diff --git a/src/plugins/home/public/application/components/tutorial_directory.js b/src/plugins/home/public/application/components/tutorial_directory.js index ac0d1524145a1..a1a93e3eba542 100644 --- a/src/plugins/home/public/application/components/tutorial_directory.js +++ b/src/plugins/home/public/application/components/tutorial_directory.js @@ -218,7 +218,13 @@ class TutorialDirectoryUi extends React.Component { pageTitle: ( + ), + description: ( + ), tabs, diff --git a/src/plugins/home/server/services/sample_data/lib/register_with_integrations.ts b/src/plugins/home/server/services/sample_data/lib/register_with_integrations.ts index e33cd58910fd6..d06dcacff18d9 100644 --- a/src/plugins/home/server/services/sample_data/lib/register_with_integrations.ts +++ b/src/plugins/home/server/services/sample_data/lib/register_with_integrations.ts @@ -22,7 +22,7 @@ export function registerSampleDatasetWithIntegration( defaultMessage: 'Sample Data', }), description: i18n.translate('home.sampleData.customIntegrationsDescription', { - defaultMessage: 'Add sample data and assets to Elasticsearch and Kibana.', + defaultMessage: 'Explore data in Kibana with these one-click data sets.', }), uiInternalPath: `${HOME_APP_BASE_PATH}#/tutorial_directory/sampleData`, isBeta: false, diff --git a/src/plugins/home/server/services/sample_data/sample_data_registry.ts b/src/plugins/home/server/services/sample_data/sample_data_registry.ts index b88f42ca970af..ef453592d9790 100644 --- a/src/plugins/home/server/services/sample_data/sample_data_registry.ts +++ b/src/plugins/home/server/services/sample_data/sample_data_registry.ts @@ -61,7 +61,8 @@ export class SampleDataRegistry { customIntegrations?: CustomIntegrationsPluginSetup ) { if (usageCollections) { - makeSampleDataUsageCollector(usageCollections, this.initContext); + const kibanaIndex = core.savedObjects.getKibanaIndex(); + makeSampleDataUsageCollector(usageCollections, kibanaIndex); } const usageTracker = usage( core.getStartServices().then(([coreStart]) => coreStart.savedObjects), diff --git a/src/plugins/home/server/services/sample_data/usage/collector.ts b/src/plugins/home/server/services/sample_data/usage/collector.ts index df7d485c1f6fa..06c0c9239942b 100644 --- a/src/plugins/home/server/services/sample_data/usage/collector.ts +++ b/src/plugins/home/server/services/sample_data/usage/collector.ts @@ -6,20 +6,16 @@ * Side Public License, v 1. */ -import type { PluginInitializerContext } from 'kibana/server'; import type { UsageCollectionSetup } from '../../../../../usage_collection/server'; import { fetchProvider, TelemetryResponse } from './collector_fetch'; export function makeSampleDataUsageCollector( usageCollection: UsageCollectionSetup, - context: PluginInitializerContext + kibanaIndex: string ) { - const config = context.config.legacy.get(); - const index = config.kibana.index; - const collector = usageCollection.makeUsageCollector({ type: 'sample-data', - fetch: fetchProvider(index), + fetch: fetchProvider(kibanaIndex), isReady: () => true, schema: { installed: { type: 'array', items: { type: 'keyword' } }, diff --git a/src/plugins/home/server/tutorials/activemq_logs/index.ts b/src/plugins/home/server/tutorials/activemq_logs/index.ts index 64a6fa575f5b6..a277b37838562 100644 --- a/src/plugins/home/server/tutorials/activemq_logs/index.ts +++ b/src/plugins/home/server/tutorials/activemq_logs/index.ts @@ -24,12 +24,12 @@ export function activemqLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'activemqLogs', name: i18n.translate('home.tutorials.activemqLogs.nameTitle', { - defaultMessage: 'ActiveMQ logs', + defaultMessage: 'ActiveMQ Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.activemqLogs.shortDescription', { - defaultMessage: 'Collect ActiveMQ logs with Filebeat.', + defaultMessage: 'Collect and parse logs from ActiveMQ instances with Filebeat.', }), longDescription: i18n.translate('home.tutorials.activemqLogs.longDescription', { defaultMessage: 'Collect ActiveMQ logs with Filebeat. \ diff --git a/src/plugins/home/server/tutorials/activemq_metrics/index.ts b/src/plugins/home/server/tutorials/activemq_metrics/index.ts index 7a59d6d4b70d1..9a001c149cda0 100644 --- a/src/plugins/home/server/tutorials/activemq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/activemq_metrics/index.ts @@ -23,16 +23,16 @@ export function activemqMetricsSpecProvider(context: TutorialContext): TutorialS return { id: 'activemqMetrics', name: i18n.translate('home.tutorials.activemqMetrics.nameTitle', { - defaultMessage: 'ActiveMQ metrics', + defaultMessage: 'ActiveMQ Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.activemqMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from ActiveMQ instances.', + defaultMessage: 'Collect metrics from ActiveMQ instances with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.activemqMetrics.longDescription', { defaultMessage: - 'The `activemq` Metricbeat module fetches monitoring metrics from ActiveMQ instances \ + 'The `activemq` Metricbeat module fetches metrics from ActiveMQ instances \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-activemq.html', diff --git a/src/plugins/home/server/tutorials/aerospike_metrics/index.ts b/src/plugins/home/server/tutorials/aerospike_metrics/index.ts index 75dd45272db69..3e574f2c75496 100644 --- a/src/plugins/home/server/tutorials/aerospike_metrics/index.ts +++ b/src/plugins/home/server/tutorials/aerospike_metrics/index.ts @@ -23,17 +23,17 @@ export function aerospikeMetricsSpecProvider(context: TutorialContext): Tutorial return { id: 'aerospikeMetrics', name: i18n.translate('home.tutorials.aerospikeMetrics.nameTitle', { - defaultMessage: 'Aerospike metrics', + defaultMessage: 'Aerospike Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.aerospikeMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Aerospike server.', + defaultMessage: 'Collect metrics from Aerospike servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.aerospikeMetrics.longDescription', { defaultMessage: - 'The `aerospike` Metricbeat module fetches internal metrics from Aerospike. \ + 'The `aerospike` Metricbeat module fetches metrics from Aerospike. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-aerospike.html', diff --git a/src/plugins/home/server/tutorials/apache_logs/index.ts b/src/plugins/home/server/tutorials/apache_logs/index.ts index 8606a40fe0a23..6e588fd86588d 100644 --- a/src/plugins/home/server/tutorials/apache_logs/index.ts +++ b/src/plugins/home/server/tutorials/apache_logs/index.ts @@ -24,12 +24,12 @@ export function apacheLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'apacheLogs', name: i18n.translate('home.tutorials.apacheLogs.nameTitle', { - defaultMessage: 'Apache logs', + defaultMessage: 'Apache HTTP Server Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.apacheLogs.shortDescription', { - defaultMessage: 'Collect and parse access and error logs created by the Apache HTTP server.', + defaultMessage: 'Collect and parse logs from Apache HTTP servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.apacheLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/apache_metrics/index.ts b/src/plugins/home/server/tutorials/apache_metrics/index.ts index f013f3da737f0..17b495d1460c5 100644 --- a/src/plugins/home/server/tutorials/apache_metrics/index.ts +++ b/src/plugins/home/server/tutorials/apache_metrics/index.ts @@ -23,16 +23,16 @@ export function apacheMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: 'apacheMetrics', name: i18n.translate('home.tutorials.apacheMetrics.nameTitle', { - defaultMessage: 'Apache metrics', + defaultMessage: 'Apache HTTP Server Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.apacheMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Apache 2 HTTP server.', + defaultMessage: 'Collect metrics from Apache HTTP servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.apacheMetrics.longDescription', { defaultMessage: - 'The `apache` Metricbeat module fetches internal metrics from the Apache 2 HTTP server. \ + 'The `apache` Metricbeat module fetches metrics from Apache 2 HTTP server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-apache.html', diff --git a/src/plugins/home/server/tutorials/auditbeat/index.ts b/src/plugins/home/server/tutorials/auditbeat/index.ts index 8bd6450b1daa4..96e5d4bcda393 100644 --- a/src/plugins/home/server/tutorials/auditbeat/index.ts +++ b/src/plugins/home/server/tutorials/auditbeat/index.ts @@ -24,12 +24,12 @@ export function auditbeatSpecProvider(context: TutorialContext): TutorialSchema return { id: 'auditbeat', name: i18n.translate('home.tutorials.auditbeat.nameTitle', { - defaultMessage: 'Auditbeat', + defaultMessage: 'Auditbeat Events', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.auditbeat.shortDescription', { - defaultMessage: 'Collect audit data from your hosts.', + defaultMessage: 'Collect events from your servers with Auditbeat.', }), longDescription: i18n.translate('home.tutorials.auditbeat.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/auditd_logs/index.ts b/src/plugins/home/server/tutorials/auditd_logs/index.ts index a0d6f5f683e2c..6993196d93417 100644 --- a/src/plugins/home/server/tutorials/auditd_logs/index.ts +++ b/src/plugins/home/server/tutorials/auditd_logs/index.ts @@ -24,16 +24,16 @@ export function auditdLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'auditdLogs', name: i18n.translate('home.tutorials.auditdLogs.nameTitle', { - defaultMessage: 'Auditd logs', + defaultMessage: 'Auditd Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.auditdLogs.shortDescription', { - defaultMessage: 'Collect logs from the Linux auditd daemon.', + defaultMessage: 'Collect and parse logs from Linux audit daemon with Filebeat.', }), longDescription: i18n.translate('home.tutorials.auditdLogs.longDescription', { defaultMessage: - 'The module collects and parses logs from the audit daemon ( `auditd`). \ + 'The module collects and parses logs from audit daemon ( `auditd`). \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-auditd.html', diff --git a/src/plugins/home/server/tutorials/aws_logs/index.ts b/src/plugins/home/server/tutorials/aws_logs/index.ts index 3458800b33f0a..62fbcc4eebc18 100644 --- a/src/plugins/home/server/tutorials/aws_logs/index.ts +++ b/src/plugins/home/server/tutorials/aws_logs/index.ts @@ -24,12 +24,12 @@ export function awsLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'awsLogs', name: i18n.translate('home.tutorials.awsLogs.nameTitle', { - defaultMessage: 'AWS S3 based logs', + defaultMessage: 'AWS S3 based Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.awsLogs.shortDescription', { - defaultMessage: 'Collect AWS logs from S3 bucket with Filebeat.', + defaultMessage: 'Collect and parse logs from AWS S3 buckets with Filebeat.', }), longDescription: i18n.translate('home.tutorials.awsLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/aws_metrics/index.ts b/src/plugins/home/server/tutorials/aws_metrics/index.ts index 7c3a15a47d784..6bf1bf64bff9f 100644 --- a/src/plugins/home/server/tutorials/aws_metrics/index.ts +++ b/src/plugins/home/server/tutorials/aws_metrics/index.ts @@ -23,17 +23,17 @@ export function awsMetricsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'awsMetrics', name: i18n.translate('home.tutorials.awsMetrics.nameTitle', { - defaultMessage: 'AWS metrics', + defaultMessage: 'AWS Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.awsMetrics.shortDescription', { defaultMessage: - 'Fetch monitoring metrics for EC2 instances from the AWS APIs and Cloudwatch.', + 'Collect metrics for EC2 instances from AWS APIs and Cloudwatch with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.awsMetrics.longDescription', { defaultMessage: - 'The `aws` Metricbeat module fetches monitoring metrics from the AWS APIs and Cloudwatch. \ + 'The `aws` Metricbeat module fetches metrics from AWS APIs and Cloudwatch. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-aws.html', diff --git a/src/plugins/home/server/tutorials/azure_logs/index.ts b/src/plugins/home/server/tutorials/azure_logs/index.ts index 2bf1527a79c40..3c9438d9a6298 100644 --- a/src/plugins/home/server/tutorials/azure_logs/index.ts +++ b/src/plugins/home/server/tutorials/azure_logs/index.ts @@ -24,13 +24,13 @@ export function azureLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'azureLogs', name: i18n.translate('home.tutorials.azureLogs.nameTitle', { - defaultMessage: 'Azure logs', + defaultMessage: 'Azure Logs', }), moduleName, isBeta: true, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.azureLogs.shortDescription', { - defaultMessage: 'Collects Azure activity and audit related logs.', + defaultMessage: 'Collect and parse logs from Azure with Filebeat.', }), longDescription: i18n.translate('home.tutorials.azureLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/azure_metrics/index.ts b/src/plugins/home/server/tutorials/azure_metrics/index.ts index 4a6112510b333..310f954104634 100644 --- a/src/plugins/home/server/tutorials/azure_metrics/index.ts +++ b/src/plugins/home/server/tutorials/azure_metrics/index.ts @@ -23,13 +23,13 @@ export function azureMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'azureMetrics', name: i18n.translate('home.tutorials.azureMetrics.nameTitle', { - defaultMessage: 'Azure metrics', + defaultMessage: 'Azure Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.azureMetrics.shortDescription', { - defaultMessage: 'Fetch Azure Monitor metrics.', + defaultMessage: 'Collect metrics from Azure with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.azureMetrics.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/barracuda_logs/index.ts b/src/plugins/home/server/tutorials/barracuda_logs/index.ts index 35ce10e00892e..cdfd75b9728b9 100644 --- a/src/plugins/home/server/tutorials/barracuda_logs/index.ts +++ b/src/plugins/home/server/tutorials/barracuda_logs/index.ts @@ -24,12 +24,13 @@ export function barracudaLogsSpecProvider(context: TutorialContext): TutorialSch return { id: 'barracudaLogs', name: i18n.translate('home.tutorials.barracudaLogs.nameTitle', { - defaultMessage: 'Barracuda logs', + defaultMessage: 'Barracuda Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.barracudaLogs.shortDescription', { - defaultMessage: 'Collect Barracuda Web Application Firewall logs over syslog or from a file.', + defaultMessage: + 'Collect and parse logs from Barracuda Web Application Firewall with Filebeat.', }), longDescription: i18n.translate('home.tutorials.barracudaLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/bluecoat_logs/index.ts b/src/plugins/home/server/tutorials/bluecoat_logs/index.ts index 85c7dff85d3e6..a7db5b04ee40d 100644 --- a/src/plugins/home/server/tutorials/bluecoat_logs/index.ts +++ b/src/plugins/home/server/tutorials/bluecoat_logs/index.ts @@ -24,12 +24,12 @@ export function bluecoatLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'bluecoatLogs', name: i18n.translate('home.tutorials.bluecoatLogs.nameTitle', { - defaultMessage: 'Bluecoat logs', + defaultMessage: 'Bluecoat Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.bluecoatLogs.shortDescription', { - defaultMessage: 'Collect Blue Coat Director logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Blue Coat Director with Filebeat.', }), longDescription: i18n.translate('home.tutorials.bluecoatLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/cef_logs/index.ts b/src/plugins/home/server/tutorials/cef_logs/index.ts index cfd267f661d2a..1366198d610d7 100644 --- a/src/plugins/home/server/tutorials/cef_logs/index.ts +++ b/src/plugins/home/server/tutorials/cef_logs/index.ts @@ -24,12 +24,12 @@ export function cefLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'cefLogs', name: i18n.translate('home.tutorials.cefLogs.nameTitle', { - defaultMessage: 'CEF logs', + defaultMessage: 'CEF Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.cefLogs.shortDescription', { - defaultMessage: 'Collect Common Event Format (CEF) log data over syslog.', + defaultMessage: 'Collect and parse logs from Common Event Format (CEF) with Filebeat.', }), longDescription: i18n.translate('home.tutorials.cefLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/ceph_metrics/index.ts b/src/plugins/home/server/tutorials/ceph_metrics/index.ts index 821067d87c905..6a53789d26f7c 100644 --- a/src/plugins/home/server/tutorials/ceph_metrics/index.ts +++ b/src/plugins/home/server/tutorials/ceph_metrics/index.ts @@ -23,17 +23,17 @@ export function cephMetricsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'cephMetrics', name: i18n.translate('home.tutorials.cephMetrics.nameTitle', { - defaultMessage: 'Ceph metrics', + defaultMessage: 'Ceph Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.cephMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Ceph server.', + defaultMessage: 'Collect metrics from Ceph servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.cephMetrics.longDescription', { defaultMessage: - 'The `ceph` Metricbeat module fetches internal metrics from Ceph. \ + 'The `ceph` Metricbeat module fetches metrics from Ceph. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-ceph.html', diff --git a/src/plugins/home/server/tutorials/checkpoint_logs/index.ts b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts index 9c0d5591ae35b..b5ea6be42403b 100644 --- a/src/plugins/home/server/tutorials/checkpoint_logs/index.ts +++ b/src/plugins/home/server/tutorials/checkpoint_logs/index.ts @@ -24,12 +24,12 @@ export function checkpointLogsSpecProvider(context: TutorialContext): TutorialSc return { id: 'checkpointLogs', name: i18n.translate('home.tutorials.checkpointLogs.nameTitle', { - defaultMessage: 'Check Point logs', + defaultMessage: 'Check Point Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.checkpointLogs.shortDescription', { - defaultMessage: 'Collect Check Point firewall logs.', + defaultMessage: 'Collect and parse logs from Check Point firewalls with Filebeat.', }), longDescription: i18n.translate('home.tutorials.checkpointLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/cisco_logs/index.ts b/src/plugins/home/server/tutorials/cisco_logs/index.ts index 50b79f448b316..922cfbf1e23ee 100644 --- a/src/plugins/home/server/tutorials/cisco_logs/index.ts +++ b/src/plugins/home/server/tutorials/cisco_logs/index.ts @@ -24,12 +24,12 @@ export function ciscoLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'ciscoLogs', name: i18n.translate('home.tutorials.ciscoLogs.nameTitle', { - defaultMessage: 'Cisco logs', + defaultMessage: 'Cisco Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.ciscoLogs.shortDescription', { - defaultMessage: 'Collect Cisco network device logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Cisco network devices with Filebeat.', }), longDescription: i18n.translate('home.tutorials.ciscoLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/cloudwatch_logs/index.ts b/src/plugins/home/server/tutorials/cloudwatch_logs/index.ts index cf0c27ed9be73..5564d11be4d19 100644 --- a/src/plugins/home/server/tutorials/cloudwatch_logs/index.ts +++ b/src/plugins/home/server/tutorials/cloudwatch_logs/index.ts @@ -23,12 +23,12 @@ export function cloudwatchLogsSpecProvider(context: TutorialContext): TutorialSc return { id: 'cloudwatchLogs', name: i18n.translate('home.tutorials.cloudwatchLogs.nameTitle', { - defaultMessage: 'AWS Cloudwatch logs', + defaultMessage: 'AWS Cloudwatch Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.cloudwatchLogs.shortDescription', { - defaultMessage: 'Collect Cloudwatch logs with Functionbeat.', + defaultMessage: 'Collect and parse logs from AWS Cloudwatch with Functionbeat.', }), longDescription: i18n.translate('home.tutorials.cloudwatchLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts index e43d05a0a098f..535c8aaa90768 100644 --- a/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/cockroachdb_metrics/index.ts @@ -23,16 +23,16 @@ export function cockroachdbMetricsSpecProvider(context: TutorialContext): Tutori return { id: 'cockroachdbMetrics', name: i18n.translate('home.tutorials.cockroachdbMetrics.nameTitle', { - defaultMessage: 'CockroachDB metrics', + defaultMessage: 'CockroachDB Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.cockroachdbMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the CockroachDB server.', + defaultMessage: 'Collect metrics from CockroachDB servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.cockroachdbMetrics.longDescription', { defaultMessage: - 'The `cockroachdb` Metricbeat module fetches monitoring metrics from CockroachDB. \ + 'The `cockroachdb` Metricbeat module fetches metrics from CockroachDB. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-cockroachdb.html', diff --git a/src/plugins/home/server/tutorials/consul_metrics/index.ts b/src/plugins/home/server/tutorials/consul_metrics/index.ts index 915920db5882c..ca7179d55fd89 100644 --- a/src/plugins/home/server/tutorials/consul_metrics/index.ts +++ b/src/plugins/home/server/tutorials/consul_metrics/index.ts @@ -23,16 +23,16 @@ export function consulMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: 'consulMetrics', name: i18n.translate('home.tutorials.consulMetrics.nameTitle', { - defaultMessage: 'Consul metrics', + defaultMessage: 'Consul Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.consulMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the Consul server.', + defaultMessage: 'Collect metrics from Consul servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.consulMetrics.longDescription', { defaultMessage: - 'The `consul` Metricbeat module fetches monitoring metrics from Consul. \ + 'The `consul` Metricbeat module fetches metrics from Consul. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-consul.html', diff --git a/src/plugins/home/server/tutorials/coredns_logs/index.ts b/src/plugins/home/server/tutorials/coredns_logs/index.ts index 298464651f7fc..1261c67135001 100644 --- a/src/plugins/home/server/tutorials/coredns_logs/index.ts +++ b/src/plugins/home/server/tutorials/coredns_logs/index.ts @@ -24,12 +24,12 @@ export function corednsLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'corednsLogs', name: i18n.translate('home.tutorials.corednsLogs.nameTitle', { - defaultMessage: 'CoreDNS logs', + defaultMessage: 'CoreDNS Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.corednsLogs.shortDescription', { - defaultMessage: 'Collect CoreDNS logs.', + defaultMessage: 'Collect and parse logs from CoreDNS servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.corednsLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/coredns_metrics/index.ts b/src/plugins/home/server/tutorials/coredns_metrics/index.ts index 34912efb31a81..3abc14314a6ba 100644 --- a/src/plugins/home/server/tutorials/coredns_metrics/index.ts +++ b/src/plugins/home/server/tutorials/coredns_metrics/index.ts @@ -23,16 +23,16 @@ export function corednsMetricsSpecProvider(context: TutorialContext): TutorialSc return { id: 'corednsMetrics', name: i18n.translate('home.tutorials.corednsMetrics.nameTitle', { - defaultMessage: 'CoreDNS metrics', + defaultMessage: 'CoreDNS Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.corednsMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the CoreDNS server.', + defaultMessage: 'Collect metrics from CoreDNS servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.corednsMetrics.longDescription', { defaultMessage: - 'The `coredns` Metricbeat module fetches monitoring metrics from CoreDNS. \ + 'The `coredns` Metricbeat module fetches metrics from CoreDNS. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-coredns.html', diff --git a/src/plugins/home/server/tutorials/couchbase_metrics/index.ts b/src/plugins/home/server/tutorials/couchbase_metrics/index.ts index 1860991fd17b2..5c29aa2d9a524 100644 --- a/src/plugins/home/server/tutorials/couchbase_metrics/index.ts +++ b/src/plugins/home/server/tutorials/couchbase_metrics/index.ts @@ -23,17 +23,17 @@ export function couchbaseMetricsSpecProvider(context: TutorialContext): Tutorial return { id: 'couchbaseMetrics', name: i18n.translate('home.tutorials.couchbaseMetrics.nameTitle', { - defaultMessage: 'Couchbase metrics', + defaultMessage: 'Couchbase Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.couchbaseMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Couchbase.', + defaultMessage: 'Collect metrics from Couchbase databases with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.couchbaseMetrics.longDescription', { defaultMessage: - 'The `couchbase` Metricbeat module fetches internal metrics from Couchbase. \ + 'The `couchbase` Metricbeat module fetches metrics from Couchbase. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-couchbase.html', diff --git a/src/plugins/home/server/tutorials/couchdb_metrics/index.ts b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts index a6c57f56cf2e1..00bea11d13d99 100644 --- a/src/plugins/home/server/tutorials/couchdb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/couchdb_metrics/index.ts @@ -23,16 +23,16 @@ export function couchdbMetricsSpecProvider(context: TutorialContext): TutorialSc return { id: 'couchdbMetrics', name: i18n.translate('home.tutorials.couchdbMetrics.nameTitle', { - defaultMessage: 'CouchDB metrics', + defaultMessage: 'CouchDB Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.couchdbMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the CouchdB server.', + defaultMessage: 'Collect metrics from CouchDB servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.couchdbMetrics.longDescription', { defaultMessage: - 'The `couchdb` Metricbeat module fetches monitoring metrics from CouchDB. \ + 'The `couchdb` Metricbeat module fetches metrics from CouchDB. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-couchdb.html', diff --git a/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts index baaaef50a641f..a48ed4288210b 100644 --- a/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts +++ b/src/plugins/home/server/tutorials/crowdstrike_logs/index.ts @@ -24,12 +24,13 @@ export function crowdstrikeLogsSpecProvider(context: TutorialContext): TutorialS return { id: 'crowdstrikeLogs', name: i18n.translate('home.tutorials.crowdstrikeLogs.nameTitle', { - defaultMessage: 'CrowdStrike logs', + defaultMessage: 'CrowdStrike Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.crowdstrikeLogs.shortDescription', { - defaultMessage: 'Collect CrowdStrike Falcon logs using the Falcon SIEM Connector.', + defaultMessage: + 'Collect and parse logs from CrowdStrike Falcon using the Falcon SIEM Connector with Filebeat.', }), longDescription: i18n.translate('home.tutorials.crowdstrikeLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/cylance_logs/index.ts b/src/plugins/home/server/tutorials/cylance_logs/index.ts index 9766f417b8870..64b79a41cd2e0 100644 --- a/src/plugins/home/server/tutorials/cylance_logs/index.ts +++ b/src/plugins/home/server/tutorials/cylance_logs/index.ts @@ -24,12 +24,12 @@ export function cylanceLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'cylanceLogs', name: i18n.translate('home.tutorials.cylanceLogs.nameTitle', { - defaultMessage: 'CylancePROTECT logs', + defaultMessage: 'CylancePROTECT Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.cylanceLogs.shortDescription', { - defaultMessage: 'Collect CylancePROTECT logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from CylancePROTECT with Filebeat.', }), longDescription: i18n.translate('home.tutorials.cylanceLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/docker_metrics/index.ts b/src/plugins/home/server/tutorials/docker_metrics/index.ts index 6a8687ef5d66e..ab80e6d644dbc 100644 --- a/src/plugins/home/server/tutorials/docker_metrics/index.ts +++ b/src/plugins/home/server/tutorials/docker_metrics/index.ts @@ -23,16 +23,16 @@ export function dockerMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: 'dockerMetrics', name: i18n.translate('home.tutorials.dockerMetrics.nameTitle', { - defaultMessage: 'Docker metrics', + defaultMessage: 'Docker Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.dockerMetrics.shortDescription', { - defaultMessage: 'Fetch metrics about your Docker containers.', + defaultMessage: 'Collect metrics from Docker containers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.dockerMetrics.longDescription', { defaultMessage: - 'The `docker` Metricbeat module fetches metrics from the Docker server. \ + 'The `docker` Metricbeat module fetches metrics from Docker server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-docker.html', diff --git a/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts b/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts index 86be26dd12ca7..9864d376966bb 100644 --- a/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts +++ b/src/plugins/home/server/tutorials/dropwizard_metrics/index.ts @@ -23,17 +23,17 @@ export function dropwizardMetricsSpecProvider(context: TutorialContext): Tutoria return { id: 'dropwizardMetrics', name: i18n.translate('home.tutorials.dropwizardMetrics.nameTitle', { - defaultMessage: 'Dropwizard metrics', + defaultMessage: 'Dropwizard Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.dropwizardMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Dropwizard Java application.', + defaultMessage: 'Collect metrics from Dropwizard Java applciations with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.dropwizardMetrics.longDescription', { defaultMessage: - 'The `dropwizard` Metricbeat module fetches internal metrics from Dropwizard Java Application. \ + 'The `dropwizard` Metricbeat module fetches metrics from Dropwizard Java Application. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-dropwizard.html', diff --git a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts index 1886a912fdcd2..6415781d02c06 100644 --- a/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts +++ b/src/plugins/home/server/tutorials/elasticsearch_logs/index.ts @@ -24,13 +24,13 @@ export function elasticsearchLogsSpecProvider(context: TutorialContext): Tutoria return { id: 'elasticsearchLogs', name: i18n.translate('home.tutorials.elasticsearchLogs.nameTitle', { - defaultMessage: 'Elasticsearch logs', + defaultMessage: 'Elasticsearch Logs', }), moduleName, category: TutorialsCategory.LOGGING, isBeta: true, shortDescription: i18n.translate('home.tutorials.elasticsearchLogs.shortDescription', { - defaultMessage: 'Collect and parse logs created by Elasticsearch.', + defaultMessage: 'Collect and parse logs from Elasticsearch clusters with Filebeat.', }), longDescription: i18n.translate('home.tutorials.elasticsearchLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts b/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts index 2adc2fd90fa70..3961d7f78c86c 100644 --- a/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts +++ b/src/plugins/home/server/tutorials/elasticsearch_metrics/index.ts @@ -23,17 +23,17 @@ export function elasticsearchMetricsSpecProvider(context: TutorialContext): Tuto return { id: 'elasticsearchMetrics', name: i18n.translate('home.tutorials.elasticsearchMetrics.nameTitle', { - defaultMessage: 'Elasticsearch metrics', + defaultMessage: 'Elasticsearch Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.elasticsearchMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Elasticsearch.', + defaultMessage: 'Collect metrics from Elasticsearch clusters with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.elasticsearchMetrics.longDescription', { defaultMessage: - 'The `elasticsearch` Metricbeat module fetches internal metrics from Elasticsearch. \ + 'The `elasticsearch` Metricbeat module fetches metrics from Elasticsearch. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-elasticsearch.html', diff --git a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts index fda69a2467b25..55c85a5bdd2a4 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_logs/index.ts @@ -24,12 +24,12 @@ export function envoyproxyLogsSpecProvider(context: TutorialContext): TutorialSc return { id: 'envoyproxyLogs', name: i18n.translate('home.tutorials.envoyproxyLogs.nameTitle', { - defaultMessage: 'Envoy Proxy logs', + defaultMessage: 'Envoy Proxy Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.envoyproxyLogs.shortDescription', { - defaultMessage: 'Collect Envoy Proxy logs.', + defaultMessage: 'Collect and parse logs from Envoy Proxy with Filebeat.', }), longDescription: i18n.translate('home.tutorials.envoyproxyLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts index 263d1a2036fd0..e2f3b84739685 100644 --- a/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts +++ b/src/plugins/home/server/tutorials/envoyproxy_metrics/index.ts @@ -23,16 +23,16 @@ export function envoyproxyMetricsSpecProvider(context: TutorialContext): Tutoria return { id: 'envoyproxyMetrics', name: i18n.translate('home.tutorials.envoyproxyMetrics.nameTitle', { - defaultMessage: 'Envoy Proxy metrics', + defaultMessage: 'Envoy Proxy Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.envoyproxyMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from Envoy Proxy.', + defaultMessage: 'Collect metrics from Envoy Proxy with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.envoyproxyMetrics.longDescription', { defaultMessage: - 'The `envoyproxy` Metricbeat module fetches monitoring metrics from Envoy Proxy. \ + 'The `envoyproxy` Metricbeat module fetches metrics from Envoy Proxy. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-envoyproxy.html', diff --git a/src/plugins/home/server/tutorials/etcd_metrics/index.ts b/src/plugins/home/server/tutorials/etcd_metrics/index.ts index cda16ecf68e34..9ed153c21c257 100644 --- a/src/plugins/home/server/tutorials/etcd_metrics/index.ts +++ b/src/plugins/home/server/tutorials/etcd_metrics/index.ts @@ -23,17 +23,17 @@ export function etcdMetricsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'etcdMetrics', name: i18n.translate('home.tutorials.etcdMetrics.nameTitle', { - defaultMessage: 'Etcd metrics', + defaultMessage: 'Etcd Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.etcdMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Etcd server.', + defaultMessage: 'Collect metrics from Etcd servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.etcdMetrics.longDescription', { defaultMessage: - 'The `etcd` Metricbeat module fetches internal metrics from Etcd. \ + 'The `etcd` Metricbeat module fetches metrics from Etcd. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-etcd.html', diff --git a/src/plugins/home/server/tutorials/f5_logs/index.ts b/src/plugins/home/server/tutorials/f5_logs/index.ts index ebcdd4ece7f45..a407d1d3d5142 100644 --- a/src/plugins/home/server/tutorials/f5_logs/index.ts +++ b/src/plugins/home/server/tutorials/f5_logs/index.ts @@ -24,12 +24,12 @@ export function f5LogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'f5Logs', name: i18n.translate('home.tutorials.f5Logs.nameTitle', { - defaultMessage: 'F5 logs', + defaultMessage: 'F5 Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.f5Logs.shortDescription', { - defaultMessage: 'Collect F5 Big-IP Access Policy Manager logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from F5 Big-IP Access Policy Manager with Filebeat.', }), longDescription: i18n.translate('home.tutorials.f5Logs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/fortinet_logs/index.ts b/src/plugins/home/server/tutorials/fortinet_logs/index.ts index 3e7923b680c6e..2f6af3ba47280 100644 --- a/src/plugins/home/server/tutorials/fortinet_logs/index.ts +++ b/src/plugins/home/server/tutorials/fortinet_logs/index.ts @@ -24,12 +24,12 @@ export function fortinetLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'fortinetLogs', name: i18n.translate('home.tutorials.fortinetLogs.nameTitle', { - defaultMessage: 'Fortinet logs', + defaultMessage: 'Fortinet Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.fortinetLogs.shortDescription', { - defaultMessage: 'Collect Fortinet FortiOS logs over syslog.', + defaultMessage: 'Collect and parse logs from Fortinet FortiOS with Filebeat.', }), longDescription: i18n.translate('home.tutorials.fortinetLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/gcp_logs/index.ts b/src/plugins/home/server/tutorials/gcp_logs/index.ts index feef7d673c5d9..23d8e3364eb69 100644 --- a/src/plugins/home/server/tutorials/gcp_logs/index.ts +++ b/src/plugins/home/server/tutorials/gcp_logs/index.ts @@ -24,12 +24,12 @@ export function gcpLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'gcpLogs', name: i18n.translate('home.tutorials.gcpLogs.nameTitle', { - defaultMessage: 'Google Cloud logs', + defaultMessage: 'Google Cloud Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.gcpLogs.shortDescription', { - defaultMessage: 'Collect Google Cloud audit, firewall, and VPC flow logs.', + defaultMessage: 'Collect and parse logs from Google Cloud Platform with Filebeat.', }), longDescription: i18n.translate('home.tutorials.gcpLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/gcp_metrics/index.ts b/src/plugins/home/server/tutorials/gcp_metrics/index.ts index 5f198ed5f3cf2..7f397c1e1be7b 100644 --- a/src/plugins/home/server/tutorials/gcp_metrics/index.ts +++ b/src/plugins/home/server/tutorials/gcp_metrics/index.ts @@ -23,17 +23,16 @@ export function gcpMetricsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'gcpMetrics', name: i18n.translate('home.tutorials.gcpMetrics.nameTitle', { - defaultMessage: 'Google Cloud metrics', + defaultMessage: 'Google Cloud Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.gcpMetrics.shortDescription', { - defaultMessage: - 'Fetch monitoring metrics from Google Cloud Platform using Stackdriver Monitoring API.', + defaultMessage: 'Collect metrics from Google Cloud Platform with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.gcpMetrics.longDescription', { defaultMessage: - 'The `gcp` Metricbeat module fetches monitoring metrics from Google Cloud Platform using Stackdriver Monitoring API. \ + 'The `gcp` Metricbeat module fetches metrics from Google Cloud Platform using Stackdriver Monitoring API. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-gcp.html', diff --git a/src/plugins/home/server/tutorials/golang_metrics/index.ts b/src/plugins/home/server/tutorials/golang_metrics/index.ts index 85937e0dda0e0..50d09e42e8791 100644 --- a/src/plugins/home/server/tutorials/golang_metrics/index.ts +++ b/src/plugins/home/server/tutorials/golang_metrics/index.ts @@ -23,17 +23,17 @@ export function golangMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: moduleName + 'Metrics', name: i18n.translate('home.tutorials.golangMetrics.nameTitle', { - defaultMessage: 'Golang metrics', + defaultMessage: 'Golang Metrics', }), moduleName, isBeta: true, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.golangMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from a Golang app.', + defaultMessage: 'Collect metrics from Golang applications with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.golangMetrics.longDescription', { defaultMessage: - 'The `{moduleName}` Metricbeat module fetches internal metrics from a Golang app. \ + 'The `{moduleName}` Metricbeat module fetches metrics from a Golang app. \ [Learn more]({learnMoreLink}).', values: { moduleName, diff --git a/src/plugins/home/server/tutorials/gsuite_logs/index.ts b/src/plugins/home/server/tutorials/gsuite_logs/index.ts index 4d23c6b1cfdce..718558321cf78 100644 --- a/src/plugins/home/server/tutorials/gsuite_logs/index.ts +++ b/src/plugins/home/server/tutorials/gsuite_logs/index.ts @@ -24,16 +24,16 @@ export function gsuiteLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'gsuiteLogs', name: i18n.translate('home.tutorials.gsuiteLogs.nameTitle', { - defaultMessage: 'GSuite logs', + defaultMessage: 'GSuite Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.gsuiteLogs.shortDescription', { - defaultMessage: 'Collect GSuite activity reports.', + defaultMessage: 'Collect and parse activity reports from GSuite with Filebeat.', }), longDescription: i18n.translate('home.tutorials.gsuiteLogs.longDescription', { defaultMessage: - 'This is a module for ingesting data from the different GSuite audit reports APIs. \ + 'This is a module for ingesting data from different GSuite audit reports APIs. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.filebeat}/filebeat-module-gsuite.html', diff --git a/src/plugins/home/server/tutorials/haproxy_logs/index.ts b/src/plugins/home/server/tutorials/haproxy_logs/index.ts index 0b0fd35f07058..c3765317ecbe0 100644 --- a/src/plugins/home/server/tutorials/haproxy_logs/index.ts +++ b/src/plugins/home/server/tutorials/haproxy_logs/index.ts @@ -24,12 +24,12 @@ export function haproxyLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'haproxyLogs', name: i18n.translate('home.tutorials.haproxyLogs.nameTitle', { - defaultMessage: 'HAProxy logs', + defaultMessage: 'HAProxy Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.haproxyLogs.shortDescription', { - defaultMessage: 'Collect HAProxy logs.', + defaultMessage: 'Collect and parse logs from HAProxy servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.haproxyLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/haproxy_metrics/index.ts b/src/plugins/home/server/tutorials/haproxy_metrics/index.ts index e37f0ffc4b916..49f1d32dc4c82 100644 --- a/src/plugins/home/server/tutorials/haproxy_metrics/index.ts +++ b/src/plugins/home/server/tutorials/haproxy_metrics/index.ts @@ -23,17 +23,17 @@ export function haproxyMetricsSpecProvider(context: TutorialContext): TutorialSc return { id: 'haproxyMetrics', name: i18n.translate('home.tutorials.haproxyMetrics.nameTitle', { - defaultMessage: 'HAProxy metrics', + defaultMessage: 'HAProxy Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.haproxyMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the HAProxy server.', + defaultMessage: 'Collect metrics from HAProxy servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.haproxyMetrics.longDescription', { defaultMessage: - 'The `haproxy` Metricbeat module fetches internal metrics from HAProxy. \ + 'The `haproxy` Metricbeat module fetches metrics from HAProxy. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-haproxy.html', diff --git a/src/plugins/home/server/tutorials/ibmmq_logs/index.ts b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts index 646747d1a49f8..21b60a9ab5a5c 100644 --- a/src/plugins/home/server/tutorials/ibmmq_logs/index.ts +++ b/src/plugins/home/server/tutorials/ibmmq_logs/index.ts @@ -24,12 +24,12 @@ export function ibmmqLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'ibmmqLogs', name: i18n.translate('home.tutorials.ibmmqLogs.nameTitle', { - defaultMessage: 'IBM MQ logs', + defaultMessage: 'IBM MQ Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.ibmmqLogs.shortDescription', { - defaultMessage: 'Collect IBM MQ logs with Filebeat.', + defaultMessage: 'Collect and parse logs from IBM MQ with Filebeat.', }), longDescription: i18n.translate('home.tutorials.ibmmqLogs.longDescription', { defaultMessage: 'Collect IBM MQ logs with Filebeat. \ diff --git a/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts index 3862bd9ca85eb..706003f0eab48 100644 --- a/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/ibmmq_metrics/index.ts @@ -23,16 +23,16 @@ export function ibmmqMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'ibmmqMetrics', name: i18n.translate('home.tutorials.ibmmqMetrics.nameTitle', { - defaultMessage: 'IBM MQ metrics', + defaultMessage: 'IBM MQ Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.ibmmqMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from IBM MQ instances.', + defaultMessage: 'Collect metrics from IBM MQ instances with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.ibmmqMetrics.longDescription', { defaultMessage: - 'The `ibmmq` Metricbeat module fetches monitoring metrics from IBM MQ instances \ + 'The `ibmmq` Metricbeat module fetches metrics from IBM MQ instances \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-ibmmq.html', diff --git a/src/plugins/home/server/tutorials/icinga_logs/index.ts b/src/plugins/home/server/tutorials/icinga_logs/index.ts index 0dae93b70343b..dc730022262c2 100644 --- a/src/plugins/home/server/tutorials/icinga_logs/index.ts +++ b/src/plugins/home/server/tutorials/icinga_logs/index.ts @@ -24,12 +24,12 @@ export function icingaLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'icingaLogs', name: i18n.translate('home.tutorials.icingaLogs.nameTitle', { - defaultMessage: 'Icinga logs', + defaultMessage: 'Icinga Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.icingaLogs.shortDescription', { - defaultMessage: 'Collect Icinga main, debug, and startup logs.', + defaultMessage: 'Collect and parse main, debug, and startup logs from Icinga with Filebeat.', }), longDescription: i18n.translate('home.tutorials.icingaLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/iis_logs/index.ts b/src/plugins/home/server/tutorials/iis_logs/index.ts index 5393edf6ab148..0dbc5bbdc75b8 100644 --- a/src/plugins/home/server/tutorials/iis_logs/index.ts +++ b/src/plugins/home/server/tutorials/iis_logs/index.ts @@ -24,12 +24,13 @@ export function iisLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'iisLogs', name: i18n.translate('home.tutorials.iisLogs.nameTitle', { - defaultMessage: 'IIS logs', + defaultMessage: 'IIS Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.iisLogs.shortDescription', { - defaultMessage: 'Collect and parse access and error logs created by the IIS HTTP server.', + defaultMessage: + 'Collect and parse access and error logs from IIS HTTP servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.iisLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/iis_metrics/index.ts b/src/plugins/home/server/tutorials/iis_metrics/index.ts index dbfa474dc9c89..d57e4688ba753 100644 --- a/src/plugins/home/server/tutorials/iis_metrics/index.ts +++ b/src/plugins/home/server/tutorials/iis_metrics/index.ts @@ -28,7 +28,7 @@ export function iisMetricsSpecProvider(context: TutorialContext): TutorialSchema moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.iisMetrics.shortDescription', { - defaultMessage: 'Collect IIS server related metrics.', + defaultMessage: 'Collect metrics from IIS HTTP servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.iisMetrics.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/imperva_logs/index.ts b/src/plugins/home/server/tutorials/imperva_logs/index.ts index 71c3af3809e2e..1cbe707f813ee 100644 --- a/src/plugins/home/server/tutorials/imperva_logs/index.ts +++ b/src/plugins/home/server/tutorials/imperva_logs/index.ts @@ -24,12 +24,12 @@ export function impervaLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'impervaLogs', name: i18n.translate('home.tutorials.impervaLogs.nameTitle', { - defaultMessage: 'Imperva logs', + defaultMessage: 'Imperva Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.impervaLogs.shortDescription', { - defaultMessage: 'Collect Imperva SecureSphere logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Imperva SecureSphere with Filebeat.', }), longDescription: i18n.translate('home.tutorials.impervaLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/infoblox_logs/index.ts b/src/plugins/home/server/tutorials/infoblox_logs/index.ts index 5329444dfa85f..8dce2bf00b2e2 100644 --- a/src/plugins/home/server/tutorials/infoblox_logs/index.ts +++ b/src/plugins/home/server/tutorials/infoblox_logs/index.ts @@ -24,12 +24,12 @@ export function infobloxLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'infobloxLogs', name: i18n.translate('home.tutorials.infobloxLogs.nameTitle', { - defaultMessage: 'Infoblox logs', + defaultMessage: 'Infoblox Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.infobloxLogs.shortDescription', { - defaultMessage: 'Collect Infoblox NIOS logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Infoblox NIOS with Filebeat.', }), longDescription: i18n.translate('home.tutorials.infobloxLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/iptables_logs/index.ts b/src/plugins/home/server/tutorials/iptables_logs/index.ts index 85faf169f8714..6d298e88a2dfb 100644 --- a/src/plugins/home/server/tutorials/iptables_logs/index.ts +++ b/src/plugins/home/server/tutorials/iptables_logs/index.ts @@ -24,12 +24,12 @@ export function iptablesLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'iptablesLogs', name: i18n.translate('home.tutorials.iptablesLogs.nameTitle', { - defaultMessage: 'Iptables logs', + defaultMessage: 'Iptables Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.iptablesLogs.shortDescription', { - defaultMessage: 'Collect iptables and ip6tables logs.', + defaultMessage: 'Collect and parse logs from iptables and ip6tables with Filebeat.', }), longDescription: i18n.translate('home.tutorials.iptablesLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/juniper_logs/index.ts b/src/plugins/home/server/tutorials/juniper_logs/index.ts index f9174d8a089e0..7430e4705a5f4 100644 --- a/src/plugins/home/server/tutorials/juniper_logs/index.ts +++ b/src/plugins/home/server/tutorials/juniper_logs/index.ts @@ -29,7 +29,7 @@ export function juniperLogsSpecProvider(context: TutorialContext): TutorialSchem moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.juniperLogs.shortDescription', { - defaultMessage: 'Collect Juniper JUNOS logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Juniper JUNOS with Filebeat.', }), longDescription: i18n.translate('home.tutorials.juniperLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/kafka_logs/index.ts b/src/plugins/home/server/tutorials/kafka_logs/index.ts index 5b877cadcbec6..9ccc06eb222c7 100644 --- a/src/plugins/home/server/tutorials/kafka_logs/index.ts +++ b/src/plugins/home/server/tutorials/kafka_logs/index.ts @@ -24,12 +24,12 @@ export function kafkaLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'kafkaLogs', name: i18n.translate('home.tutorials.kafkaLogs.nameTitle', { - defaultMessage: 'Kafka logs', + defaultMessage: 'Kafka Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.kafkaLogs.shortDescription', { - defaultMessage: 'Collect and parse logs created by Kafka.', + defaultMessage: 'Collect and parse logs from Kafka servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.kafkaLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/kafka_metrics/index.ts b/src/plugins/home/server/tutorials/kafka_metrics/index.ts index 92f6744b91cbe..973ec06b58fdf 100644 --- a/src/plugins/home/server/tutorials/kafka_metrics/index.ts +++ b/src/plugins/home/server/tutorials/kafka_metrics/index.ts @@ -23,17 +23,17 @@ export function kafkaMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'kafkaMetrics', name: i18n.translate('home.tutorials.kafkaMetrics.nameTitle', { - defaultMessage: 'Kafka metrics', + defaultMessage: 'Kafka Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.kafkaMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Kafka server.', + defaultMessage: 'Collect metrics from Kafka servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.kafkaMetrics.longDescription', { defaultMessage: - 'The `kafka` Metricbeat module fetches internal metrics from Kafka. \ + 'The `kafka` Metricbeat module fetches metrics from Kafka. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kafka.html', diff --git a/src/plugins/home/server/tutorials/kibana_logs/index.ts b/src/plugins/home/server/tutorials/kibana_logs/index.ts index 988af821ef9e3..9863a53700a55 100644 --- a/src/plugins/home/server/tutorials/kibana_logs/index.ts +++ b/src/plugins/home/server/tutorials/kibana_logs/index.ts @@ -29,7 +29,7 @@ export function kibanaLogsSpecProvider(context: TutorialContext): TutorialSchema moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.kibanaLogs.shortDescription', { - defaultMessage: 'Collect Kibana logs.', + defaultMessage: 'Collect and parse logs from Kibana with Filebeat.', }), longDescription: i18n.translate('home.tutorials.kibanaLogs.longDescription', { defaultMessage: 'This is the Kibana module. \ diff --git a/src/plugins/home/server/tutorials/kibana_metrics/index.ts b/src/plugins/home/server/tutorials/kibana_metrics/index.ts index dfe4efe4f7337..3d0eb691ede51 100644 --- a/src/plugins/home/server/tutorials/kibana_metrics/index.ts +++ b/src/plugins/home/server/tutorials/kibana_metrics/index.ts @@ -23,17 +23,17 @@ export function kibanaMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: 'kibanaMetrics', name: i18n.translate('home.tutorials.kibanaMetrics.nameTitle', { - defaultMessage: 'Kibana metrics', + defaultMessage: 'Kibana Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.kibanaMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Kibana.', + defaultMessage: 'Collect metrics from Kibana with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.kibanaMetrics.longDescription', { defaultMessage: - 'The `kibana` Metricbeat module fetches internal metrics from Kibana. \ + 'The `kibana` Metricbeat module fetches metrics from Kibana. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kibana.html', diff --git a/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts index 4a694560f5c28..9c66125ee0cfe 100644 --- a/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts +++ b/src/plugins/home/server/tutorials/kubernetes_metrics/index.ts @@ -23,16 +23,16 @@ export function kubernetesMetricsSpecProvider(context: TutorialContext): Tutoria return { id: 'kubernetesMetrics', name: i18n.translate('home.tutorials.kubernetesMetrics.nameTitle', { - defaultMessage: 'Kubernetes metrics', + defaultMessage: 'Kubernetes Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.kubernetesMetrics.shortDescription', { - defaultMessage: 'Fetch metrics from your Kubernetes installation.', + defaultMessage: 'Collect metrics from Kubernetes installations with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.kubernetesMetrics.longDescription', { defaultMessage: - 'The `kubernetes` Metricbeat module fetches metrics from the Kubernetes APIs. \ + 'The `kubernetes` Metricbeat module fetches metrics from Kubernetes APIs. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-kubernetes.html', diff --git a/src/plugins/home/server/tutorials/logstash_logs/index.ts b/src/plugins/home/server/tutorials/logstash_logs/index.ts index 55491d45df28c..688ad8245b78d 100644 --- a/src/plugins/home/server/tutorials/logstash_logs/index.ts +++ b/src/plugins/home/server/tutorials/logstash_logs/index.ts @@ -24,12 +24,12 @@ export function logstashLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'logstashLogs', name: i18n.translate('home.tutorials.logstashLogs.nameTitle', { - defaultMessage: 'Logstash logs', + defaultMessage: 'Logstash Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.logstashLogs.shortDescription', { - defaultMessage: 'Collect Logstash main and slow logs.', + defaultMessage: 'Collect and parse main and slow logs from Logstash with Filebeat.', }), longDescription: i18n.translate('home.tutorials.logstashLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/logstash_metrics/index.ts b/src/plugins/home/server/tutorials/logstash_metrics/index.ts index e7d3fae011bd2..9ae4bcdcecbf1 100644 --- a/src/plugins/home/server/tutorials/logstash_metrics/index.ts +++ b/src/plugins/home/server/tutorials/logstash_metrics/index.ts @@ -23,17 +23,17 @@ export function logstashMetricsSpecProvider(context: TutorialContext): TutorialS return { id: moduleName + 'Metrics', name: i18n.translate('home.tutorials.logstashMetrics.nameTitle', { - defaultMessage: 'Logstash metrics', + defaultMessage: 'Logstash Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.logstashMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from a Logstash server.', + defaultMessage: 'Collect metrics from Logstash servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.logstashMetrics.longDescription', { defaultMessage: - 'The `{moduleName}` Metricbeat module fetches internal metrics from a Logstash server. \ + 'The `{moduleName}` Metricbeat module fetches metrics from a Logstash server. \ [Learn more]({learnMoreLink}).', values: { moduleName, diff --git a/src/plugins/home/server/tutorials/memcached_metrics/index.ts b/src/plugins/home/server/tutorials/memcached_metrics/index.ts index 15df179b44a9e..891567f72ca7c 100644 --- a/src/plugins/home/server/tutorials/memcached_metrics/index.ts +++ b/src/plugins/home/server/tutorials/memcached_metrics/index.ts @@ -23,17 +23,17 @@ export function memcachedMetricsSpecProvider(context: TutorialContext): Tutorial return { id: 'memcachedMetrics', name: i18n.translate('home.tutorials.memcachedMetrics.nameTitle', { - defaultMessage: 'Memcached metrics', + defaultMessage: 'Memcached Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.memcachedMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Memcached server.', + defaultMessage: 'Collect metrics from Memcached servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.memcachedMetrics.longDescription', { defaultMessage: - 'The `memcached` Metricbeat module fetches internal metrics from Memcached. \ + 'The `memcached` Metricbeat module fetches metrics from Memcached. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-memcached.html', diff --git a/src/plugins/home/server/tutorials/microsoft_logs/index.ts b/src/plugins/home/server/tutorials/microsoft_logs/index.ts index 52401df1f9eb7..88893e22bc9ff 100644 --- a/src/plugins/home/server/tutorials/microsoft_logs/index.ts +++ b/src/plugins/home/server/tutorials/microsoft_logs/index.ts @@ -24,12 +24,12 @@ export function microsoftLogsSpecProvider(context: TutorialContext): TutorialSch return { id: 'microsoftLogs', name: i18n.translate('home.tutorials.microsoftLogs.nameTitle', { - defaultMessage: 'Microsoft Defender ATP logs', + defaultMessage: 'Microsoft Defender ATP Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.microsoftLogs.shortDescription', { - defaultMessage: 'Collect Microsoft Defender ATP alerts.', + defaultMessage: 'Collect and parse alerts from Microsoft Defender ATP with Filebeat.', }), longDescription: i18n.translate('home.tutorials.microsoftLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/misp_logs/index.ts b/src/plugins/home/server/tutorials/misp_logs/index.ts index b7611b543bab1..ea2147a296534 100644 --- a/src/plugins/home/server/tutorials/misp_logs/index.ts +++ b/src/plugins/home/server/tutorials/misp_logs/index.ts @@ -24,12 +24,12 @@ export function mispLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'mispLogs', name: i18n.translate('home.tutorials.mispLogs.nameTitle', { - defaultMessage: 'MISP threat intel logs', + defaultMessage: 'MISP threat intel Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.mispLogs.shortDescription', { - defaultMessage: 'Collect MISP threat intelligence data with Filebeat.', + defaultMessage: 'Collect and parse logs from MISP threat intelligence with Filebeat.', }), longDescription: i18n.translate('home.tutorials.mispLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/mongodb_logs/index.ts b/src/plugins/home/server/tutorials/mongodb_logs/index.ts index 3c189c04da43b..a7f9869d440ed 100644 --- a/src/plugins/home/server/tutorials/mongodb_logs/index.ts +++ b/src/plugins/home/server/tutorials/mongodb_logs/index.ts @@ -24,12 +24,12 @@ export function mongodbLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'mongodbLogs', name: i18n.translate('home.tutorials.mongodbLogs.nameTitle', { - defaultMessage: 'MongoDB logs', + defaultMessage: 'MongoDB Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.mongodbLogs.shortDescription', { - defaultMessage: 'Collect MongoDB logs.', + defaultMessage: 'Collect and parse logs from MongoDB servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.mongodbLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/mongodb_metrics/index.ts b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts index 121310fba6f3a..cc0ecc0574fa9 100644 --- a/src/plugins/home/server/tutorials/mongodb_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mongodb_metrics/index.ts @@ -23,16 +23,16 @@ export function mongodbMetricsSpecProvider(context: TutorialContext): TutorialSc return { id: 'mongodbMetrics', name: i18n.translate('home.tutorials.mongodbMetrics.nameTitle', { - defaultMessage: 'MongoDB metrics', + defaultMessage: 'MongoDB Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.mongodbMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from MongoDB.', + defaultMessage: 'Collect metrics from MongoDB servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.mongodbMetrics.longDescription', { defaultMessage: - 'The `mongodb` Metricbeat module fetches internal metrics from the MongoDB server. \ + 'The `mongodb` Metricbeat module fetches metrics from MongoDB server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mongodb.html', diff --git a/src/plugins/home/server/tutorials/mssql_logs/index.ts b/src/plugins/home/server/tutorials/mssql_logs/index.ts index 567080910b7fe..06cafd95283c8 100644 --- a/src/plugins/home/server/tutorials/mssql_logs/index.ts +++ b/src/plugins/home/server/tutorials/mssql_logs/index.ts @@ -24,12 +24,12 @@ export function mssqlLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'mssqlLogs', name: i18n.translate('home.tutorials.mssqlLogs.nameTitle', { - defaultMessage: 'MSSQL logs', + defaultMessage: 'Microsoft SQL Server Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.mssqlLogs.shortDescription', { - defaultMessage: 'Collect MSSQL logs.', + defaultMessage: 'Collect and parse logs from Microsoft SQL Server instances with Filebeat.', }), longDescription: i18n.translate('home.tutorials.mssqlLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/mssql_metrics/index.ts b/src/plugins/home/server/tutorials/mssql_metrics/index.ts index 998cefe2de004..e3c9e3c338209 100644 --- a/src/plugins/home/server/tutorials/mssql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mssql_metrics/index.ts @@ -28,7 +28,7 @@ export function mssqlMetricsSpecProvider(context: TutorialContext): TutorialSche moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.mssqlMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from a Microsoft SQL Server instance', + defaultMessage: 'Collect metrics from Microsoft SQL Server instances with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.mssqlMetrics.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/munin_metrics/index.ts b/src/plugins/home/server/tutorials/munin_metrics/index.ts index 1abd321e4c738..12621d05d0766 100644 --- a/src/plugins/home/server/tutorials/munin_metrics/index.ts +++ b/src/plugins/home/server/tutorials/munin_metrics/index.ts @@ -23,18 +23,18 @@ export function muninMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'muninMetrics', name: i18n.translate('home.tutorials.muninMetrics.nameTitle', { - defaultMessage: 'Munin metrics', + defaultMessage: 'Munin Metrics', }), moduleName, euiIconType: '/plugins/home/assets/logos/munin.svg', isBeta: true, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.muninMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Munin server.', + defaultMessage: 'Collect metrics from Munin servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.muninMetrics.longDescription', { defaultMessage: - 'The `munin` Metricbeat module fetches internal metrics from Munin. \ + 'The `munin` Metricbeat module fetches metrics from Munin. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-munin.html', diff --git a/src/plugins/home/server/tutorials/mysql_logs/index.ts b/src/plugins/home/server/tutorials/mysql_logs/index.ts index a788e736d2964..b0c6f0e69dcfb 100644 --- a/src/plugins/home/server/tutorials/mysql_logs/index.ts +++ b/src/plugins/home/server/tutorials/mysql_logs/index.ts @@ -24,12 +24,12 @@ export function mysqlLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'mysqlLogs', name: i18n.translate('home.tutorials.mysqlLogs.nameTitle', { - defaultMessage: 'MySQL logs', + defaultMessage: 'MySQL Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.mysqlLogs.shortDescription', { - defaultMessage: 'Collect and parse error and slow logs created by MySQL.', + defaultMessage: 'Collect and parse logs from MySQL servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.mysqlLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/mysql_metrics/index.ts b/src/plugins/home/server/tutorials/mysql_metrics/index.ts index 078a96f8110df..09c55dc81ff84 100644 --- a/src/plugins/home/server/tutorials/mysql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/mysql_metrics/index.ts @@ -23,16 +23,16 @@ export function mysqlMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'mysqlMetrics', name: i18n.translate('home.tutorials.mysqlMetrics.nameTitle', { - defaultMessage: 'MySQL metrics', + defaultMessage: 'MySQL Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.mysqlMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from MySQL.', + defaultMessage: 'Collect metrics from MySQL servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.mysqlMetrics.longDescription', { defaultMessage: - 'The `mysql` Metricbeat module fetches internal metrics from the MySQL server. \ + 'The `mysql` Metricbeat module fetches metrics from MySQL server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-mysql.html', diff --git a/src/plugins/home/server/tutorials/nats_logs/index.ts b/src/plugins/home/server/tutorials/nats_logs/index.ts index a1dc24080bc0d..b6ef0a192d92f 100644 --- a/src/plugins/home/server/tutorials/nats_logs/index.ts +++ b/src/plugins/home/server/tutorials/nats_logs/index.ts @@ -24,13 +24,13 @@ export function natsLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'natsLogs', name: i18n.translate('home.tutorials.natsLogs.nameTitle', { - defaultMessage: 'NATS logs', + defaultMessage: 'NATS Logs', }), moduleName, category: TutorialsCategory.LOGGING, isBeta: true, shortDescription: i18n.translate('home.tutorials.natsLogs.shortDescription', { - defaultMessage: 'Collect and parse logs created by Nats.', + defaultMessage: 'Collect and parse logs from NATS servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.natsLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/nats_metrics/index.ts b/src/plugins/home/server/tutorials/nats_metrics/index.ts index 11494e5dc57d0..54f034ad44b19 100644 --- a/src/plugins/home/server/tutorials/nats_metrics/index.ts +++ b/src/plugins/home/server/tutorials/nats_metrics/index.ts @@ -23,16 +23,16 @@ export function natsMetricsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'natsMetrics', name: i18n.translate('home.tutorials.natsMetrics.nameTitle', { - defaultMessage: 'NATS metrics', + defaultMessage: 'NATS Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.natsMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the Nats server.', + defaultMessage: 'Collect metrics from NATS servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.natsMetrics.longDescription', { defaultMessage: - 'The `nats` Metricbeat module fetches monitoring metrics from Nats. \ + 'The `nats` Metricbeat module fetches metrics from Nats. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-nats.html', diff --git a/src/plugins/home/server/tutorials/netflow_logs/index.ts b/src/plugins/home/server/tutorials/netflow_logs/index.ts index e8404e93ae355..c659d9c1d31b1 100644 --- a/src/plugins/home/server/tutorials/netflow_logs/index.ts +++ b/src/plugins/home/server/tutorials/netflow_logs/index.ts @@ -24,12 +24,12 @@ export function netflowLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'netflowLogs', name: i18n.translate('home.tutorials.netflowLogs.nameTitle', { - defaultMessage: 'NetFlow / IPFIX Collector', + defaultMessage: 'NetFlow / IPFIX Records', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.netflowLogs.shortDescription', { - defaultMessage: 'Collect NetFlow and IPFIX flow records.', + defaultMessage: 'Collect records from NetFlow and IPFIX flow with Filebeat.', }), longDescription: i18n.translate('home.tutorials.netflowLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/netscout_logs/index.ts b/src/plugins/home/server/tutorials/netscout_logs/index.ts index 395fbb8b49d39..e6c22947f8057 100644 --- a/src/plugins/home/server/tutorials/netscout_logs/index.ts +++ b/src/plugins/home/server/tutorials/netscout_logs/index.ts @@ -24,12 +24,12 @@ export function netscoutLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'netscoutLogs', name: i18n.translate('home.tutorials.netscoutLogs.nameTitle', { - defaultMessage: 'Arbor Peakflow logs', + defaultMessage: 'Arbor Peakflow Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.netscoutLogs.shortDescription', { - defaultMessage: 'Collect Netscout Arbor Peakflow SP logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Netscout Arbor Peakflow SP with Filebeat.', }), longDescription: i18n.translate('home.tutorials.netscoutLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/nginx_logs/index.ts b/src/plugins/home/server/tutorials/nginx_logs/index.ts index 90ec6737c2461..e6f2fc4efb01c 100644 --- a/src/plugins/home/server/tutorials/nginx_logs/index.ts +++ b/src/plugins/home/server/tutorials/nginx_logs/index.ts @@ -24,12 +24,12 @@ export function nginxLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'nginxLogs', name: i18n.translate('home.tutorials.nginxLogs.nameTitle', { - defaultMessage: 'Nginx logs', + defaultMessage: 'Nginx Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.nginxLogs.shortDescription', { - defaultMessage: 'Collect and parse access and error logs created by the Nginx HTTP server.', + defaultMessage: 'Collect and parse logs from Nginx HTTP servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.nginxLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/nginx_metrics/index.ts b/src/plugins/home/server/tutorials/nginx_metrics/index.ts index 12f67a26dcf29..680dd664912d3 100644 --- a/src/plugins/home/server/tutorials/nginx_metrics/index.ts +++ b/src/plugins/home/server/tutorials/nginx_metrics/index.ts @@ -23,16 +23,16 @@ export function nginxMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'nginxMetrics', name: i18n.translate('home.tutorials.nginxMetrics.nameTitle', { - defaultMessage: 'Nginx metrics', + defaultMessage: 'Nginx Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.nginxMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the Nginx HTTP server.', + defaultMessage: 'Collect metrics from Nginx HTTP servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.nginxMetrics.longDescription', { defaultMessage: - 'The `nginx` Metricbeat module fetches internal metrics from the Nginx HTTP server. \ + 'The `nginx` Metricbeat module fetches metrics from Nginx HTTP server. \ The module scrapes the server status data from the web page generated by the \ {statusModuleLink}, \ which must be enabled in your Nginx installation. \ diff --git a/src/plugins/home/server/tutorials/o365_logs/index.ts b/src/plugins/home/server/tutorials/o365_logs/index.ts index e3663e2c3cd78..3cd4d3a5c5e18 100644 --- a/src/plugins/home/server/tutorials/o365_logs/index.ts +++ b/src/plugins/home/server/tutorials/o365_logs/index.ts @@ -24,12 +24,12 @@ export function o365LogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'o365Logs', name: i18n.translate('home.tutorials.o365Logs.nameTitle', { - defaultMessage: 'Office 365 logs', + defaultMessage: 'Office 365 Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.o365Logs.shortDescription', { - defaultMessage: 'Collect Office 365 activity logs via the Office 365 API.', + defaultMessage: 'Collect and parse logs from Office 365 with Filebeat.', }), longDescription: i18n.translate('home.tutorials.o365Logs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/okta_logs/index.ts b/src/plugins/home/server/tutorials/okta_logs/index.ts index 62cde4b5128c3..aad18409de329 100644 --- a/src/plugins/home/server/tutorials/okta_logs/index.ts +++ b/src/plugins/home/server/tutorials/okta_logs/index.ts @@ -24,12 +24,12 @@ export function oktaLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'oktaLogs', name: i18n.translate('home.tutorials.oktaLogs.nameTitle', { - defaultMessage: 'Okta logs', + defaultMessage: 'Okta Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.oktaLogs.shortDescription', { - defaultMessage: 'Collect the Okta system log via the Okta API.', + defaultMessage: 'Collect and parse logs from the Okta API with Filebeat.', }), longDescription: i18n.translate('home.tutorials.oktaLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts b/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts index acbddf5169881..02625b341549b 100644 --- a/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts +++ b/src/plugins/home/server/tutorials/openmetrics_metrics/index.ts @@ -23,12 +23,13 @@ export function openmetricsMetricsSpecProvider(context: TutorialContext): Tutori return { id: 'openmetricsMetrics', name: i18n.translate('home.tutorials.openmetricsMetrics.nameTitle', { - defaultMessage: 'OpenMetrics metrics', + defaultMessage: 'OpenMetrics Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.openmetricsMetrics.shortDescription', { - defaultMessage: 'Fetch metrics from an endpoint that serves metrics in OpenMetrics format.', + defaultMessage: + 'Collect metrics from an endpoint that serves metrics in OpenMetrics format with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.openmetricsMetrics.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/oracle_metrics/index.ts b/src/plugins/home/server/tutorials/oracle_metrics/index.ts index 9b63e82c21ccd..14cf5392c5231 100644 --- a/src/plugins/home/server/tutorials/oracle_metrics/index.ts +++ b/src/plugins/home/server/tutorials/oracle_metrics/index.ts @@ -23,17 +23,17 @@ export function oracleMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: moduleName + 'Metrics', name: i18n.translate('home.tutorials.oracleMetrics.nameTitle', { - defaultMessage: 'oracle metrics', + defaultMessage: 'oracle Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.oracleMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from a Oracle server.', + defaultMessage: 'Collect metrics from Oracle servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.oracleMetrics.longDescription', { defaultMessage: - 'The `{moduleName}` Metricbeat module fetches internal metrics from a Oracle server. \ + 'The `{moduleName}` Metricbeat module fetches metrics from a Oracle server. \ [Learn more]({learnMoreLink}).', values: { moduleName, diff --git a/src/plugins/home/server/tutorials/osquery_logs/index.ts b/src/plugins/home/server/tutorials/osquery_logs/index.ts index 6bacbed57792c..4f87fc4e256e1 100644 --- a/src/plugins/home/server/tutorials/osquery_logs/index.ts +++ b/src/plugins/home/server/tutorials/osquery_logs/index.ts @@ -24,12 +24,12 @@ export function osqueryLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'osqueryLogs', name: i18n.translate('home.tutorials.osqueryLogs.nameTitle', { - defaultMessage: 'Osquery logs', + defaultMessage: 'Osquery Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.osqueryLogs.shortDescription', { - defaultMessage: 'Collect osquery logs in JSON format.', + defaultMessage: 'Collect and parse logs from Osquery with Filebeat.', }), longDescription: i18n.translate('home.tutorials.osqueryLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/panw_logs/index.ts b/src/plugins/home/server/tutorials/panw_logs/index.ts index 3ca839556d756..f5158c48f30d5 100644 --- a/src/plugins/home/server/tutorials/panw_logs/index.ts +++ b/src/plugins/home/server/tutorials/panw_logs/index.ts @@ -24,13 +24,13 @@ export function panwLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'panwLogs', name: i18n.translate('home.tutorials.panwLogs.nameTitle', { - defaultMessage: 'Palo Alto Networks PAN-OS logs', + defaultMessage: 'Palo Alto Networks PAN-OS Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.panwLogs.shortDescription', { defaultMessage: - 'Collect Palo Alto Networks PAN-OS threat and traffic logs over syslog or from a log file.', + 'Collect and parse threat and traffic logs from Palo Alto Networks PAN-OS with Filebeat.', }), longDescription: i18n.translate('home.tutorials.panwLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts b/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts index ed67960ab5a1c..40b35984fb17a 100644 --- a/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts +++ b/src/plugins/home/server/tutorials/php_fpm_metrics/index.ts @@ -23,17 +23,17 @@ export function phpfpmMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: 'phpfpmMetrics', name: i18n.translate('home.tutorials.phpFpmMetrics.nameTitle', { - defaultMessage: 'PHP-FPM metrics', + defaultMessage: 'PHP-FPM Metrics', }), moduleName, category: TutorialsCategory.METRICS, isBeta: false, shortDescription: i18n.translate('home.tutorials.phpFpmMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from PHP-FPM.', + defaultMessage: 'Collect metrics from PHP-FPM with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.phpFpmMetrics.longDescription', { defaultMessage: - 'The `php_fpm` Metricbeat module fetches internal metrics from the PHP-FPM server. \ + 'The `php_fpm` Metricbeat module fetches metrics from PHP-FPM server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-php_fpm.html', diff --git a/src/plugins/home/server/tutorials/postgresql_logs/index.ts b/src/plugins/home/server/tutorials/postgresql_logs/index.ts index c5f5d879ac35d..3a092e61b0bd9 100644 --- a/src/plugins/home/server/tutorials/postgresql_logs/index.ts +++ b/src/plugins/home/server/tutorials/postgresql_logs/index.ts @@ -24,12 +24,12 @@ export function postgresqlLogsSpecProvider(context: TutorialContext): TutorialSc return { id: 'postgresqlLogs', name: i18n.translate('home.tutorials.postgresqlLogs.nameTitle', { - defaultMessage: 'PostgreSQL logs', + defaultMessage: 'PostgreSQL Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.postgresqlLogs.shortDescription', { - defaultMessage: 'Collect and parse error and slow logs created by PostgreSQL.', + defaultMessage: 'Collect and parse logs from PostgreSQL servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.postgresqlLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/postgresql_metrics/index.ts b/src/plugins/home/server/tutorials/postgresql_metrics/index.ts index ca20efb44bca7..501ea252cd16f 100644 --- a/src/plugins/home/server/tutorials/postgresql_metrics/index.ts +++ b/src/plugins/home/server/tutorials/postgresql_metrics/index.ts @@ -23,17 +23,17 @@ export function postgresqlMetricsSpecProvider(context: TutorialContext): Tutoria return { id: 'postgresqlMetrics', name: i18n.translate('home.tutorials.postgresqlMetrics.nameTitle', { - defaultMessage: 'PostgreSQL metrics', + defaultMessage: 'PostgreSQL Metrics', }), moduleName, category: TutorialsCategory.METRICS, isBeta: false, shortDescription: i18n.translate('home.tutorials.postgresqlMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from PostgreSQL.', + defaultMessage: 'Collect metrics from PostgreSQL servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.postgresqlMetrics.longDescription', { defaultMessage: - 'The `postgresql` Metricbeat module fetches internal metrics from the PostgreSQL server. \ + 'The `postgresql` Metricbeat module fetches metrics from PostgreSQL server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-postgresql.html', diff --git a/src/plugins/home/server/tutorials/prometheus_metrics/index.ts b/src/plugins/home/server/tutorials/prometheus_metrics/index.ts index ee05770d65108..2f422e5e3be70 100644 --- a/src/plugins/home/server/tutorials/prometheus_metrics/index.ts +++ b/src/plugins/home/server/tutorials/prometheus_metrics/index.ts @@ -23,13 +23,13 @@ export function prometheusMetricsSpecProvider(context: TutorialContext): Tutoria return { id: moduleName + 'Metrics', name: i18n.translate('home.tutorials.prometheusMetrics.nameTitle', { - defaultMessage: 'Prometheus metrics', + defaultMessage: 'Prometheus Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.prometheusMetrics.shortDescription', { - defaultMessage: 'Fetch metrics from a Prometheus exporter.', + defaultMessage: 'Collect metrics from Prometheus exporters with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.prometheusMetrics.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts index 0fbdb48236832..8a1634e7da038 100644 --- a/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts +++ b/src/plugins/home/server/tutorials/rabbitmq_logs/index.ts @@ -24,12 +24,12 @@ export function rabbitmqLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'rabbitmqLogs', name: i18n.translate('home.tutorials.rabbitmqLogs.nameTitle', { - defaultMessage: 'RabbitMQ logs', + defaultMessage: 'RabbitMQ Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.rabbitmqLogs.shortDescription', { - defaultMessage: 'Collect RabbitMQ logs.', + defaultMessage: 'Collect and parse logs from RabbitMQ servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.rabbitmqLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts index b58f936f205b2..abfc895088d91 100644 --- a/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts +++ b/src/plugins/home/server/tutorials/rabbitmq_metrics/index.ts @@ -23,16 +23,16 @@ export function rabbitmqMetricsSpecProvider(context: TutorialContext): TutorialS return { id: 'rabbitmqMetrics', name: i18n.translate('home.tutorials.rabbitmqMetrics.nameTitle', { - defaultMessage: 'RabbitMQ metrics', + defaultMessage: 'RabbitMQ Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.rabbitmqMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the RabbitMQ server.', + defaultMessage: 'Collect metrics from RabbitMQ servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.rabbitmqMetrics.longDescription', { defaultMessage: - 'The `rabbitmq` Metricbeat module fetches internal metrics from the RabbitMQ server. \ + 'The `rabbitmq` Metricbeat module fetches metrics from RabbitMQ server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-rabbitmq.html', diff --git a/src/plugins/home/server/tutorials/radware_logs/index.ts b/src/plugins/home/server/tutorials/radware_logs/index.ts index 28392cf9c4362..3e918a0a4064c 100644 --- a/src/plugins/home/server/tutorials/radware_logs/index.ts +++ b/src/plugins/home/server/tutorials/radware_logs/index.ts @@ -24,12 +24,12 @@ export function radwareLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'radwareLogs', name: i18n.translate('home.tutorials.radwareLogs.nameTitle', { - defaultMessage: 'Radware DefensePro logs', + defaultMessage: 'Radware DefensePro Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.radwareLogs.shortDescription', { - defaultMessage: 'Collect Radware DefensePro logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Radware DefensePro with Filebeat.', }), longDescription: i18n.translate('home.tutorials.radwareLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/redis_logs/index.ts b/src/plugins/home/server/tutorials/redis_logs/index.ts index 0f3a5aa812f49..f6aada27dec48 100644 --- a/src/plugins/home/server/tutorials/redis_logs/index.ts +++ b/src/plugins/home/server/tutorials/redis_logs/index.ts @@ -24,12 +24,12 @@ export function redisLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'redisLogs', name: i18n.translate('home.tutorials.redisLogs.nameTitle', { - defaultMessage: 'Redis logs', + defaultMessage: 'Redis Logs', }), moduleName, category: TutorialsCategory.LOGGING, shortDescription: i18n.translate('home.tutorials.redisLogs.shortDescription', { - defaultMessage: 'Collect and parse error and slow logs created by Redis.', + defaultMessage: 'Collect and parse logs from Redis servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.redisLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/redis_metrics/index.ts b/src/plugins/home/server/tutorials/redis_metrics/index.ts index 1b4ee7290a6d0..2bb300c48ff65 100644 --- a/src/plugins/home/server/tutorials/redis_metrics/index.ts +++ b/src/plugins/home/server/tutorials/redis_metrics/index.ts @@ -23,16 +23,16 @@ export function redisMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'redisMetrics', name: i18n.translate('home.tutorials.redisMetrics.nameTitle', { - defaultMessage: 'Redis metrics', + defaultMessage: 'Redis Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.redisMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Redis.', + defaultMessage: 'Collect metrics from Redis servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.redisMetrics.longDescription', { defaultMessage: - 'The `redis` Metricbeat module fetches internal metrics from the Redis server. \ + 'The `redis` Metricbeat module fetches metrics from Redis server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-redis.html', diff --git a/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts b/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts index be8de9c3eab4d..62e1386f29dbb 100644 --- a/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts +++ b/src/plugins/home/server/tutorials/redisenterprise_metrics/index.ts @@ -23,16 +23,16 @@ export function redisenterpriseMetricsSpecProvider(context: TutorialContext): Tu return { id: 'redisenterpriseMetrics', name: i18n.translate('home.tutorials.redisenterpriseMetrics.nameTitle', { - defaultMessage: 'Redis Enterprise metrics', + defaultMessage: 'Redis Enterprise Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.redisenterpriseMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from Redis Enterprise Server.', + defaultMessage: 'Collect metrics from Redis Enterprise servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.redisenterpriseMetrics.longDescription', { defaultMessage: - 'The `redisenterprise` Metricbeat module fetches monitoring metrics from Redis Enterprise Server \ + 'The `redisenterprise` Metricbeat module fetches metrics from Redis Enterprise Server \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-redisenterprise.html', diff --git a/src/plugins/home/server/tutorials/santa_logs/index.ts b/src/plugins/home/server/tutorials/santa_logs/index.ts index 10d1506438b62..da9f2e940066e 100644 --- a/src/plugins/home/server/tutorials/santa_logs/index.ts +++ b/src/plugins/home/server/tutorials/santa_logs/index.ts @@ -24,12 +24,12 @@ export function santaLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'santaLogs', name: i18n.translate('home.tutorials.santaLogs.nameTitle', { - defaultMessage: 'Google Santa logs', + defaultMessage: 'Google Santa Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.santaLogs.shortDescription', { - defaultMessage: 'Collect Google Santa logs about process executions on MacOS.', + defaultMessage: 'Collect and parse logs from Google Santa systems with Filebeat.', }), longDescription: i18n.translate('home.tutorials.santaLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/sonicwall_logs/index.ts b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts index 1fa711327a07d..04bf7a3968320 100644 --- a/src/plugins/home/server/tutorials/sonicwall_logs/index.ts +++ b/src/plugins/home/server/tutorials/sonicwall_logs/index.ts @@ -24,12 +24,12 @@ export function sonicwallLogsSpecProvider(context: TutorialContext): TutorialSch return { id: 'sonicwallLogs', name: i18n.translate('home.tutorials.sonicwallLogs.nameTitle', { - defaultMessage: 'Sonicwall FW logs', + defaultMessage: 'Sonicwall FW Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.sonicwallLogs.shortDescription', { - defaultMessage: 'Collect Sonicwall-FW logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Sonicwall-FW with Filebeat.', }), longDescription: i18n.translate('home.tutorials.sonicwallLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/sophos_logs/index.ts b/src/plugins/home/server/tutorials/sophos_logs/index.ts index 35b27973a55ec..4fadcecb6e1bd 100644 --- a/src/plugins/home/server/tutorials/sophos_logs/index.ts +++ b/src/plugins/home/server/tutorials/sophos_logs/index.ts @@ -24,12 +24,12 @@ export function sophosLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'sophosLogs', name: i18n.translate('home.tutorials.sophosLogs.nameTitle', { - defaultMessage: 'Sophos logs', + defaultMessage: 'Sophos Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.sophosLogs.shortDescription', { - defaultMessage: 'Collect Sophos XG SFOS logs over syslog.', + defaultMessage: 'Collect and parse logs from Sophos XG SFOS with Filebeat.', }), longDescription: i18n.translate('home.tutorials.sophosLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/squid_logs/index.ts b/src/plugins/home/server/tutorials/squid_logs/index.ts index d8d0bb6c0829b..2d8f055d7fa6b 100644 --- a/src/plugins/home/server/tutorials/squid_logs/index.ts +++ b/src/plugins/home/server/tutorials/squid_logs/index.ts @@ -24,12 +24,12 @@ export function squidLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'squidLogs', name: i18n.translate('home.tutorials.squidLogs.nameTitle', { - defaultMessage: 'Squid logs', + defaultMessage: 'Squid Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.squidLogs.shortDescription', { - defaultMessage: 'Collect Squid logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Squid servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.squidLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/stan_metrics/index.ts b/src/plugins/home/server/tutorials/stan_metrics/index.ts index ceb6084b539e6..0b3c0352b663d 100644 --- a/src/plugins/home/server/tutorials/stan_metrics/index.ts +++ b/src/plugins/home/server/tutorials/stan_metrics/index.ts @@ -23,16 +23,16 @@ export function stanMetricsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'stanMetrics', name: i18n.translate('home.tutorials.stanMetrics.nameTitle', { - defaultMessage: 'STAN metrics', + defaultMessage: 'STAN Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.stanMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from the STAN server.', + defaultMessage: 'Collect metrics from STAN servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.stanMetrics.longDescription', { defaultMessage: - 'The `stan` Metricbeat module fetches monitoring metrics from STAN. \ + 'The `stan` Metricbeat module fetches metrics from STAN. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-stan.html', diff --git a/src/plugins/home/server/tutorials/statsd_metrics/index.ts b/src/plugins/home/server/tutorials/statsd_metrics/index.ts index 472c1406db386..1be010a01d5a6 100644 --- a/src/plugins/home/server/tutorials/statsd_metrics/index.ts +++ b/src/plugins/home/server/tutorials/statsd_metrics/index.ts @@ -20,16 +20,16 @@ export function statsdMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: 'statsdMetrics', name: i18n.translate('home.tutorials.statsdMetrics.nameTitle', { - defaultMessage: 'Statsd metrics', + defaultMessage: 'Statsd Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.statsdMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from statsd.', + defaultMessage: 'Collect metrics from Statsd servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.statsdMetrics.longDescription', { defaultMessage: - 'The `statsd` Metricbeat module fetches monitoring metrics from statsd. \ + 'The `statsd` Metricbeat module fetches metrics from statsd. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-statsd.html', diff --git a/src/plugins/home/server/tutorials/suricata_logs/index.ts b/src/plugins/home/server/tutorials/suricata_logs/index.ts index 3bb2b93b6301a..373522e333379 100644 --- a/src/plugins/home/server/tutorials/suricata_logs/index.ts +++ b/src/plugins/home/server/tutorials/suricata_logs/index.ts @@ -24,12 +24,12 @@ export function suricataLogsSpecProvider(context: TutorialContext): TutorialSche return { id: 'suricataLogs', name: i18n.translate('home.tutorials.suricataLogs.nameTitle', { - defaultMessage: 'Suricata logs', + defaultMessage: 'Suricata Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.suricataLogs.shortDescription', { - defaultMessage: 'Collect Suricata IDS/IPS/NSM logs.', + defaultMessage: 'Collect and parse logs from Suricata IDS/IPS/NSM with Filebeat.', }), longDescription: i18n.translate('home.tutorials.suricataLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/system_logs/index.ts b/src/plugins/home/server/tutorials/system_logs/index.ts index 6f403a6d0a71a..fcc5745f48252 100644 --- a/src/plugins/home/server/tutorials/system_logs/index.ts +++ b/src/plugins/home/server/tutorials/system_logs/index.ts @@ -24,7 +24,7 @@ export function systemLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'systemLogs', name: i18n.translate('home.tutorials.systemLogs.nameTitle', { - defaultMessage: 'System logs', + defaultMessage: 'System Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, diff --git a/src/plugins/home/server/tutorials/system_metrics/index.ts b/src/plugins/home/server/tutorials/system_metrics/index.ts index 08979a3d3b003..1348535d9bb72 100644 --- a/src/plugins/home/server/tutorials/system_metrics/index.ts +++ b/src/plugins/home/server/tutorials/system_metrics/index.ts @@ -23,16 +23,17 @@ export function systemMetricsSpecProvider(context: TutorialContext): TutorialSch return { id: 'systemMetrics', name: i18n.translate('home.tutorials.systemMetrics.nameTitle', { - defaultMessage: 'System metrics', + defaultMessage: 'System Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.systemMetrics.shortDescription', { - defaultMessage: 'Collect CPU, memory, network, and disk statistics from the host.', + defaultMessage: + 'Collect CPU, memory, network, and disk metrics from System hosts with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.systemMetrics.longDescription', { defaultMessage: - 'The `system` Metricbeat module collects CPU, memory, network, and disk statistics from the host. \ + 'The `system` Metricbeat module collects CPU, memory, network, and disk statistics from host. \ It collects system wide statistics and statistics per process and filesystem. \ [Learn more]({learnMoreLink}).', values: { diff --git a/src/plugins/home/server/tutorials/tomcat_logs/index.ts b/src/plugins/home/server/tutorials/tomcat_logs/index.ts index 5ce4096ad4628..3258d3eff5a16 100644 --- a/src/plugins/home/server/tutorials/tomcat_logs/index.ts +++ b/src/plugins/home/server/tutorials/tomcat_logs/index.ts @@ -24,12 +24,12 @@ export function tomcatLogsSpecProvider(context: TutorialContext): TutorialSchema return { id: 'tomcatLogs', name: i18n.translate('home.tutorials.tomcatLogs.nameTitle', { - defaultMessage: 'Tomcat logs', + defaultMessage: 'Tomcat Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.tomcatLogs.shortDescription', { - defaultMessage: 'Collect Apache Tomcat logs over syslog or from a file.', + defaultMessage: 'Collect and parse logs from Apache Tomcat servers with Filebeat.', }), longDescription: i18n.translate('home.tutorials.tomcatLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/traefik_logs/index.ts b/src/plugins/home/server/tutorials/traefik_logs/index.ts index 6bbc905bbd6aa..30b9db4022137 100644 --- a/src/plugins/home/server/tutorials/traefik_logs/index.ts +++ b/src/plugins/home/server/tutorials/traefik_logs/index.ts @@ -24,12 +24,12 @@ export function traefikLogsSpecProvider(context: TutorialContext): TutorialSchem return { id: 'traefikLogs', name: i18n.translate('home.tutorials.traefikLogs.nameTitle', { - defaultMessage: 'Traefik logs', + defaultMessage: 'Traefik Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.traefikLogs.shortDescription', { - defaultMessage: 'Collect Traefik access logs.', + defaultMessage: 'Collect and parse logs from Traefik with Filebeat.', }), longDescription: i18n.translate('home.tutorials.traefikLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/traefik_metrics/index.ts b/src/plugins/home/server/tutorials/traefik_metrics/index.ts index 35d54317c8ede..6f76be3056110 100644 --- a/src/plugins/home/server/tutorials/traefik_metrics/index.ts +++ b/src/plugins/home/server/tutorials/traefik_metrics/index.ts @@ -20,16 +20,16 @@ export function traefikMetricsSpecProvider(context: TutorialContext): TutorialSc return { id: 'traefikMetrics', name: i18n.translate('home.tutorials.traefikMetrics.nameTitle', { - defaultMessage: 'Traefik metrics', + defaultMessage: 'Traefik Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.traefikMetrics.shortDescription', { - defaultMessage: 'Fetch monitoring metrics from Traefik.', + defaultMessage: 'Collect metrics from Traefik with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.traefikMetrics.longDescription', { defaultMessage: - 'The `traefik` Metricbeat module fetches monitoring metrics from Traefik. \ + 'The `traefik` Metricbeat module fetches metrics from Traefik. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-traefik.html', diff --git a/src/plugins/home/server/tutorials/uptime_monitors/index.ts b/src/plugins/home/server/tutorials/uptime_monitors/index.ts index 6e949d5410115..118174d0e5717 100644 --- a/src/plugins/home/server/tutorials/uptime_monitors/index.ts +++ b/src/plugins/home/server/tutorials/uptime_monitors/index.ts @@ -28,7 +28,7 @@ export function uptimeMonitorsSpecProvider(context: TutorialContext): TutorialSc moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.uptimeMonitors.shortDescription', { - defaultMessage: 'Monitor services for their availability', + defaultMessage: 'Monitor availability of the services with Heartbeat.', }), longDescription: i18n.translate('home.tutorials.uptimeMonitors.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts index d9cfcc9f7fb75..b1dbeb89bdb26 100644 --- a/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts +++ b/src/plugins/home/server/tutorials/uwsgi_metrics/index.ts @@ -23,16 +23,16 @@ export function uwsgiMetricsSpecProvider(context: TutorialContext): TutorialSche return { id: 'uwsgiMetrics', name: i18n.translate('home.tutorials.uwsgiMetrics.nameTitle', { - defaultMessage: 'uWSGI metrics', + defaultMessage: 'uWSGI Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.uwsgiMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from the uWSGI server.', + defaultMessage: 'Collect metrics from uWSGI servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.uwsgiMetrics.longDescription', { defaultMessage: - 'The `uwsgi` Metricbeat module fetches internal metrics from the uWSGI server. \ + 'The `uwsgi` Metricbeat module fetches metrics from uWSGI server. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-uwsgi.html', diff --git a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts index bcbcec59c36e4..14a574872221a 100644 --- a/src/plugins/home/server/tutorials/vsphere_metrics/index.ts +++ b/src/plugins/home/server/tutorials/vsphere_metrics/index.ts @@ -23,16 +23,16 @@ export function vSphereMetricsSpecProvider(context: TutorialContext): TutorialSc return { id: 'vsphereMetrics', name: i18n.translate('home.tutorials.vsphereMetrics.nameTitle', { - defaultMessage: 'vSphere metrics', + defaultMessage: 'vSphere Metrics', }), moduleName, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.vsphereMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from vSphere.', + defaultMessage: 'Collect metrics from vSphere with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.vsphereMetrics.longDescription', { defaultMessage: - 'The `vsphere` Metricbeat module fetches internal metrics from a vSphere cluster. \ + 'The `vsphere` Metricbeat module fetches metrics from a vSphere cluster. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-vsphere.html', diff --git a/src/plugins/home/server/tutorials/windows_event_logs/index.ts b/src/plugins/home/server/tutorials/windows_event_logs/index.ts index 0df7fa906e085..008468487ea64 100644 --- a/src/plugins/home/server/tutorials/windows_event_logs/index.ts +++ b/src/plugins/home/server/tutorials/windows_event_logs/index.ts @@ -23,17 +23,17 @@ export function windowsEventLogsSpecProvider(context: TutorialContext): Tutorial return { id: 'windowsEventLogs', name: i18n.translate('home.tutorials.windowsEventLogs.nameTitle', { - defaultMessage: 'Windows Event Log', + defaultMessage: 'Windows Event Logs', }), moduleName, isBeta: false, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.windowsEventLogs.shortDescription', { - defaultMessage: 'Fetch logs from the Windows Event Log.', + defaultMessage: 'Collect and parse logs from Windows Event Logs with WinLogBeat.', }), longDescription: i18n.translate('home.tutorials.windowsEventLogs.longDescription', { defaultMessage: - 'Use Winlogbeat to collect the logs from the Windows Event Log. \ + 'Use Winlogbeat to collect the logs from Windows Event Logs. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.winlogbeat}/index.html', diff --git a/src/plugins/home/server/tutorials/windows_metrics/index.ts b/src/plugins/home/server/tutorials/windows_metrics/index.ts index 6c663fbb13d4d..31d9b3f8962ce 100644 --- a/src/plugins/home/server/tutorials/windows_metrics/index.ts +++ b/src/plugins/home/server/tutorials/windows_metrics/index.ts @@ -23,17 +23,17 @@ export function windowsMetricsSpecProvider(context: TutorialContext): TutorialSc return { id: 'windowsMetrics', name: i18n.translate('home.tutorials.windowsMetrics.nameTitle', { - defaultMessage: 'Windows metrics', + defaultMessage: 'Windows Metrics', }), moduleName, isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.windowsMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from Windows.', + defaultMessage: 'Collect metrics from Windows with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.windowsMetrics.longDescription', { defaultMessage: - 'The `windows` Metricbeat module fetches internal metrics from Windows. \ + 'The `windows` Metricbeat module fetches metrics from Windows. \ [Learn more]({learnMoreLink}).', values: { learnMoreLink: '{config.docs.beats.metricbeat}/metricbeat-module-windows.html', diff --git a/src/plugins/home/server/tutorials/zeek_logs/index.ts b/src/plugins/home/server/tutorials/zeek_logs/index.ts index 5434dcc8527ff..df86518978c52 100644 --- a/src/plugins/home/server/tutorials/zeek_logs/index.ts +++ b/src/plugins/home/server/tutorials/zeek_logs/index.ts @@ -24,12 +24,12 @@ export function zeekLogsSpecProvider(context: TutorialContext): TutorialSchema { return { id: 'zeekLogs', name: i18n.translate('home.tutorials.zeekLogs.nameTitle', { - defaultMessage: 'Zeek logs', + defaultMessage: 'Zeek Logs', }), moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.zeekLogs.shortDescription', { - defaultMessage: 'Collect Zeek network security monitoring logs.', + defaultMessage: 'Collect and parse logs from Zeek network security with Filebeat.', }), longDescription: i18n.translate('home.tutorials.zeekLogs.longDescription', { defaultMessage: diff --git a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts index 85ca03acacfd4..8f732969a07f3 100644 --- a/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts +++ b/src/plugins/home/server/tutorials/zookeeper_metrics/index.ts @@ -23,18 +23,18 @@ export function zookeeperMetricsSpecProvider(context: TutorialContext): Tutorial return { id: moduleName + 'Metrics', name: i18n.translate('home.tutorials.zookeeperMetrics.nameTitle', { - defaultMessage: 'Zookeeper metrics', + defaultMessage: 'Zookeeper Metrics', }), moduleName, euiIconType: '/plugins/home/assets/logos/zookeeper.svg', isBeta: false, category: TutorialsCategory.METRICS, shortDescription: i18n.translate('home.tutorials.zookeeperMetrics.shortDescription', { - defaultMessage: 'Fetch internal metrics from a Zookeeper server.', + defaultMessage: 'Collect metrics from Zookeeper servers with Metricbeat.', }), longDescription: i18n.translate('home.tutorials.zookeeperMetrics.longDescription', { defaultMessage: - 'The `{moduleName}` Metricbeat module fetches internal metrics from a Zookeeper server. \ + 'The `{moduleName}` Metricbeat module fetches metrics from a Zookeeper server. \ [Learn more]({learnMoreLink}).', values: { moduleName, diff --git a/src/plugins/home/server/tutorials/zscaler_logs/index.ts b/src/plugins/home/server/tutorials/zscaler_logs/index.ts index a2eb41a257a92..977bbb242c62a 100644 --- a/src/plugins/home/server/tutorials/zscaler_logs/index.ts +++ b/src/plugins/home/server/tutorials/zscaler_logs/index.ts @@ -29,7 +29,7 @@ export function zscalerLogsSpecProvider(context: TutorialContext): TutorialSchem moduleName, category: TutorialsCategory.SECURITY_SOLUTION, shortDescription: i18n.translate('home.tutorials.zscalerLogs.shortDescription', { - defaultMessage: 'This is a module for receiving Zscaler NSS logs over Syslog or a file.', + defaultMessage: 'Collect and parse logs from Zscaler NSS with Filebeat.', }), longDescription: i18n.translate('home.tutorials.zscalerLogs.longDescription', { defaultMessage: diff --git a/src/plugins/interactive_setup/server/kibana_config_writer.test.ts b/src/plugins/interactive_setup/server/kibana_config_writer.test.ts index 4b68451930a3d..0580a35d909ea 100644 --- a/src/plugins/interactive_setup/server/kibana_config_writer.test.ts +++ b/src/plugins/interactive_setup/server/kibana_config_writer.test.ts @@ -30,6 +30,7 @@ describe('KibanaConfigWriter', () => { kibanaConfigWriter = new KibanaConfigWriter( '/some/path/kibana.yml', + '/data', loggingSystemMock.createLogger() ); }); @@ -37,15 +38,15 @@ describe('KibanaConfigWriter', () => { afterEach(() => jest.resetAllMocks()); describe('#isConfigWritable()', () => { - it('returns `false` if config directory is not writable even if kibana yml is writable', async () => { + it('returns `false` if data directory is not writable even if kibana yml is writable', async () => { mockFsAccess.mockImplementation((path, modifier) => - path === '/some/path' && modifier === constants.W_OK ? Promise.reject() : Promise.resolve() + path === '/data' && modifier === constants.W_OK ? Promise.reject() : Promise.resolve() ); await expect(kibanaConfigWriter.isConfigWritable()).resolves.toBe(false); }); - it('returns `false` if kibana yml is NOT writable if even config directory is writable', async () => { + it('returns `false` if kibana yml is NOT writable if even data directory is writable', async () => { mockFsAccess.mockImplementation((path, modifier) => path === '/some/path/kibana.yml' && modifier === constants.W_OK ? Promise.reject() @@ -55,219 +56,208 @@ describe('KibanaConfigWriter', () => { await expect(kibanaConfigWriter.isConfigWritable()).resolves.toBe(false); }); - it('returns `true` if both kibana yml and config directory are writable', async () => { + it('returns `true` if both kibana yml and data directory are writable', async () => { mockFsAccess.mockResolvedValue(undefined); await expect(kibanaConfigWriter.isConfigWritable()).resolves.toBe(true); }); - it('returns `true` even if kibana yml does not exist when config directory is writable', async () => { + it('returns `true` even if kibana yml does not exist even if data directory is writable', async () => { mockFsAccess.mockImplementation((path) => path === '/some/path/kibana.yml' ? Promise.reject() : Promise.resolve() ); - await expect(kibanaConfigWriter.isConfigWritable()).resolves.toBe(true); + await expect(kibanaConfigWriter.isConfigWritable()).resolves.toBe(false); }); }); describe('#writeConfig()', () => { - describe('without existing config', () => { - beforeEach(() => { - mockReadFile.mockResolvedValue(''); - }); - - it('throws if cannot write CA file', async () => { - mockWriteFile.mockRejectedValue(new Error('Oh no!')); - - await expect( - kibanaConfigWriter.writeConfig({ - caCert: 'ca-content', - host: '', - serviceAccountToken: { name: '', value: '' }, - }) - ).rejects.toMatchInlineSnapshot(`[Error: Oh no!]`); - - expect(mockWriteFile).toHaveBeenCalledTimes(1); - expect(mockWriteFile).toHaveBeenCalledWith('/some/path/ca_1234.crt', 'ca-content'); - }); - - it('throws if cannot write config to yaml file', async () => { - mockWriteFile.mockResolvedValueOnce(undefined).mockRejectedValueOnce(new Error('Oh no!')); - - await expect( - kibanaConfigWriter.writeConfig({ - caCert: 'ca-content', - host: 'some-host', - serviceAccountToken: { name: 'some-token', value: 'some-value' }, - }) - ).rejects.toMatchInlineSnapshot(`[Error: Oh no!]`); - - expect(mockWriteFile).toHaveBeenCalledTimes(2); - expect(mockWriteFile).toHaveBeenCalledWith('/some/path/ca_1234.crt', 'ca-content'); - expect(mockWriteFile).toHaveBeenCalledWith( - '/some/path/kibana.yml', - ` - -# This section was automatically generated during setup. -elasticsearch.hosts: [some-host] -elasticsearch.serviceAccountToken: some-value -elasticsearch.ssl.certificateAuthorities: [/some/path/ca_1234.crt] - -` - ); - }); - - it('throws if cannot read existing config', async () => { - mockReadFile.mockRejectedValue(new Error('Oh no!')); - - await expect( - kibanaConfigWriter.writeConfig({ - caCert: 'ca-content', - host: 'some-host', - serviceAccountToken: { name: 'some-token', value: 'some-value' }, - }) - ).rejects.toMatchInlineSnapshot(`[Error: Oh no!]`); - - expect(mockWriteFile).not.toHaveBeenCalled(); - }); - - it('throws if cannot parse existing config', async () => { - mockReadFile.mockResolvedValue('foo: bar\nfoo: baz'); - - await expect( - kibanaConfigWriter.writeConfig({ - caCert: 'ca-content', - host: 'some-host', - serviceAccountToken: { name: 'some-token', value: 'some-value' }, - }) - ).rejects.toMatchInlineSnapshot(` - [YAMLException: duplicated mapping key at line 2, column 1: - foo: baz - ^] - `); - - expect(mockWriteFile).not.toHaveBeenCalled(); - }); - - it('can successfully write CA certificate and elasticsearch config with service token', async () => { - await expect( - kibanaConfigWriter.writeConfig({ - caCert: 'ca-content', - host: 'some-host', - serviceAccountToken: { name: 'some-token', value: 'some-value' }, - }) - ).resolves.toBeUndefined(); + beforeEach(() => { + mockReadFile.mockResolvedValue( + '# Default Kibana configuration for docker target\nserver.host: "0.0.0.0"\nserver.shutdownTimeout: "5s"' + ); + }); - expect(mockWriteFile).toHaveBeenCalledTimes(2); - expect(mockWriteFile).toHaveBeenCalledWith('/some/path/ca_1234.crt', 'ca-content'); - expect(mockWriteFile).toHaveBeenCalledWith( - '/some/path/kibana.yml', - ` + it('throws if cannot write CA file', async () => { + mockWriteFile.mockRejectedValue(new Error('Oh no!')); -# This section was automatically generated during setup. -elasticsearch.hosts: [some-host] -elasticsearch.serviceAccountToken: some-value -elasticsearch.ssl.certificateAuthorities: [/some/path/ca_1234.crt] + await expect( + kibanaConfigWriter.writeConfig({ + caCert: 'ca-content', + host: '', + serviceAccountToken: { name: '', value: '' }, + }) + ).rejects.toMatchInlineSnapshot(`[Error: Oh no!]`); -` - ); - }); + expect(mockWriteFile).toHaveBeenCalledTimes(1); + expect(mockWriteFile).toHaveBeenCalledWith('/data/ca_1234.crt', 'ca-content'); + }); - it('can successfully write CA certificate and elasticsearch config with credentials', async () => { - await expect( - kibanaConfigWriter.writeConfig({ - caCert: 'ca-content', - host: 'some-host', - username: 'username', - password: 'password', - }) - ).resolves.toBeUndefined(); + it('throws if cannot write config to yaml file', async () => { + mockWriteFile.mockResolvedValueOnce(undefined).mockRejectedValueOnce(new Error('Oh no!')); - expect(mockWriteFile).toHaveBeenCalledTimes(2); - expect(mockWriteFile).toHaveBeenCalledWith('/some/path/ca_1234.crt', 'ca-content'); - expect(mockWriteFile).toHaveBeenCalledWith( - '/some/path/kibana.yml', - ` - -# This section was automatically generated during setup. -elasticsearch.hosts: [some-host] -elasticsearch.password: password -elasticsearch.username: username -elasticsearch.ssl.certificateAuthorities: [/some/path/ca_1234.crt] - -` - ); - }); + await expect( + kibanaConfigWriter.writeConfig({ + caCert: 'ca-content', + host: 'some-host', + serviceAccountToken: { name: 'some-token', value: 'some-value' }, + }) + ).rejects.toMatchInlineSnapshot(`[Error: Oh no!]`); - it('can successfully write elasticsearch config without CA certificate', async () => { - await expect( - kibanaConfigWriter.writeConfig({ - host: 'some-host', - username: 'username', - password: 'password', - }) - ).resolves.toBeUndefined(); + expect(mockWriteFile.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "/data/ca_1234.crt", + "ca-content", + ], + Array [ + "/some/path/kibana.yml", + "# Default Kibana configuration for docker target + server.host: \\"0.0.0.0\\" + server.shutdownTimeout: \\"5s\\" + + # This section was automatically generated during setup. + elasticsearch.hosts: [some-host] + elasticsearch.serviceAccountToken: some-value + elasticsearch.ssl.certificateAuthorities: [/data/ca_1234.crt] + + ", + ], + ] + `); + }); - expect(mockWriteFile).toHaveBeenCalledTimes(1); - expect(mockWriteFile).toHaveBeenCalledWith( - '/some/path/kibana.yml', - ` + it('throws if cannot read existing config', async () => { + mockReadFile.mockRejectedValue(new Error('Oh no!')); -# This section was automatically generated during setup. -elasticsearch.hosts: [some-host] -elasticsearch.password: password -elasticsearch.username: username + await expect( + kibanaConfigWriter.writeConfig({ + caCert: 'ca-content', + host: 'some-host', + serviceAccountToken: { name: 'some-token', value: 'some-value' }, + }) + ).rejects.toMatchInlineSnapshot(`[Error: Oh no!]`); -` - ); - }); + expect(mockWriteFile).not.toHaveBeenCalled(); }); - describe('with existing config (no conflicts)', () => { - beforeEach(() => { - mockReadFile.mockResolvedValue( - '# Default Kibana configuration for docker target\nserver.host: "0.0.0.0"\nserver.shutdownTimeout: "5s"' - ); - }); - - it('can successfully write CA certificate and elasticsearch config', async () => { - await expect( - kibanaConfigWriter.writeConfig({ - caCert: 'ca-content', - host: 'some-host', - serviceAccountToken: { name: 'some-token', value: 'some-value' }, - }) - ).resolves.toBeUndefined(); - - expect(mockReadFile).toHaveBeenCalledTimes(1); - expect(mockReadFile).toHaveBeenCalledWith('/some/path/kibana.yml', 'utf-8'); + it('throws if cannot parse existing config', async () => { + mockReadFile.mockResolvedValue('foo: bar\nfoo: baz'); + + await expect( + kibanaConfigWriter.writeConfig({ + caCert: 'ca-content', + host: 'some-host', + serviceAccountToken: { name: 'some-token', value: 'some-value' }, + }) + ).rejects.toMatchInlineSnapshot(` + [YAMLException: duplicated mapping key at line 2, column 1: + foo: baz + ^] + `); + + expect(mockWriteFile).not.toHaveBeenCalled(); + }); - expect(mockWriteFile).toHaveBeenCalledTimes(2); - expect(mockWriteFile.mock.calls).toMatchInlineSnapshot(` + it('can successfully write CA certificate and elasticsearch config with credentials', async () => { + await expect( + kibanaConfigWriter.writeConfig({ + caCert: 'ca-content', + host: 'some-host', + username: 'username', + password: 'password', + }) + ).resolves.toBeUndefined(); + + expect(mockWriteFile.mock.calls).toMatchInlineSnapshot(` + Array [ Array [ - Array [ - "/some/path/ca_1234.crt", - "ca-content", - ], - Array [ - "/some/path/kibana.yml", - "# Default Kibana configuration for docker target - server.host: \\"0.0.0.0\\" - server.shutdownTimeout: \\"5s\\" + "/data/ca_1234.crt", + "ca-content", + ], + Array [ + "/some/path/kibana.yml", + "# Default Kibana configuration for docker target + server.host: \\"0.0.0.0\\" + server.shutdownTimeout: \\"5s\\" + + # This section was automatically generated during setup. + elasticsearch.hosts: [some-host] + elasticsearch.password: password + elasticsearch.username: username + elasticsearch.ssl.certificateAuthorities: [/data/ca_1234.crt] + + ", + ], + ] + `); + }); - # This section was automatically generated during setup. - elasticsearch.hosts: [some-host] - elasticsearch.serviceAccountToken: some-value - elasticsearch.ssl.certificateAuthorities: [/some/path/ca_1234.crt] + it('can successfully write elasticsearch config without CA certificate', async () => { + await expect( + kibanaConfigWriter.writeConfig({ + host: 'some-host', + username: 'username', + password: 'password', + }) + ).resolves.toBeUndefined(); + + expect(mockWriteFile.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "/some/path/kibana.yml", + "# Default Kibana configuration for docker target + server.host: \\"0.0.0.0\\" + server.shutdownTimeout: \\"5s\\" + + # This section was automatically generated during setup. + elasticsearch.hosts: [some-host] + elasticsearch.password: password + elasticsearch.username: username + + ", + ], + ] + `); + }); - ", - ], - ] - `); - }); + it('can successfully write CA certificate and elasticsearch config with service token', async () => { + await expect( + kibanaConfigWriter.writeConfig({ + caCert: 'ca-content', + host: 'some-host', + serviceAccountToken: { name: 'some-token', value: 'some-value' }, + }) + ).resolves.toBeUndefined(); + + expect(mockReadFile).toHaveBeenCalledTimes(1); + expect(mockReadFile).toHaveBeenCalledWith('/some/path/kibana.yml', 'utf-8'); + + expect(mockWriteFile).toHaveBeenCalledTimes(2); + expect(mockWriteFile.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "/data/ca_1234.crt", + "ca-content", + ], + Array [ + "/some/path/kibana.yml", + "# Default Kibana configuration for docker target + server.host: \\"0.0.0.0\\" + server.shutdownTimeout: \\"5s\\" + + # This section was automatically generated during setup. + elasticsearch.hosts: [some-host] + elasticsearch.serviceAccountToken: some-value + elasticsearch.ssl.certificateAuthorities: [/data/ca_1234.crt] + + ", + ], + ] + `); }); - describe('with existing config (with conflicts)', () => { + describe('with conflicts', () => { beforeEach(() => { jest.spyOn(Date.prototype, 'toISOString').mockReturnValue('some date'); mockReadFile.mockResolvedValue( @@ -291,7 +281,7 @@ elasticsearch.username: username expect(mockWriteFile.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "/some/path/ca_1234.crt", + "/data/ca_1234.crt", "ca-content", ], Array [ @@ -312,7 +302,7 @@ elasticsearch.username: username elasticsearch.hosts: [some-host] monitoring.ui.container.elasticsearch.enabled: true elasticsearch.serviceAccountToken: some-value - elasticsearch.ssl.certificateAuthorities: [/some/path/ca_1234.crt] + elasticsearch.ssl.certificateAuthorities: [/data/ca_1234.crt] ", ], diff --git a/src/plugins/interactive_setup/server/kibana_config_writer.ts b/src/plugins/interactive_setup/server/kibana_config_writer.ts index ff67e887fab49..ea7f776aad82f 100644 --- a/src/plugins/interactive_setup/server/kibana_config_writer.ts +++ b/src/plugins/interactive_setup/server/kibana_config_writer.ts @@ -31,24 +31,23 @@ export type WriteConfigParameters = { ); export class KibanaConfigWriter { - constructor(private readonly configPath: string, private readonly logger: Logger) {} + constructor( + private readonly configPath: string, + private readonly dataDirectoryPath: string, + private readonly logger: Logger + ) {} /** - * Checks if we can write to the Kibana configuration file and configuration directory. + * Checks if we can write to the Kibana configuration file and data directory. */ public async isConfigWritable() { try { // We perform two separate checks here: - // 1. If we can write to config directory to add a new CA certificate file and potentially Kibana configuration - // file if it doesn't exist for some reason. + // 1. If we can write to data directory to add a new CA certificate file. // 2. If we can write to the Kibana configuration file if it exists. - const canWriteToConfigDirectory = fs.access(path.dirname(this.configPath), constants.W_OK); await Promise.all([ - canWriteToConfigDirectory, - fs.access(this.configPath, constants.F_OK).then( - () => fs.access(this.configPath, constants.W_OK), - () => canWriteToConfigDirectory - ), + fs.access(this.dataDirectoryPath, constants.W_OK), + fs.access(this.configPath, constants.W_OK), ]); return true; } catch { @@ -61,7 +60,7 @@ export class KibanaConfigWriter { * @param params */ public async writeConfig(params: WriteConfigParameters) { - const caPath = path.join(path.dirname(this.configPath), `ca_${Date.now()}.crt`); + const caPath = path.join(this.dataDirectoryPath, `ca_${Date.now()}.crt`); const config: Record = { 'elasticsearch.hosts': [params.host] }; if ('serviceAccountToken' in params) { config['elasticsearch.serviceAccountToken'] = params.serviceAccountToken.value; diff --git a/src/plugins/interactive_setup/server/plugin.ts b/src/plugins/interactive_setup/server/plugin.ts index 8c1d00a254764..067b8fd044f30 100644 --- a/src/plugins/interactive_setup/server/plugin.ts +++ b/src/plugins/interactive_setup/server/plugin.ts @@ -10,6 +10,7 @@ import chalk from 'chalk'; import type { Subscription } from 'rxjs'; import type { TypeOf } from '@kbn/config-schema'; +import { getDataPath } from '@kbn/utils'; import type { CorePreboot, Logger, PluginInitializerContext, PrebootPlugin } from 'src/core/server'; import { ElasticsearchConnectionStatus } from '../common'; @@ -146,7 +147,11 @@ Go to ${chalk.cyanBright.underline(url)} to get started. basePath: core.http.basePath, logger: this.#logger.get('routes'), preboot: { ...core.preboot, completeSetup }, - kibanaConfigWriter: new KibanaConfigWriter(configPath, this.#logger.get('kibana-config')), + kibanaConfigWriter: new KibanaConfigWriter( + configPath, + getDataPath(), + this.#logger.get('kibana-config') + ), elasticsearch, verificationCode, getConfig: this.#getConfig.bind(this), diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index a8a391995b005..bf936b2ae8dbe 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -448,6 +448,10 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'discover:showFieldStatistics': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, 'discover:showMultiFields': { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index 7ea80ffb77dda..7575fa5d2b3f3 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -31,6 +31,7 @@ export interface UsageStats { 'doc_table:legacy': boolean; 'discover:modifyColumnsOnSwitch': boolean; 'discover:searchFieldsFromSource': boolean; + 'discover:showFieldStatistics': boolean; 'discover:showMultiFields': boolean; 'discover:maxDocFieldsDisplayed': number; 'securitySolution:rulesTableRefresh': string; diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts index fc9f9a6e8c2d3..d61b8ca2c7779 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.test.ts @@ -6,11 +6,7 @@ * Side Public License, v 1. */ -import { - loggingSystemMock, - pluginInitializerContextConfigMock, - elasticsearchServiceMock, -} from '../../../../../core/server/mocks'; +import { loggingSystemMock, elasticsearchServiceMock } from '../../../../../core/server/mocks'; import { Collector, createCollectorFetchContextMock, @@ -29,7 +25,7 @@ describe('kibana_usage', () => { return createUsageCollectionSetupMock().makeUsageCollector(config); }); - const legacyConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; + const kibanaIndex = '.kibana-tests'; const getMockFetchClients = (hits?: unknown[]) => { const fetchParamsMock = createCollectorFetchContextMock(); @@ -40,7 +36,7 @@ describe('kibana_usage', () => { return fetchParamsMock; }; - beforeAll(() => registerKibanaUsageCollector(usageCollectionMock, legacyConfig$)); + beforeAll(() => registerKibanaUsageCollector(usageCollectionMock, kibanaIndex)); afterAll(() => jest.clearAllTimers()); test('registered collector is set', () => { diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts index 75d5af2737772..9bd8da2be54df 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/kibana_usage_collector.ts @@ -6,10 +6,8 @@ * Side Public License, v 1. */ -import type { Observable } from 'rxjs'; -import type { ElasticsearchClient, SharedGlobalConfig } from 'src/core/server'; +import type { ElasticsearchClient } from 'src/core/server'; import type { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; -import { take } from 'rxjs/operators'; import { snakeCase } from 'lodash'; import { getSavedObjectsCounts } from './get_saved_object_counts'; @@ -46,7 +44,7 @@ export async function getKibanaSavedObjectCounts( export function registerKibanaUsageCollector( usageCollection: UsageCollectionSetup, - legacyConfig$: Observable + kibanaIndex: string ) { usageCollection.registerCollector( usageCollection.makeUsageCollector({ @@ -83,12 +81,9 @@ export function registerKibanaUsageCollector( }, }, async fetch({ esClient }) { - const { - kibana: { index }, - } = await legacyConfig$.pipe(take(1)).toPromise(); return { - index, - ...(await getKibanaSavedObjectCounts(esClient, index)), + index: kibanaIndex, + ...(await getKibanaSavedObjectCounts(esClient, kibanaIndex)), }; }, }) diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts index 0ef5bffd40ff7..1f507dcc44666 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.test.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { pluginInitializerContextConfigMock } from '../../../../../core/server/mocks'; import { createCollectorFetchContextMock, createUsageCollectionSetupMock, @@ -16,9 +15,9 @@ import { registerSavedObjectsCountUsageCollector } from './saved_objects_count_c describe('saved_objects_count_collector', () => { const usageCollectionMock = createUsageCollectionSetupMock(); - const legacyConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; + const kibanaIndex = '.kibana-tests'; - beforeAll(() => registerSavedObjectsCountUsageCollector(usageCollectionMock, legacyConfig$)); + beforeAll(() => registerSavedObjectsCountUsageCollector(usageCollectionMock, kibanaIndex)); afterAll(() => jest.clearAllTimers()); test('registered collector is set', () => { diff --git a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts index 71bf2da7dc270..f541b1ef452e6 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/saved_objects_counts/saved_objects_count_collector.ts @@ -6,9 +6,6 @@ * Side Public License, v 1. */ -import type { Observable } from 'rxjs'; -import { take } from 'rxjs/operators'; -import type { SharedGlobalConfig } from 'src/core/server'; import type { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { getSavedObjectsCounts } from './get_saved_object_counts'; @@ -23,7 +20,7 @@ interface SavedObjectsCountUsage { export function registerSavedObjectsCountUsageCollector( usageCollection: UsageCollectionSetup, - legacyConfig$: Observable + kibanaIndex: string ) { usageCollection.registerCollector( usageCollection.makeUsageCollector({ @@ -45,10 +42,7 @@ export function registerSavedObjectsCountUsageCollector( }, }, async fetch({ esClient }) { - const { - kibana: { index }, - } = await legacyConfig$.pipe(take(1)).toPromise(); - const buckets = await getSavedObjectsCounts(esClient, index); + const buckets = await getSavedObjectsCounts(esClient, kibanaIndex); return { by_type: buckets.map(({ key: type, doc_count: count }) => { return { type, count }; diff --git a/src/plugins/kibana_usage_collection/server/plugin.ts b/src/plugins/kibana_usage_collection/server/plugin.ts index 07a70dfd56fb4..96d37c0303482 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.ts @@ -7,14 +7,13 @@ */ import type { UsageCollectionSetup, UsageCounter } from 'src/plugins/usage_collection/server'; -import { Subject, Observable } from 'rxjs'; +import { Subject } from 'rxjs'; import type { PluginInitializerContext, CoreSetup, Plugin, ISavedObjectsRepository, IUiSettingsClient, - SharedGlobalConfig, CoreStart, SavedObjectsServiceSetup, OpsMetrics, @@ -55,7 +54,6 @@ type SavedObjectsRegisterType = SavedObjectsServiceSetup['registerType']; export class KibanaUsageCollectionPlugin implements Plugin { private readonly logger: Logger; - private readonly legacyConfig$: Observable; private readonly instanceUuid: string; private savedObjectsClient?: ISavedObjectsRepository; private uiSettingsClient?: IUiSettingsClient; @@ -66,7 +64,6 @@ export class KibanaUsageCollectionPlugin implements Plugin { constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); - this.legacyConfig$ = initializerContext.config.legacy.globalConfig$; this.metric$ = new Subject(); this.pluginStop$ = new Subject(); this.instanceUuid = initializerContext.env.instanceUuid; @@ -121,6 +118,7 @@ export class KibanaUsageCollectionPlugin implements Plugin { pluginStop$: Subject, registerType: SavedObjectsRegisterType ) { + const kibanaIndex = coreSetup.savedObjects.getKibanaIndex(); const getSavedObjectsClient = () => this.savedObjectsClient; const getUiSettingsClient = () => this.uiSettingsClient; const getCoreUsageDataService = () => this.coreUsageData!; @@ -133,8 +131,8 @@ export class KibanaUsageCollectionPlugin implements Plugin { registerUsageCountersUsageCollector(usageCollection); registerOpsStatsCollector(usageCollection, metric$); - registerKibanaUsageCollector(usageCollection, this.legacyConfig$); - registerSavedObjectsCountUsageCollector(usageCollection, this.legacyConfig$); + registerKibanaUsageCollector(usageCollection, kibanaIndex); + registerSavedObjectsCountUsageCollector(usageCollection, kibanaIndex); registerManagementUsageCollector(usageCollection, getUiSettingsClient); registerUiMetricUsageCollector(usageCollection, registerType, getSavedObjectsClient); registerApplicationUsageCollector( diff --git a/src/plugins/presentation_util/kibana.json b/src/plugins/presentation_util/kibana.json index d7fe9b558e606..71ac224d1976a 100644 --- a/src/plugins/presentation_util/kibana.json +++ b/src/plugins/presentation_util/kibana.json @@ -10,6 +10,6 @@ "server": true, "ui": true, "extraPublicDirs": ["common/lib"], - "requiredPlugins": ["savedObjects"], + "requiredPlugins": ["savedObjects", "kibanaReact"], "optionalPlugins": [] } diff --git a/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.stories.tsx b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.stories.tsx new file mode 100644 index 0000000000000..1a29d0536a290 --- /dev/null +++ b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.stories.tsx @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState } from 'react'; + +import { DataView, DataViewField, IIndexPatternFieldList } from '../../../../data_views/common'; + +import { StorybookParams } from '../../services/storybook'; +import { DataViewPicker } from './data_view_picker'; + +// TODO: we probably should remove this once the PR is merged that has better data views for stories +const flightFieldNames: string[] = [ + 'AvgTicketPrice', + 'Cancelled', + 'Carrier', + 'dayOfWeek', + 'Dest', + 'DestAirportID', + 'DestCityName', + 'DestCountry', + 'DestLocation', + 'DestRegion', + 'DestWeather', + 'DistanceKilometers', + 'DistanceMiles', + 'FlightDelay', + 'FlightDelayMin', + 'FlightDelayType', + 'FlightNum', + 'FlightTimeHour', + 'FlightTimeMin', + 'Origin', + 'OriginAirportID', + 'OriginCityName', + 'OriginCountry', + 'OriginLocation', + 'OriginRegion', + 'OriginWeather', + 'timestamp', +]; +const flightFieldByName: { [key: string]: DataViewField } = {}; +flightFieldNames.forEach( + (flightFieldName) => + (flightFieldByName[flightFieldName] = { + name: flightFieldName, + type: 'string', + } as unknown as DataViewField) +); + +// Change some types manually for now +flightFieldByName.Cancelled = { name: 'Cancelled', type: 'boolean' } as DataViewField; +flightFieldByName.timestamp = { name: 'timestamp', type: 'date' } as DataViewField; + +const flightFields: DataViewField[] = Object.values(flightFieldByName); +const storybookFlightsDataView: DataView = { + id: 'demoDataFlights', + title: 'demo data flights', + fields: flightFields as unknown as IIndexPatternFieldList, + getFieldByName: (name: string) => flightFieldByName[name], +} as unknown as DataView; + +export default { + component: DataViewPicker, + title: 'Data View Picker', + argTypes: {}, +}; + +export function Example({}: {} & StorybookParams) { + const dataViews = [storybookFlightsDataView]; + + const [dataView, setDataView] = useState(undefined); + + const onChange = (newId: string) => { + const newIndexPattern = dataViews.find((ip) => ip.id === newId); + + setDataView(newIndexPattern); + }; + + const triggerLabel = dataView?.title || 'Choose Data View'; + + return ( + + ); +} diff --git a/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.tsx b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.tsx new file mode 100644 index 0000000000000..38ec4f16f9432 --- /dev/null +++ b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.tsx @@ -0,0 +1,114 @@ +/* + * Copyright 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 React, { useState } from 'react'; +import { EuiPopover, EuiPopoverTitle, EuiSelectable, EuiSelectableProps } from '@elastic/eui'; +import { DataView } from '../../../../data_views/common'; + +import { ToolbarButton, ToolbarButtonProps } from '../../../../kibana_react/public'; + +export type DataViewTriggerProps = ToolbarButtonProps & { + label: string; + title?: string; +}; + +export function DataViewPicker({ + dataViews, + selectedDataViewId, + onChangeIndexPattern, + trigger, + selectableProps, +}: { + dataViews: DataView[]; + selectedDataViewId?: string; + trigger: DataViewTriggerProps; + onChangeIndexPattern: (newId: string) => void; + selectableProps?: EuiSelectableProps; +}) { + const [isPopoverOpen, setPopoverIsOpen] = useState(false); + + const isMissingCurrent = !dataViews.some(({ id }) => id === selectedDataViewId); + + // be careful to only add color with a value, otherwise it will fallbacks to "primary" + const colorProp = isMissingCurrent + ? { + color: 'danger' as const, + } + : {}; + + const createTrigger = function () { + const { label, title, ...rest } = trigger; + return ( + setPopoverIsOpen(!isPopoverOpen)} + fullWidth + {...colorProp} + {...rest} + > + {label} + + ); + }; + + return ( + <> + setPopoverIsOpen(false)} + display="block" + panelPaddingSize="s" + ownFocus + > +
+ + {i18n.translate('presentationUtil.dataViewPicker.changeDataViewTitle', { + defaultMessage: 'Data view', + })} + + + {...selectableProps} + searchable + singleSelection="always" + options={dataViews.map(({ title, id }) => ({ + key: id, + label: title, + value: id, + checked: id === selectedDataViewId ? 'on' : undefined, + }))} + onChange={(choices) => { + const choice = choices.find(({ checked }) => checked) as unknown as { + value: string; + }; + onChangeIndexPattern(choice.value); + setPopoverIsOpen(false); + }} + searchProps={{ + compressed: true, + ...(selectableProps ? selectableProps.searchProps : undefined), + }} + > + {(list, search) => ( + <> + {search} + {list} + + )} + +
+
+ + ); +} diff --git a/src/plugins/presentation_util/public/components/field_picker/field_picker.scss b/src/plugins/presentation_util/public/components/field_picker/field_picker.scss new file mode 100644 index 0000000000000..c07cf99ed03d6 --- /dev/null +++ b/src/plugins/presentation_util/public/components/field_picker/field_picker.scss @@ -0,0 +1,15 @@ +.presFieldPicker__fieldButton { + box-shadow: 0 .8px .8px rgba(0,0,0,.04),0 2.3px 2px rgba(0,0,0,.03); + background: #FFF; + border: 1px dashed transparent; +} + +.presFieldPicker__fieldPanel { + height: 300px; + overflow-y: scroll; +} + +.presFieldPicker__container--disabled { + opacity: .7; + pointer-events: none; +} \ No newline at end of file diff --git a/src/plugins/presentation_util/public/components/field_picker/field_picker.stories.tsx b/src/plugins/presentation_util/public/components/field_picker/field_picker.stories.tsx new file mode 100644 index 0000000000000..c5654254ea70a --- /dev/null +++ b/src/plugins/presentation_util/public/components/field_picker/field_picker.stories.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; + +import { FieldPicker } from './field_picker'; + +import { DataView, DataViewField, IIndexPatternFieldList } from '../../../../data_views/common'; + +// TODO: we probably should remove this once the PR is merged that has better data views for stories +const flightFieldNames: string[] = [ + 'AvgTicketPrice', + 'Cancelled', + 'Carrier', + 'dayOfWeek', + 'Dest', + 'DestAirportID', + 'DestCityName', + 'DestCountry', + 'DestLocation', + 'DestRegion', + 'DestWeather', + 'DistanceKilometers', + 'DistanceMiles', + 'FlightDelay', + 'FlightDelayMin', + 'FlightDelayType', + 'FlightNum', + 'FlightTimeHour', + 'FlightTimeMin', + 'Origin', + 'OriginAirportID', + 'OriginCityName', + 'OriginCountry', + 'OriginLocation', + 'OriginRegion', + 'OriginWeather', + 'timestamp', +]; +const flightFieldByName: { [key: string]: DataViewField } = {}; +flightFieldNames.forEach( + (flightFieldName) => + (flightFieldByName[flightFieldName] = { + name: flightFieldName, + type: 'string', + } as unknown as DataViewField) +); + +// Change some types manually for now +flightFieldByName.Cancelled = { name: 'Cancelled', type: 'boolean' } as DataViewField; +flightFieldByName.timestamp = { name: 'timestamp', type: 'date' } as DataViewField; + +const flightFields: DataViewField[] = Object.values(flightFieldByName); +const storybookFlightsDataView: DataView = { + id: 'demoDataFlights', + title: 'demo data flights', + fields: flightFields as unknown as IIndexPatternFieldList, + getFieldByName: (name: string) => flightFieldByName[name], +} as unknown as DataView; + +export default { + component: FieldPicker, + title: 'Field Picker', +}; + +export const FieldPickerWithDataView = () => { + return ; +}; + +export const FieldPickerWithFilter = () => { + return ( + { + // Only show fields with "Dest" in the title + return f.name.includes('Dest'); + }} + /> + ); +}; + +export const FieldPickerWithoutIndexPattern = () => { + return ; +}; diff --git a/src/plugins/presentation_util/public/components/field_picker/field_picker.tsx b/src/plugins/presentation_util/public/components/field_picker/field_picker.tsx new file mode 100644 index 0000000000000..bbdf389ccee14 --- /dev/null +++ b/src/plugins/presentation_util/public/components/field_picker/field_picker.tsx @@ -0,0 +1,152 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState } from 'react'; +import { sortBy, uniq } from 'lodash'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiTitle, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { DataView, DataViewField } from '../../../../data_views/common'; +import { FieldIcon, FieldButton } from '../../../../kibana_react/public'; + +import { FieldSearch } from './field_search'; + +import './field_picker.scss'; + +export interface Props { + dataView: DataView | null; + filterPredicate?: (f: DataViewField) => boolean; +} + +export const FieldPicker = ({ dataView, filterPredicate }: Props) => { + const [nameFilter, setNameFilter] = useState(''); + const [typesFilter, setTypesFilter] = useState([]); + const [selectedField, setSelectedField] = useState(null); + + // Retrieve, filter, and sort fields from data view + const fields = dataView + ? sortBy( + dataView.fields + .filter( + (f) => + f.name.includes(nameFilter) && + (typesFilter.length === 0 || typesFilter.includes(f.type as string)) + ) + .filter((f) => (filterPredicate ? filterPredicate(f) : true)), + ['name'] + ) + : []; + + const uniqueTypes = dataView ? uniq(dataView.fields.map((f) => f.type as string)) : []; + + return ( + + + setNameFilter(val)} + searchValue={nameFilter} + onFieldTypesChange={(types) => setTypesFilter(types)} + fieldTypesValue={typesFilter} + availableFieldTypes={uniqueTypes} + /> + + + + {fields.length > 0 && ( + + {fields.map((f, i) => { + return ( + + setSelectedField(f)} + isActive={f.name === selectedField?.name} + fieldName={f.name} + fieldIcon={} + /> + + ); + })} + + )} + {!dataView && ( + + + + + + + + )} + {dataView && fields.length === 0 && ( + + + + + + + + )} + + + {selectedField && ( + + +

+ +

+
+
+ + } + /> +
+
+ )} +
+ ); +}; diff --git a/src/plugins/presentation_util/public/components/field_picker/field_search.tsx b/src/plugins/presentation_util/public/components/field_picker/field_search.tsx new file mode 100644 index 0000000000000..d3c6c728b3d08 --- /dev/null +++ b/src/plugins/presentation_util/public/components/field_picker/field_search.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiFieldSearch, + EuiFilterGroup, + EuiFlexGroup, + EuiFlexItem, + EuiPopover, + EuiContextMenuPanel, + EuiContextMenuItem, + EuiOutsideClickDetector, + EuiFilterButton, + EuiSpacer, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { FieldIcon } from '../../../../kibana_react/public'; + +export interface Props { + onSearchChange: (value: string) => void; + searchValue?: string; + + onFieldTypesChange: (value: string[]) => void; + fieldTypesValue: string[]; + + availableFieldTypes: string[]; +} + +export function FieldSearch({ + onSearchChange, + searchValue, + onFieldTypesChange, + fieldTypesValue, + availableFieldTypes, +}: Props) { + const searchPlaceholder = i18n.translate('presentationUtil.fieldSearch.searchPlaceHolder', { + defaultMessage: 'Search field names', + }); + + const [isPopoverOpen, setPopoverOpen] = useState(false); + + const handleFilterButtonClicked = () => { + setPopoverOpen(!isPopoverOpen); + }; + + const buttonContent = ( + 0} + numFilters={0} + hasActiveFilters={fieldTypesValue.length > 0} + numActiveFilters={fieldTypesValue.length} + onClick={handleFilterButtonClicked} + > + + + ); + + return ( + + + + onSearchChange(event.currentTarget.value)} + placeholder={searchPlaceholder} + value={searchValue} + /> + + + + {}} isDisabled={!isPopoverOpen}> + + { + setPopoverOpen(false); + }} + button={buttonContent} + > + ( + { + if (fieldTypesValue.includes(type)) { + onFieldTypesChange(fieldTypesValue.filter((f) => f !== type)); + } else { + onFieldTypesChange([...fieldTypesValue, type]); + } + }} + > + + + {type} + + + ))} + /> + + + + + ); +} diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index c6724056f77a5..f9ca99a26ec19 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -7689,6 +7689,12 @@ "description": "Non-default value of setting." } }, + "discover:showFieldStatistics": { + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } + }, "discover:showMultiFields": { "type": "boolean", "_meta": { diff --git a/src/plugins/telemetry/server/fetcher.ts b/src/plugins/telemetry/server/fetcher.ts index 02ac428b07667..97180f351986e 100644 --- a/src/plugins/telemetry/server/fetcher.ts +++ b/src/plugins/telemetry/server/fetcher.ts @@ -230,6 +230,7 @@ export class FetcherTask { method: 'post', body: stats, headers: { + 'Content-Type': 'application/json', 'X-Elastic-Stack-Version': this.currentKibanaVersion, 'X-Elastic-Cluster-ID': clusterUuid, 'X-Elastic-Content-Encoding': PAYLOAD_CONTENT_ENCODING, diff --git a/src/plugins/usage_collection/server/plugin.ts b/src/plugins/usage_collection/server/plugin.ts index 1c537ccfbb22b..12b2db43016e4 100644 --- a/src/plugins/usage_collection/server/plugin.ts +++ b/src/plugins/usage_collection/server/plugin.ts @@ -113,6 +113,7 @@ export class UsageCollectionPlugin implements Plugin { public setup(core: CoreSetup): UsageCollectionSetup { const config = this.initializerContext.config.get(); + const kibanaIndex = core.savedObjects.getKibanaIndex(); const collectorSet = new CollectorSet({ logger: this.logger.get('usage-collection', 'collector-set'), @@ -128,7 +129,6 @@ export class UsageCollectionPlugin implements Plugin { const { createUsageCounter, getUsageCounterByType } = this.usageCountersService.setup(core); const uiCountersUsageCounter = createUsageCounter('uiCounter'); - const globalConfig = this.initializerContext.config.legacy.get(); const router = core.http.createRouter(); setupRoutes({ router, @@ -137,7 +137,7 @@ export class UsageCollectionPlugin implements Plugin { collectorSet, config: { allowAnonymous: core.status.isStatusPageAnonymous(), - kibanaIndex: globalConfig.kibana.index, + kibanaIndex, kibanaVersion: this.initializerContext.env.packageInfo.version, server: core.http.getServerInfo(), uuid: this.initializerContext.env.instanceUuid, diff --git a/src/plugins/vis_default_editor/kibana.json b/src/plugins/vis_default_editor/kibana.json index efed1eab1e494..253edc74f87b4 100644 --- a/src/plugins/vis_default_editor/kibana.json +++ b/src/plugins/vis_default_editor/kibana.json @@ -3,7 +3,7 @@ "version": "kibana", "ui": true, "optionalPlugins": ["visualize"], - "requiredBundles": ["kibanaUtils", "kibanaReact", "data", "fieldFormats", "discover"], + "requiredBundles": ["kibanaUtils", "kibanaReact", "data", "fieldFormats", "discover", "esUiShared"], "owner": { "name": "Vis Editors", "githubTeam": "kibana-vis-editors" diff --git a/src/plugins/vis_default_editor/public/components/__snapshots__/agg.test.tsx.snap b/src/plugins/vis_default_editor/public/components/__snapshots__/agg.test.tsx.snap index bc6d28bd5c1c4..b25444d16c46a 100644 --- a/src/plugins/vis_default_editor/public/components/__snapshots__/agg.test.tsx.snap +++ b/src/plugins/vis_default_editor/public/components/__snapshots__/agg.test.tsx.snap @@ -12,8 +12,10 @@ exports[`DefaultEditorAgg component should init with the default set of props 1` } buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate" + buttonElement="button" className="visEditorSidebar__section visEditorSidebar__collapsible visEditorSidebar__collapsible--marginBottom" data-test-subj="visEditorAggAccordion1" + element="div" extraAction={
)} - + + +
+ } + > + + ); diff --git a/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx b/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx index 34cc1dc347ef8..ad069a4d7e2cc 100644 --- a/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx +++ b/src/plugins/vis_types/timeseries/public/timeseries_vis_renderer.tsx @@ -13,6 +13,7 @@ import { render, unmountComponentAtNode } from 'react-dom'; import { I18nProvider } from '@kbn/i18n/react'; import { IUiSettingsClient } from 'kibana/public'; +import { EuiLoadingChart } from '@elastic/eui'; import { fetchIndexPattern } from '../common/index_patterns_utils'; import { VisualizationContainer, PersistedState } from '../../../visualizations/public'; @@ -43,10 +44,6 @@ export const getTimeseriesVisRenderer: (deps: { name: 'timeseries_vis', reuseDomNode: true, render: async (domNode, config, handlers) => { - // Build optimization. Move app styles from main bundle - // @ts-expect-error TS error, cannot find type declaration for scss - await import('./application/index.scss'); - handlers.onDestroy(() => { unmountComponentAtNode(domNode); }); @@ -55,33 +52,49 @@ export const getTimeseriesVisRenderer: (deps: { const { indexPatterns } = getDataStart(); const showNoResult = !checkIfDataExists(visData, model); - const [palettesService, { indexPattern }] = await Promise.all([ + + let servicesLoaded; + + Promise.all([ palettes.getPalettes(), fetchIndexPattern(model.index_pattern, indexPatterns), - ]); + ]).then(([palettesService, { indexPattern }]) => { + servicesLoaded = true; - render( - - - + - - , - domNode - ); + showNoResult={showNoResult} + error={get(visData, [model.id, 'error'])} + > + + + , + domNode + ); + }); + + if (!servicesLoaded) { + render( +
+ +
, + domNode + ); + } }, }); diff --git a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_interval_and_timefield.ts b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_interval_and_timefield.ts index b7a22abd825e0..7c17f003dfbab 100644 --- a/src/plugins/vis_types/timeseries/server/lib/vis_data/get_interval_and_timefield.ts +++ b/src/plugins/vis_types/timeseries/server/lib/vis_data/get_interval_and_timefield.ts @@ -24,10 +24,15 @@ export function getIntervalAndTimefield( { min, max, maxBuckets }: IntervalParams, series?: Series ) { - const timeField = + let timeField = (series?.override_index_pattern ? series.series_time_field : panel.time_field) || index.indexPattern?.timeFieldName; + // should use @timestamp as default timeField for es indeces if user doesn't provide timeField + if (!panel.use_kibana_indexes && !timeField) { + timeField = '@timestamp'; + } + if (panel.use_kibana_indexes) { validateField(timeField!, index); } diff --git a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap index f50836e6ca8af..1dd916f827fe6 100644 --- a/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap +++ b/src/plugins/vis_types/xy/public/editor/components/options/metrics_axes/__snapshots__/value_axes_panel.test.tsx.snap @@ -66,8 +66,10 @@ exports[`ValueAxesPanel component should init with the default set of props 1`] } buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate" + buttonElement="button" className="visEditorSidebar__section visEditorSidebar__collapsible" data-test-subj="toggleYAxisOptions-ValueAxis-1" + element="div" extraAction={ } buttonContentClassName="visEditorSidebar__aggGroupAccordionButtonContent eui-textTruncate" + buttonElement="button" className="visEditorSidebar__section visEditorSidebar__collapsible" data-test-subj="toggleYAxisOptions-ValueAxis-2" + element="div" extraAction={ + +
, + this.domNode + ); + const expressions = getExpressions(); this.handler = await expressions.loader(this.domNode, undefined, { onRenderError: (element: HTMLElement, error: ExpressionRenderError) => { diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable_async.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable_async.ts index c7480844adbea..2fa22cfe8d80b 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable_async.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable_async.ts @@ -12,10 +12,12 @@ export const createVisualizeEmbeddableAsync = async ( ...args: ConstructorParameters ) => { // Build optimization. Move app styles from main bundle - // @ts-expect-error TS error, cannot find type declaration for scss - await import('./embeddables.scss'); - const { VisualizeEmbeddable } = await import('./visualize_embeddable'); + const [{ VisualizeEmbeddable }] = await Promise.all([ + import('./visualize_embeddable'), + // @ts-expect-error TS error, cannot find type declaration for scss + import('./embeddables.scss'), + ]); return new VisualizeEmbeddable(...args); }; diff --git a/src/setup_node_env/dist.js b/src/setup_node_env/dist.js index 1d901b9ef5f06..3628a27a7793f 100644 --- a/src/setup_node_env/dist.js +++ b/src/setup_node_env/dist.js @@ -6,5 +6,5 @@ * Side Public License, v 1. */ -require('./no_transpilation'); +require('./no_transpilation_dist'); require('./polyfill'); diff --git a/src/setup_node_env/no_transpilation.js b/src/setup_node_env/no_transpilation.js index 1826f5bb0297d..b9497734b40bc 100644 --- a/src/setup_node_env/no_transpilation.js +++ b/src/setup_node_env/no_transpilation.js @@ -7,12 +7,4 @@ */ require('./ensure_node_preserve_symlinks'); - -// The following require statements MUST be executed before any others - BEGIN -require('./exit_on_warning'); -require('./harden'); -// The following require statements MUST be executed before any others - END - -require('symbol-observable'); -require('source-map-support/register'); -require('./node_version_validator'); +require('./no_transpilation_dist'); diff --git a/src/setup_node_env/no_transpilation_dist.js b/src/setup_node_env/no_transpilation_dist.js new file mode 100644 index 0000000000000..c52eba70f4ad3 --- /dev/null +++ b/src/setup_node_env/no_transpilation_dist.js @@ -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. + */ + +// The following require statements MUST be executed before any others - BEGIN +require('./exit_on_warning'); +require('./harden'); +// The following require statements MUST be executed before any others - END + +require('symbol-observable'); +require('source-map-support/register'); +require('./node_version_validator'); diff --git a/test/accessibility/apps/dashboard.ts b/test/accessibility/apps/dashboard.ts index 408e7d402a8f0..54eb5e7df4178 100644 --- a/test/accessibility/apps/dashboard.ts +++ b/test/accessibility/apps/dashboard.ts @@ -15,8 +15,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const listingTable = getService('listingTable'); - // FLAKY: https://github.com/elastic/kibana/issues/105171 - describe.skip('Dashboard', () => { + describe('Dashboard', () => { const dashboardName = 'Dashboard Listing A11y'; const clonedDashboardName = 'Dashboard Listing A11y Copy'; diff --git a/test/accessibility/apps/dashboard_panel.ts b/test/accessibility/apps/dashboard_panel.ts index b2fc073949d73..83c7776049d16 100644 --- a/test/accessibility/apps/dashboard_panel.ts +++ b/test/accessibility/apps/dashboard_panel.ts @@ -14,8 +14,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const inspector = getService('inspector'); - // FLAKY: https://github.com/elastic/kibana/issues/112920 - describe.skip('Dashboard Panel', () => { + describe('Dashboard Panel', () => { before(async () => { await PageObjects.common.navigateToApp('dashboard'); await testSubjects.click('dashboardListingTitleLink-[Flights]-Global-Flight-Dashboard'); diff --git a/test/accessibility/apps/discover.ts b/test/accessibility/apps/discover.ts index e05f3e2bc091d..867e146e64ca3 100644 --- a/test/accessibility/apps/discover.ts +++ b/test/accessibility/apps/discover.ts @@ -92,8 +92,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.discover.saveCurrentSavedQuery(); }); - // issue - https://github.com/elastic/kibana/issues/78488 - it.skip('a11y test on saved queries list panel', async () => { + it('a11y test on saved queries list panel', async () => { await PageObjects.discover.clickSavedQueriesPopOver(); await testSubjects.moveMouseTo( 'saved-query-list-item load-saved-query-test-button saved-query-list-item-selected saved-query-list-item-selected' diff --git a/test/api_integration/apis/custom_integration/integrations.ts b/test/api_integration/apis/custom_integration/integrations.ts index e4797b334a866..0784a86e4b546 100644 --- a/test/api_integration/apis/custom_integration/integrations.ts +++ b/test/api_integration/apis/custom_integration/integrations.ts @@ -22,7 +22,7 @@ export default function ({ getService }: FtrProviderContext) { expect(resp.body).to.be.an('array'); - expect(resp.body.length).to.be(12); + expect(resp.body.length).to.be(33); // Test for sample data card expect(resp.body.findIndex((c: { id: string }) => c.id === 'sample_data_all')).to.be.above( diff --git a/test/api_integration/apis/saved_objects_management/find.ts b/test/api_integration/apis/saved_objects_management/find.ts index 0b744b7991b38..ea7f297dfeb08 100644 --- a/test/api_integration/apis/saved_objects_management/find.ts +++ b/test/api_integration/apis/saved_objects_management/find.ts @@ -249,7 +249,7 @@ export default function ({ getService }: FtrProviderContext) { path: '/app/management/kibana/dataViews/dataView/8963ca30-3224-11e8-a572-ffca06da1357', uiCapabilitiesPath: 'management.kibana.indexPatterns', }, - namespaceType: 'single', + namespaceType: 'multiple-isolated', }); })); }); diff --git a/test/api_integration/apis/saved_objects_management/relationships.ts b/test/api_integration/apis/saved_objects_management/relationships.ts index 518ec29947016..838bc05346dda 100644 --- a/test/api_integration/apis/saved_objects_management/relationships.ts +++ b/test/api_integration/apis/saved_objects_management/relationships.ts @@ -91,7 +91,7 @@ export default function ({ getService }: FtrProviderContext) { path: '/app/management/kibana/dataViews/dataView/8963ca30-3224-11e8-a572-ffca06da1357', uiCapabilitiesPath: 'management.kibana.indexPatterns', }, - namespaceType: 'single', + namespaceType: 'multiple-isolated', hiddenType: false, }, }, @@ -132,7 +132,7 @@ export default function ({ getService }: FtrProviderContext) { path: '/app/management/kibana/dataViews/dataView/8963ca30-3224-11e8-a572-ffca06da1357', uiCapabilitiesPath: 'management.kibana.indexPatterns', }, - namespaceType: 'single', + namespaceType: 'multiple-isolated', hiddenType: false, }, relationship: 'child', diff --git a/test/common/services/security/test_user.ts b/test/common/services/security/test_user.ts index 695294f08b02d..1161e7b493f41 100644 --- a/test/common/services/security/test_user.ts +++ b/test/common/services/security/test_user.ts @@ -71,13 +71,12 @@ export class TestUser extends FtrService { export async function createTestUserService(ctx: FtrProviderContext, role: Role, user: User) { const log = ctx.getService('log'); const config = ctx.getService('config'); - const kibanaServer = ctx.getService('kibanaServer'); - const enabledPlugins = config.get('security.disableTestUser') - ? [] - : await kibanaServer.plugins.getEnabledIds(); - - const enabled = enabledPlugins.includes('security') && !config.get('security.disableTestUser'); + const enabled = + !config + .get('esTestCluster.serverArgs') + .some((arg: string) => arg === 'xpack.security.enabled=false') && + !config.get('security.disableTestUser'); if (enabled) { log.debug('===============creating roles and users==============='); diff --git a/test/functional/apps/context/_discover_navigation.ts b/test/functional/apps/context/_discover_navigation.ts index 1b8300f3345b1..60745bd64b8be 100644 --- a/test/functional/apps/context/_discover_navigation.ts +++ b/test/functional/apps/context/_discover_navigation.ts @@ -74,7 +74,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should open the context view with the same columns', async () => { const columnNames = await docTable.getHeaderFields(); - expect(columnNames).to.eql(['Time', ...TEST_COLUMN_NAMES]); + expect(columnNames).to.eql(['@timestamp', ...TEST_COLUMN_NAMES]); }); it('should open the context view with the filters disabled', async () => { diff --git a/test/functional/apps/dashboard/bwc_import.ts b/test/functional/apps/dashboard/bwc_import.ts deleted file mode 100644 index ebb9d2b99ffa7..0000000000000 --- a/test/functional/apps/dashboard/bwc_import.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 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 { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const PageObjects = getPageObjects(['dashboard', 'header', 'settings', 'savedObjects', 'common']); - const dashboardExpect = getService('dashboardExpect'); - // Legacy imports are no longer supported https://github.com/elastic/kibana/issues/103921 - describe.skip('bwc import', function describeIndexTests() { - before(async function () { - await PageObjects.dashboard.initTests(); - await PageObjects.settings.navigateTo(); - await PageObjects.settings.clickKibanaSavedObjects(); - await PageObjects.savedObjects.importFile( - path.join(__dirname, 'exports', 'dashboard_6_0_1.json') - ); - await PageObjects.settings.associateIndexPattern( - 'dd684000-8255-11eb-a5e7-93c302c8f329', - 'logstash-*' - ); - await PageObjects.savedObjects.clickConfirmChanges(); - await PageObjects.savedObjects.clickImportDone(); - await PageObjects.common.navigateToApp('dashboard'); - }); - - describe('6.0.1 dashboard', () => { - it('loads an imported dashboard', async function () { - await PageObjects.dashboard.gotoDashboardLandingPage(); - await PageObjects.dashboard.loadSavedDashboard('My custom bwc dashboard'); - await PageObjects.header.waitUntilLoadingHasFinished(); - - await dashboardExpect.metricValuesExist(['14,004']); - }); - }); - }); -} diff --git a/test/functional/apps/dashboard/index.ts b/test/functional/apps/dashboard/index.ts index 8627a258869bb..c9a62447f223a 100644 --- a/test/functional/apps/dashboard/index.ts +++ b/test/functional/apps/dashboard/index.ts @@ -49,7 +49,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dashboard_unsaved_state')); loadTestFile(require.resolve('./dashboard_unsaved_listing')); loadTestFile(require.resolve('./edit_visualizations')); - loadTestFile(require.resolve('./time_zones')); loadTestFile(require.resolve('./dashboard_options')); loadTestFile(require.resolve('./data_shared_attributes')); loadTestFile(require.resolve('./share')); @@ -95,7 +94,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dashboard_time_picker')); loadTestFile(require.resolve('./bwc_shared_urls')); - loadTestFile(require.resolve('./bwc_import')); loadTestFile(require.resolve('./panel_replacing')); loadTestFile(require.resolve('./panel_cloning')); loadTestFile(require.resolve('./copy_panel_to')); diff --git a/test/functional/apps/dashboard/time_zones.ts b/test/functional/apps/dashboard/time_zones.ts deleted file mode 100644 index f60792b3f292a..0000000000000 --- a/test/functional/apps/dashboard/time_zones.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 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 expect from '@kbn/expect'; - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const pieChart = getService('pieChart'); - const esArchiver = getService('esArchiver'); - const kibanaServer = getService('kibanaServer'); - const PageObjects = getPageObjects([ - 'dashboard', - 'timePicker', - 'settings', - 'common', - 'savedObjects', - ]); - // Legacy imports are no longer supported https://github.com/elastic/kibana/issues/103921 - describe.skip('dashboard time zones', function () { - this.tags('includeFirefox'); - - before(async () => { - await esArchiver.load('test/functional/fixtures/es_archiver/dashboard/current/kibana'); - await kibanaServer.uiSettings.replace({ - defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', - }); - await PageObjects.settings.navigateTo(); - await PageObjects.settings.clickKibanaSavedObjects(); - await PageObjects.savedObjects.importFile( - path.join(__dirname, 'exports', 'timezonetest_6_2_4.json') - ); - await PageObjects.savedObjects.checkImportSucceeded(); - await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.preserveCrossAppState(); - await PageObjects.dashboard.loadSavedDashboard('time zone test'); - }); - - after(async () => { - await kibanaServer.uiSettings.replace({ 'dateFormat:tz': 'UTC' }); - }); - - it('Exported dashboard adjusts EST time to UTC', async () => { - const time = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); - expect(time.start).to.be('Apr 10, 2018 @ 03:00:00.000'); - expect(time.end).to.be('Apr 10, 2018 @ 04:00:00.000'); - await pieChart.expectPieSliceCount(4); - }); - - it('Changing timezone changes dashboard timestamp and shows the same data', async () => { - await PageObjects.settings.navigateTo(); - await PageObjects.settings.clickKibanaSettings(); - await PageObjects.settings.setAdvancedSettingsSelect('dateFormat:tz', 'Etc/GMT+5'); - await PageObjects.common.navigateToApp('dashboard'); - await PageObjects.dashboard.loadSavedDashboard('time zone test'); - const time = await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes(); - expect(time.start).to.be('Apr 9, 2018 @ 22:00:00.000'); - expect(time.end).to.be('Apr 9, 2018 @ 23:00:00.000'); - await pieChart.expectPieSliceCount(4); - }); - }); -} diff --git a/test/functional/apps/discover/_data_grid.ts b/test/functional/apps/discover/_data_grid.ts index 4a343fb30384e..198691f3b8477 100644 --- a/test/functional/apps/discover/_data_grid.ts +++ b/test/functional/apps/discover/_data_grid.ts @@ -39,19 +39,19 @@ export default function ({ const getTitles = async () => (await testSubjects.getVisibleText('dataGridHeader')).replace(/\s|\r?\n|\r/g, ' '); - expect(await getTitles()).to.be('Time (@timestamp) Document'); + expect(await getTitles()).to.be('@timestamp Document'); await PageObjects.discover.clickFieldListItemAdd('bytes'); - expect(await getTitles()).to.be('Time (@timestamp) bytes'); + expect(await getTitles()).to.be('@timestamp bytes'); await PageObjects.discover.clickFieldListItemAdd('agent'); - expect(await getTitles()).to.be('Time (@timestamp) bytes agent'); + expect(await getTitles()).to.be('@timestamp bytes agent'); await PageObjects.discover.clickFieldListItemRemove('bytes'); - expect(await getTitles()).to.be('Time (@timestamp) agent'); + expect(await getTitles()).to.be('@timestamp agent'); await PageObjects.discover.clickFieldListItemRemove('agent'); - expect(await getTitles()).to.be('Time (@timestamp) Document'); + expect(await getTitles()).to.be('@timestamp Document'); }); }); } diff --git a/test/functional/apps/discover/_data_grid_context.ts b/test/functional/apps/discover/_data_grid_context.ts index 3d9e01e1dee19..d12ada2070cff 100644 --- a/test/functional/apps/discover/_data_grid_context.ts +++ b/test/functional/apps/discover/_data_grid_context.ts @@ -76,7 +76,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should open the context view with the same columns', async () => { const columnNames = await dataGrid.getHeaderFields(); - expect(columnNames).to.eql(['Time (@timestamp)', ...TEST_COLUMN_NAMES]); + expect(columnNames).to.eql(['@timestamp', ...TEST_COLUMN_NAMES]); }); it('should open the context view with the filters disabled', async () => { diff --git a/test/functional/apps/discover/_data_grid_field_data.ts b/test/functional/apps/discover/_data_grid_field_data.ts index 94e8e942f86ba..91c2d5914732d 100644 --- a/test/functional/apps/discover/_data_grid_field_data.ts +++ b/test/functional/apps/discover/_data_grid_field_data.ts @@ -59,8 +59,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - it('doc view should show Time and _source columns', async function () { - const expectedHeader = 'Time (@timestamp) Document'; + it('doc view should show @timestamp and _source columns', async function () { + const expectedHeader = '@timestamp Document'; const DocHeader = await dataGrid.getHeaderFields(); expect(DocHeader.join(' ')).to.be(expectedHeader); }); diff --git a/test/functional/apps/discover/_field_data.ts b/test/functional/apps/discover/_field_data.ts index 27407e9a0bc4d..28f147eeab55f 100644 --- a/test/functional/apps/discover/_field_data.ts +++ b/test/functional/apps/discover/_field_data.ts @@ -107,8 +107,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { after(async function () { await kibanaServer.uiSettings.replace({}); }); - it('doc view should show Time and _source columns', async function () { - const expectedHeader = 'Time\n_source'; + it('doc view should show @timestamp and _source columns', async function () { + const expectedHeader = '@timestamp\n_source'; const docHeader = await find.byCssSelector('thead > tr:nth-child(1)'); const docHeaderText = await docHeader.getVisibleText(); expect(docHeaderText).to.be(expectedHeader); diff --git a/test/functional/apps/discover/_field_data_with_fields_api.ts b/test/functional/apps/discover/_field_data_with_fields_api.ts index 666377ae7f794..f0dedb155fc9b 100644 --- a/test/functional/apps/discover/_field_data_with_fields_api.ts +++ b/test/functional/apps/discover/_field_data_with_fields_api.ts @@ -64,9 +64,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - it('doc view should show Time and Document columns', async function () { + it('doc view should show @timestamp and Document columns', async function () { const Docheader = await PageObjects.discover.getDocHeader(); - expect(Docheader).to.contain('Time'); + expect(Docheader).to.contain('@timestamp'); expect(Docheader).to.contain('Document'); }); diff --git a/test/functional/apps/saved_objects_management/inspect_saved_objects.ts b/test/functional/apps/saved_objects_management/inspect_saved_objects.ts index 7fff2cc001844..2faa66d258eb6 100644 --- a/test/functional/apps/saved_objects_management/inspect_saved_objects.ts +++ b/test/functional/apps/saved_objects_management/inspect_saved_objects.ts @@ -20,20 +20,20 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const focusAndClickButton = async (buttonSubject: string) => { const button = await testSubjects.find(buttonSubject); await button.scrollIntoViewIfNecessary(); - await delay(10); + await delay(100); await button.focus(); - await delay(10); + await delay(100); await button.click(); // Allow some time for the transition/animations to occur before assuming the click is done - await delay(10); + await delay(100); }; + const textIncludesAll = (text: string, items: string[]) => { const bools = items.map((item) => !!text.includes(item)); return bools.every((currBool) => currBool === true); }; - // FLAKY: https://github.com/elastic/kibana/issues/68400 - describe.skip('saved objects edition page', () => { + describe('saved objects inspect page', () => { beforeEach(async () => { await esArchiver.load( 'test/functional/fixtures/es_archiver/saved_objects_management/edit_saved_object' @@ -74,13 +74,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await PageObjects.settings.clickKibanaSavedObjects(); let objects = await PageObjects.savedObjects.getRowTitles(); expect(objects.includes('A Dashboard')).to.be(true); + await PageObjects.savedObjects.clickInspectByTitle('A Dashboard'); await PageObjects.common.navigateToUrl('management', 'kibana/objects/dashboard/i-exist', { shouldUseHashForSubUrl: false, - }); + }); // we should wait for it to load. + // wait for the Inspect view to load + await PageObjects.savedObjects.waitInspectObjectIsLoaded(); await focusAndClickButton('savedObjectEditDelete'); await PageObjects.common.clickConfirmOnModal(); - objects = await PageObjects.savedObjects.getRowTitles(); expect(objects.includes('A Dashboard')).to.be(false); }); diff --git a/test/functional/apps/visualize/_timelion.ts b/test/functional/apps/visualize/_timelion.ts index bb85b6821df31..c531ada8a2573 100644 --- a/test/functional/apps/visualize/_timelion.ts +++ b/test/functional/apps/visualize/_timelion.ts @@ -257,7 +257,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(value).to.eql('.es()'); }); - describe('dynamic suggestions for argument values', () => { + // FLAKY: https://github.com/elastic/kibana/issues/116033 + describe.skip('dynamic suggestions for argument values', () => { describe('.es()', () => { it('should show index pattern suggestions for index argument', async () => { await monacoEditor.setCodeEditorValue(''); diff --git a/test/functional/config.js b/test/functional/config.js index e0195c4dadc8d..5b0b79e84e8df 100644 --- a/test/functional/config.js +++ b/test/functional/config.js @@ -45,7 +45,6 @@ export default async function ({ readConfigFile }) { '--savedObjects.maxImportPayloadBytes=10485760', // to be re-enabled once kibana/issues/102552 is completed - '--xpack.security.enabled=false', '--xpack.reporting.enabled=false', ], }, diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index a6ee65e0febb5..a45c1a23ed3a5 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import expect from '@kbn/expect'; import { FtrService } from '../ftr_provider_context'; export class DiscoverPageObject extends FtrService { @@ -307,6 +308,13 @@ export class DiscoverPageObject extends FtrService { return await this.testSubjects.click('collapseSideBarButton'); } + public async closeSidebar() { + await this.retry.tryForTime(2 * 1000, async () => { + await this.toggleSidebarCollapse(); + await this.testSubjects.missingOrFail('discover-sidebar'); + }); + } + public async getAllFieldNames() { const sidebar = await this.testSubjects.find('discover-sidebar'); const $ = await sidebar.parseDomContent(); @@ -545,4 +553,37 @@ export class DiscoverPageObject extends FtrService { public async clearSavedQuery() { await this.testSubjects.click('saved-query-management-clear-button'); } + + public async assertHitCount(expectedHitCount: string) { + await this.retry.tryForTime(2 * 1000, async () => { + // Close side bar to ensure Discover hit count shows + // edge case for when browser width is small + await this.closeSidebar(); + const hitCount = await this.getHitCount(); + expect(hitCount).to.eql( + expectedHitCount, + `Expected Discover hit count to be ${expectedHitCount} but got ${hitCount}.` + ); + }); + } + + public async assertViewModeToggleNotExists() { + await this.testSubjects.missingOrFail('dscViewModeToggle', { timeout: 2 * 1000 }); + } + + public async assertViewModeToggleExists() { + await this.testSubjects.existOrFail('dscViewModeToggle', { timeout: 2 * 1000 }); + } + + public async assertFieldStatsTableNotExists() { + await this.testSubjects.missingOrFail('dscFieldStatsEmbeddedContent', { timeout: 2 * 1000 }); + } + + public async clickViewModeFieldStatsButton() { + await this.retry.tryForTime(2 * 1000, async () => { + await this.testSubjects.existOrFail('dscViewModeFieldStatsButton'); + await this.testSubjects.clickWhenNotDisabled('dscViewModeFieldStatsButton'); + await this.testSubjects.existOrFail('dscFieldStatsEmbeddedContent'); + }); + } } diff --git a/test/functional/page_objects/home_page.ts b/test/functional/page_objects/home_page.ts index 29fdd1453b0e0..11b304cdbbf9d 100644 --- a/test/functional/page_objects/home_page.ts +++ b/test/functional/page_objects/home_page.ts @@ -13,6 +13,7 @@ export class HomePageObject extends FtrService { private readonly retry = this.ctx.getService('retry'); private readonly find = this.ctx.getService('find'); private readonly common = this.ctx.getPageObject('common'); + private readonly log = this.ctx.getService('log'); async clickSynopsis(title: string) { await this.testSubjects.click(`homeSynopsisLink${title}`); @@ -27,7 +28,10 @@ export class HomePageObject extends FtrService { } async isSampleDataSetInstalled(id: string) { - return !(await this.testSubjects.exists(`addSampleDataSet${id}`)); + const sampleDataCard = await this.testSubjects.find(`sampleDataSetCard${id}`); + const sampleDataCardInnerHTML = await sampleDataCard.getAttribute('innerHTML'); + this.log.debug(sampleDataCardInnerHTML); + return sampleDataCardInnerHTML.includes('removeSampleDataSet'); } async isWelcomeInterstitialDisplayed() { diff --git a/test/functional/page_objects/management/saved_objects_page.ts b/test/functional/page_objects/management/saved_objects_page.ts index 9f48a6f57c8d8..21af7aa477abd 100644 --- a/test/functional/page_objects/management/saved_objects_page.ts +++ b/test/functional/page_objects/management/saved_objects_page.ts @@ -99,18 +99,30 @@ export class SavedObjectsPageObject extends FtrService { } async waitTableIsLoaded() { - return this.retry.try(async () => { + return await this.retry.try(async () => { const isLoaded = await this.find.existsByDisplayedByCssSelector( '*[data-test-subj="savedObjectsTable"] :not(.euiBasicTable-loading)' ); - if (isLoaded) { return true; } else { + this.log.debug(`still waiting for the table to load ${isLoaded}`); throw new Error('Waiting'); } }); } + async waitInspectObjectIsLoaded() { + return await this.retry.try(async () => { + this.log.debug(`wait for inspect view to load`); + const isLoaded = await this.find.byClassName('kibanaCodeEditor'); + const visibleContainerText = await isLoaded.getVisibleText(); + if (visibleContainerText) { + return true; + } else { + this.log.debug(`still waiting for json view to load ${isLoaded}`); + } + }); + } async clickRelationshipsByTitle(title: string) { const table = keyBy(await this.getElementsInTable(), 'title'); @@ -157,8 +169,10 @@ export class SavedObjectsPageObject extends FtrService { } async clickInspectByTitle(title: string) { + this.log.debug(`inspecting ${title} object through the context menu`); const table = keyBy(await this.getElementsInTable(), 'title'); if (table[title].menuElement) { + this.log.debug(`${title} has a menuElement`); await table[title].menuElement?.click(); // Wait for context menu to render const menuPanel = await this.find.byCssSelector('.euiContextMenuPanel'); @@ -166,6 +180,9 @@ export class SavedObjectsPageObject extends FtrService { await panelButton.click(); } else { // or the action elements are on the row without the menu + this.log.debug( + `${title} doesn't have a menu element, trying to copy the object instead using` + ); await table[title].copySaveObjectsElement?.click(); } } diff --git a/vars/tasks.groovy b/vars/tasks.groovy index da18d73e5b36c..1842e278282b1 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -146,13 +146,13 @@ def functionalXpack(Map params = [:]) { } } - // whenChanged([ - // 'x-pack/plugins/apm/', - // ]) { - // if (githubPr.isPr()) { - // task(kibanaPipeline.functionalTestProcess('xpack-APMCypress', './test/scripts/jenkins_apm_cypress.sh')) - // } - // } + whenChanged([ + 'x-pack/plugins/apm/', + ]) { + if (githubPr.isPr()) { + task(kibanaPipeline.functionalTestProcess('xpack-APMCypress', './test/scripts/jenkins_apm_cypress.sh')) + } + } whenChanged([ 'x-pack/plugins/uptime/', diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts index 2300143925b1e..1254d86e99066 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.test.ts @@ -8,7 +8,7 @@ import axios from 'axios'; import { createExternalService } from './service'; -import * as utils from '../lib/axios_utils'; +import { request, createAxiosResponse } from '../lib/axios_utils'; import { ExternalService } from './types'; import { Logger } from '../../../../../../src/core/server'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; @@ -29,10 +29,10 @@ jest.mock('../lib/axios_utils', () => { }); axios.create = jest.fn(() => axios); -const requestMock = utils.request as jest.Mock; +const requestMock = request as jest.Mock; const configurationUtilities = actionsConfigMock.create(); -const issueTypesResponse = { +const issueTypesResponse = createAxiosResponse({ data: { projects: [ { @@ -49,9 +49,9 @@ const issueTypesResponse = { }, ], }, -}; +}); -const fieldsResponse = { +const fieldsResponse = createAxiosResponse({ data: { projects: [ { @@ -98,7 +98,7 @@ const fieldsResponse = { }, ], }, -}; +}); const issueResponse = { id: '10267', @@ -108,6 +108,31 @@ const issueResponse = { const issuesResponse = [issueResponse]; +const mockNewAPI = () => + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + capabilities: { + 'list-project-issuetypes': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', + 'list-issuetype-fields': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }, + }, + }) + ); + +const mockOldAPI = () => + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + capabilities: { + navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', + }, + }, + }) + ); + describe('Jira service', () => { let service: ExternalService; @@ -183,18 +208,34 @@ describe('Jira service', () => { }); describe('getIncident', () => { + const axiosRes = { + data: { + id: '1', + key: 'CK-1', + fields: { + summary: 'title', + description: 'description', + created: '2021-10-20T19:41:02.754+0300', + updated: '2021-10-20T19:41:02.754+0300', + }, + }, + }; + test('it returns the incident correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { id: '1', key: 'CK-1', fields: { summary: 'title', description: 'description' } }, - })); + requestMock.mockImplementation(() => createAxiosResponse(axiosRes)); const res = await service.getIncident('1'); - expect(res).toEqual({ id: '1', key: 'CK-1', summary: 'title', description: 'description' }); + expect(res).toEqual({ + id: '1', + key: 'CK-1', + summary: 'title', + description: 'description', + created: '2021-10-20T19:41:02.754+0300', + updated: '2021-10-20T19:41:02.754+0300', + }); }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { id: '1', key: 'CK-1' }, - })); + requestMock.mockImplementation(() => createAxiosResponse(axiosRes)); await service.getIncident('1'); expect(requestMock).toHaveBeenCalledWith({ @@ -215,9 +256,38 @@ describe('Jira service', () => { '[Action][Jira]: Unable to get incident with id 1. Error: An error has occurred Reason: Required field' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ ...axiosRes, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getIncident('1')).rejects.toThrow( + '[Action][Jira]: Unable to get incident with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json Reason: unknown: errorResponse was null' + ); + }); + + test('it should throw if the required attributes are not there', async () => { + requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); + + await expect(service.getIncident('1')).rejects.toThrow( + '[Action][Jira]: Unable to get incident with id 1. Error: Response is missing at least one of the expected fields: id,key Reason: unknown: errorResponse was null' + ); + }); }); describe('createIncident', () => { + const incident = { + incident: { + summary: 'title', + description: 'desc', + labels: [], + issueType: '10006', + priority: 'High', + parent: 'RJ-107', + }, + }; + test('it creates the incident correctly', async () => { /* The response from Jira when creating an issue contains only the key and the id. The function makes the following calls when creating an issue: @@ -225,24 +295,19 @@ describe('Jira service', () => { 2. Create the issue. 3. Get the created issue with all the necessary fields. */ - requestMock.mockImplementationOnce(() => ({ - data: { id: '1', key: 'CK-1', fields: { summary: 'title', description: 'description' } }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { id: '1', key: 'CK-1', fields: { summary: 'title', description: 'description' } }, + }) + ); - requestMock.mockImplementationOnce(() => ({ - data: { id: '1', key: 'CK-1', fields: { created: '2020-04-27T10:59:46.202Z' } }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { id: '1', key: 'CK-1', fields: { created: '2020-04-27T10:59:46.202Z' } }, + }) + ); - const res = await service.createIncident({ - incident: { - summary: 'title', - description: 'desc', - labels: [], - issueType: '10006', - priority: 'High', - parent: null, - }, - }); + const res = await service.createIncident(incident); expect(res).toEqual({ title: 'CK-1', @@ -260,24 +325,30 @@ describe('Jira service', () => { 3. Get the created issue with all the necessary fields. */ // getIssueType mocks - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + capabilities: { + navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', + }, }, - }, - })); + }) + ); // getIssueType mocks requestMock.mockImplementationOnce(() => issueTypesResponse); - requestMock.mockImplementationOnce(() => ({ - data: { id: '1', key: 'CK-1', fields: { summary: 'title', description: 'description' } }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { id: '1', key: 'CK-1', fields: { summary: 'title', description: 'description' } }, + }) + ); - requestMock.mockImplementationOnce(() => ({ - data: { id: '1', key: 'CK-1', fields: { created: '2020-04-27T10:59:46.202Z' } }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { id: '1', key: 'CK-1', fields: { created: '2020-04-27T10:59:46.202Z' } }, + }) + ); const res = await service.createIncident({ incident: { @@ -317,25 +388,31 @@ describe('Jira service', () => { }); test('removes newline characters and trialing spaces from summary', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + capabilities: { + navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', + }, }, - }, - })); + }) + ); // getIssueType mocks requestMock.mockImplementationOnce(() => issueTypesResponse); // getIssueType mocks - requestMock.mockImplementationOnce(() => ({ - data: { id: '1', key: 'CK-1', fields: { summary: 'test', description: 'description' } }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { id: '1', key: 'CK-1', fields: { summary: 'test', description: 'description' } }, + }) + ); - requestMock.mockImplementationOnce(() => ({ - data: { id: '1', key: 'CK-1', fields: { created: '2020-04-27T10:59:46.202Z' } }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { id: '1', key: 'CK-1', fields: { created: '2020-04-27T10:59:46.202Z' } }, + }) + ); await service.createIncident({ incident: { @@ -368,24 +445,17 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - key: 'CK-1', - fields: { created: '2020-04-27T10:59:46.202Z' }, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + fields: { created: '2020-04-27T10:59:46.202Z' }, + }, + }) + ); - await service.createIncident({ - incident: { - summary: 'title', - description: 'desc', - labels: [], - issueType: '10006', - priority: 'High', - parent: 'RJ-107', - }, - }); + await service.createIncident(incident); expect(requestMock).toHaveBeenCalledWith({ axios, @@ -414,44 +484,55 @@ describe('Jira service', () => { throw error; }); - await expect( - service.createIncident({ - incident: { - summary: 'title', - description: 'desc', - labels: [], - issueType: '10006', - priority: 'High', - parent: null, - }, - }) - ).rejects.toThrow( + await expect(service.createIncident(incident)).rejects.toThrow( '[Action][Jira]: Unable to create incident. Error: An error has occurred. Reason: Required field' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.createIncident(incident)).rejects.toThrow( + '[Action][Jira]: Unable to create incident. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); + + test('it should throw if the required attributes are not there', async () => { + requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); + + await expect(service.createIncident(incident)).rejects.toThrow( + '[Action][Jira]: Unable to create incident. Error: Response is missing at least one of the expected fields: id. Reason: unknown: errorResponse was null' + ); + }); }); describe('updateIncident', () => { + const incident = { + incidentId: '1', + incident: { + summary: 'title', + description: 'desc', + labels: [], + issueType: '10006', + priority: 'High', + parent: 'RJ-107', + }, + }; + test('it updates the incident correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - key: 'CK-1', - fields: { updated: '2020-04-27T10:59:46.202Z' }, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + fields: { updated: '2020-04-27T10:59:46.202Z' }, + }, + }) + ); - const res = await service.updateIncident({ - incidentId: '1', - incident: { - summary: 'title', - description: 'desc', - labels: [], - issueType: '10006', - priority: 'High', - parent: null, - }, - }); + const res = await service.updateIncident(incident); expect(res).toEqual({ title: 'CK-1', @@ -462,25 +543,17 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - key: 'CK-1', - fields: { updated: '2020-04-27T10:59:46.202Z' }, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + fields: { updated: '2020-04-27T10:59:46.202Z' }, + }, + }) + ); - await service.updateIncident({ - incidentId: '1', - incident: { - summary: 'title', - description: 'desc', - labels: [], - issueType: '10006', - priority: 'High', - parent: 'RJ-107', - }, - }); + await service.updateIncident(incident); expect(requestMock).toHaveBeenCalledWith({ axios, @@ -509,41 +582,42 @@ describe('Jira service', () => { throw error; }); - await expect( - service.updateIncident({ - incidentId: '1', - incident: { - summary: 'title', - description: 'desc', - labels: [], - issueType: '10006', - priority: 'High', - parent: null, - }, - }) - ).rejects.toThrow( + await expect(service.updateIncident(incident)).rejects.toThrow( '[Action][Jira]: Unable to update incident with id 1. Error: An error has occurred. Reason: Required field' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.updateIncident(incident)).rejects.toThrow( + '[Action][Jira]: Unable to update incident with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); }); describe('createComment', () => { + const commentReq = { + incidentId: '1', + comment: { + comment: 'comment', + commentId: 'comment-1', + }, + }; test('it creates the comment correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - key: 'CK-1', - created: '2020-04-27T10:59:46.202Z', - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + created: '2020-04-27T10:59:46.202Z', + }, + }) + ); - const res = await service.createComment({ - incidentId: '1', - comment: { - comment: 'comment', - commentId: 'comment-1', - }, - }); + const res = await service.createComment(commentReq); expect(res).toEqual({ commentId: 'comment-1', @@ -553,21 +627,17 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - key: 'CK-1', - created: '2020-04-27T10:59:46.202Z', - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + key: 'CK-1', + created: '2020-04-27T10:59:46.202Z', + }, + }) + ); - await service.createComment({ - incidentId: '1', - comment: { - comment: 'comment', - commentId: 'comment-1', - }, - }); + await service.createComment(commentReq); expect(requestMock).toHaveBeenCalledWith({ axios, @@ -586,29 +656,33 @@ describe('Jira service', () => { throw error; }); - await expect( - service.createComment({ - incidentId: '1', - comment: { - comment: 'comment', - commentId: 'comment-1', - }, - }) - ).rejects.toThrow( + await expect(service.createComment(commentReq)).rejects.toThrow( '[Action][Jira]: Unable to create comment at incident with id 1. Error: An error has occurred. Reason: Required field' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.createComment(commentReq)).rejects.toThrow( + '[Action][Jira]: Unable to create comment at incident with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); + + test('it should throw if the required attributes are not there', async () => { + requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); + + await expect(service.createComment(commentReq)).rejects.toThrow( + '[Action][Jira]: Unable to create comment at incident with id 1. Error: Response is missing at least one of the expected fields: id,created. Reason: unknown: errorResponse was null' + ); + }); }); describe('getCapabilities', () => { test('it should return the capabilities', async () => { - requestMock.mockImplementation(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); const res = await service.getCapabilities(); expect(res).toEqual({ capabilities: { @@ -618,13 +692,7 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); await service.getCapabilities(); @@ -649,16 +717,34 @@ describe('Jira service', () => { ); }); - test('it should throw an auth error', async () => { + test('it should return unknown if the error is a string', async () => { requestMock.mockImplementation(() => { const error = new Error('An error has occurred'); - // @ts-ignore this can happen! + // @ts-ignore error.response = { data: 'Unauthorized' }; throw error; }); await expect(service.getCapabilities()).rejects.toThrow( - '[Action][Jira]: Unable to get capabilities. Error: An error has occurred. Reason: Unauthorized' + '[Action][Jira]: Unable to get capabilities. Error: An error has occurred. Reason: unknown: errorResponse.errors was null' + ); + }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getCapabilities()).rejects.toThrow( + '[Action][Jira]: Unable to get capabilities. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); + + test('it should throw if the required attributes are not there', async () => { + requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); + + await expect(service.getCapabilities()).rejects.toThrow( + '[Action][Jira]: Unable to get capabilities. Error: Response is missing at least one of the expected fields: capabilities. Reason: unknown: errorResponse was null' ); }); }); @@ -666,13 +752,7 @@ describe('Jira service', () => { describe('getIssueTypes', () => { describe('Old API', () => { test('it should return the issue types', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); requestMock.mockImplementationOnce(() => issueTypesResponse); @@ -691,13 +771,7 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); requestMock.mockImplementationOnce(() => issueTypesResponse); @@ -713,13 +787,7 @@ describe('Jira service', () => { }); test('it should throw an error', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); requestMock.mockImplementation(() => { const error: ResponseError = new Error('An error has occurred'); @@ -731,25 +799,30 @@ describe('Jira service', () => { '[Action][Jira]: Unable to get issue types. Error: An error has occurred. Reason: Could not get issue types' ); }); + + test('it should throw if the request is not a JSON', async () => { + mockOldAPI(); + + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getIssueTypes()).rejects.toThrow( + '[Action][Jira]: Unable to get issue types. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); }); describe('New API', () => { test('it should return the issue types', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', - }, - }, - })); + mockNewAPI(); - requestMock.mockImplementationOnce(() => ({ - data: { - values: issueTypesResponse.data.projects[0].issuetypes, - }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + values: issueTypesResponse.data.projects[0].issuetypes, + }, + }) + ); const res = await service.getIssueTypes(); @@ -766,22 +839,15 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', - }, - }, - })); + mockNewAPI(); - requestMock.mockImplementationOnce(() => ({ - data: { - values: issueTypesResponse.data.projects[0].issuetypes, - }, - })); + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + values: issueTypesResponse.data.projects[0].issuetypes, + }, + }) + ); await service.getIssueTypes(); @@ -795,16 +861,7 @@ describe('Jira service', () => { }); test('it should throw an error', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', - }, - }, - })); + mockNewAPI(); requestMock.mockImplementation(() => { const error: ResponseError = new Error('An error has occurred'); @@ -816,19 +873,25 @@ describe('Jira service', () => { '[Action][Jira]: Unable to get issue types. Error: An error has occurred. Reason: Could not get issue types' ); }); + + test('it should throw if the request is not a JSON', async () => { + mockNewAPI(); + + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getIssueTypes()).rejects.toThrow( + '[Action][Jira]: Unable to get issue types. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); }); }); describe('getFieldsByIssueType', () => { describe('Old API', () => { test('it should return the fields', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); requestMock.mockImplementationOnce(() => fieldsResponse); @@ -857,13 +920,7 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); requestMock.mockImplementationOnce(() => fieldsResponse); @@ -879,13 +936,7 @@ describe('Jira service', () => { }); test('it should throw an error', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - navigation: 'https://siem-kibana.atlassian.net/rest/capabilities/navigation', - }, - }, - })); + mockOldAPI(); requestMock.mockImplementation(() => { const error: ResponseError = new Error('An error has occurred'); @@ -897,43 +948,48 @@ describe('Jira service', () => { '[Action][Jira]: Unable to get fields. Error: An error has occurred. Reason: Could not get fields' ); }); + + test('it should throw if the request is not a JSON', async () => { + mockOldAPI(); + + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getFieldsByIssueType('10006')).rejects.toThrow( + '[Action][Jira]: Unable to get fields. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); }); describe('New API', () => { test('it should return the fields', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', - }, - }, - })); - - requestMock.mockImplementationOnce(() => ({ - data: { - values: [ - { required: true, schema: { type: 'string' }, fieldId: 'summary' }, - { - required: false, - schema: { type: 'string' }, - fieldId: 'priority', - allowedValues: [ - { + mockNewAPI(); + + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + values: [ + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, + { + required: false, + schema: { type: 'string' }, + fieldId: 'priority', + allowedValues: [ + { + name: 'Medium', + id: '3', + }, + ], + defaultValue: { name: 'Medium', id: '3', }, - ], - defaultValue: { - name: 'Medium', - id: '3', }, - }, - ], - }, - })); + ], + }, + }) + ); const res = await service.getFieldsByIssueType('10006'); @@ -954,39 +1010,32 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', - }, - }, - })); - - requestMock.mockImplementationOnce(() => ({ - data: { - values: [ - { required: true, schema: { type: 'string' }, fieldId: 'summary' }, - { - required: true, - schema: { type: 'string' }, - fieldId: 'priority', - allowedValues: [ - { + mockNewAPI(); + + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + values: [ + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, + { + required: true, + schema: { type: 'string' }, + fieldId: 'priority', + allowedValues: [ + { + name: 'Medium', + id: '3', + }, + ], + defaultValue: { name: 'Medium', id: '3', }, - ], - defaultValue: { - name: 'Medium', - id: '3', }, - }, - ], - }, - })); + ], + }, + }) + ); await service.getFieldsByIssueType('10006'); @@ -1000,16 +1049,7 @@ describe('Jira service', () => { }); test('it should throw an error', async () => { - requestMock.mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', - }, - }, - })); + mockNewAPI(); requestMock.mockImplementation(() => { const error: ResponseError = new Error('An error has occurred'); @@ -1021,16 +1061,30 @@ describe('Jira service', () => { '[Action][Jira]: Unable to get fields. Error: An error has occurred. Reason: Could not get issue types' ); }); + + test('it should throw if the request is not a JSON', async () => { + mockNewAPI(); + + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getFieldsByIssueType('10006')).rejects.toThrow( + '[Action][Jira]: Unable to get fields. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); }); }); describe('getIssues', () => { test('it should return the issues', async () => { - requestMock.mockImplementation(() => ({ - data: { - issues: issuesResponse, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + issues: issuesResponse, + }, + }) + ); const res = await service.getIssues('Test title'); @@ -1044,11 +1098,13 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - issues: issuesResponse, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + issues: issuesResponse, + }, + }) + ); await service.getIssues('Test title'); expect(requestMock).toHaveBeenLastCalledWith({ @@ -1071,13 +1127,25 @@ describe('Jira service', () => { '[Action][Jira]: Unable to get issues. Error: An error has occurred. Reason: Could not get issue types' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getIssues('Test title')).rejects.toThrow( + '[Action][Jira]: Unable to get issues. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); }); describe('getIssue', () => { test('it should return a single issue', async () => { - requestMock.mockImplementation(() => ({ - data: issueResponse, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: issueResponse, + }) + ); const res = await service.getIssue('RJ-107'); @@ -1089,11 +1157,13 @@ describe('Jira service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - issues: issuesResponse, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + issues: issuesResponse, + }, + }) + ); await service.getIssue('RJ-107'); expect(requestMock).toHaveBeenLastCalledWith({ @@ -1116,81 +1186,105 @@ describe('Jira service', () => { '[Action][Jira]: Unable to get issue with id RJ-107. Error: An error has occurred. Reason: Could not get issue types' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getIssue('Test title')).rejects.toThrow( + '[Action][Jira]: Unable to get issue with id Test title. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown: errorResponse was null' + ); + }); }); describe('getFields', () => { const callMocks = () => { requestMock - .mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + .mockImplementationOnce(() => + createAxiosResponse({ + data: { + capabilities: { + 'list-project-issuetypes': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', + 'list-issuetype-fields': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }, }, - }, - })) - .mockImplementationOnce(() => ({ - data: { - values: issueTypesResponse.data.projects[0].issuetypes, - }, - })) - .mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }) + ) + .mockImplementationOnce(() => + createAxiosResponse({ + data: { + values: issueTypesResponse.data.projects[0].issuetypes, }, - }, - })) - .mockImplementationOnce(() => ({ - data: { - capabilities: { - 'list-project-issuetypes': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', - 'list-issuetype-fields': - 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }) + ) + .mockImplementationOnce(() => + createAxiosResponse({ + data: { + capabilities: { + 'list-project-issuetypes': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', + 'list-issuetype-fields': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }, }, - }, - })) - .mockImplementationOnce(() => ({ - data: { - values: [ - { required: true, schema: { type: 'string' }, fieldId: 'summary' }, - { required: true, schema: { type: 'string' }, fieldId: 'description' }, - { - required: false, - schema: { type: 'string' }, - fieldId: 'priority', - allowedValues: [ - { + }) + ) + .mockImplementationOnce(() => + createAxiosResponse({ + data: { + capabilities: { + 'list-project-issuetypes': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-project-issuetypes', + 'list-issuetype-fields': + 'https://siem-kibana.atlassian.net/rest/capabilities/list-issuetype-fields', + }, + }, + }) + ) + .mockImplementationOnce(() => + createAxiosResponse({ + data: { + values: [ + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, + { required: true, schema: { type: 'string' }, fieldId: 'description' }, + { + required: false, + schema: { type: 'string' }, + fieldId: 'priority', + allowedValues: [ + { + name: 'Medium', + id: '3', + }, + ], + defaultValue: { name: 'Medium', id: '3', }, - ], - defaultValue: { - name: 'Medium', - id: '3', }, - }, - ], - }, - })) - .mockImplementationOnce(() => ({ - data: { - values: [ - { required: true, schema: { type: 'string' }, fieldId: 'summary' }, - { required: true, schema: { type: 'string' }, fieldId: 'description' }, - ], - }, - })); + ], + }, + }) + ) + .mockImplementationOnce(() => + createAxiosResponse({ + data: { + values: [ + { required: true, schema: { type: 'string' }, fieldId: 'summary' }, + { required: true, schema: { type: 'string' }, fieldId: 'description' }, + ], + }, + }) + ); }; + beforeEach(() => { jest.resetAllMocks(); }); + test('it should call request with correct arguments', async () => { callMocks(); await service.getFields(); diff --git a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts index be0240e705a65..a3262a526e2f4 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/jira/service.ts @@ -27,7 +27,7 @@ import { } from './types'; import * as i18n from './translations'; -import { request, getErrorMessage } from '../lib/axios_utils'; +import { request, getErrorMessage, throwIfResponseIsNotValid } from '../lib/axios_utils'; import { ActionsConfigurationUtilities } from '../../actions_config'; const VERSION = '2'; @@ -111,19 +111,15 @@ export const createExternalService = ( .filter((item) => !isEmpty(item)) .join(', '); - const createErrorMessage = (errorResponse: ResponseError | string | null | undefined): string => { + const createErrorMessage = (errorResponse: ResponseError | null | undefined): string => { if (errorResponse == null) { - return ''; - } - if (typeof errorResponse === 'string') { - // Jira error.response.data can be string!! - return errorResponse; + return 'unknown: errorResponse was null'; } const { errorMessages, errors } = errorResponse; if (errors == null) { - return ''; + return 'unknown: errorResponse.errors was null'; } if (Array.isArray(errorMessages) && errorMessages.length > 0) { @@ -185,9 +181,14 @@ export const createExternalService = ( configurationUtilities, }); - const { fields, ...rest } = res.data; + throwIfResponseIsNotValid({ + res, + requiredAttributesToBeInTheResponse: ['id', 'key'], + }); + + const { fields, id: incidentId, key } = res.data; - return { ...rest, ...fields }; + return { id: incidentId, key, created: fields.created, updated: fields.updated, ...fields }; } catch (error) { throw new Error( getErrorMessage( @@ -234,6 +235,11 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + requiredAttributesToBeInTheResponse: ['id'], + }); + const updatedIncident = await getIncident(res.data.id); return { @@ -266,7 +272,7 @@ export const createExternalService = ( const fields = createFields(projectKey, incidentWithoutNullValues); try { - await request({ + const res = await request({ axios: axiosInstance, method: 'put', url: `${incidentUrl}/${incidentId}`, @@ -275,6 +281,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + const updatedIncident = await getIncident(incidentId as string); return { @@ -309,6 +319,11 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + requiredAttributesToBeInTheResponse: ['id', 'created'], + }); + return { commentId: comment.commentId, externalCommentId: res.data.id, @@ -336,6 +351,11 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + requiredAttributesToBeInTheResponse: ['capabilities'], + }); + return { ...res.data }; } catch (error) { throw new Error( @@ -362,6 +382,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + const issueTypes = res.data.projects[0]?.issuetypes ?? []; return normalizeIssueTypes(issueTypes); } else { @@ -373,6 +397,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + const issueTypes = res.data.values; return normalizeIssueTypes(issueTypes); } @@ -401,6 +429,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + const fields = res.data.projects[0]?.issuetypes[0]?.fields || {}; return normalizeFields(fields); } else { @@ -412,6 +444,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + const fields = res.data.values.reduce( (acc: { [x: string]: {} }, value: { fieldId: string }) => ({ ...acc, @@ -471,6 +507,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + return normalizeSearchResults(res.data?.issues ?? []); } catch (error) { throw new Error( @@ -495,6 +535,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + return normalizeIssue(res.data ?? {}); } catch (error) { throw new Error( diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts index 287f74c6bc703..d0177e0e5a8a2 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.test.ts @@ -10,7 +10,14 @@ import { Agent as HttpsAgent } from 'https'; import HttpProxyAgent from 'http-proxy-agent'; import { HttpsProxyAgent } from 'https-proxy-agent'; import { Logger } from '../../../../../../src/core/server'; -import { addTimeZoneToDate, request, patch, getErrorMessage } from './axios_utils'; +import { + addTimeZoneToDate, + request, + patch, + getErrorMessage, + throwIfResponseIsNotValid, + createAxiosResponse, +} from './axios_utils'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { actionsConfigMock } from '../../actions_config.mock'; import { getCustomAgents } from './get_custom_agents'; @@ -292,3 +299,82 @@ describe('getErrorMessage', () => { expect(msg).toBe('[Action][My connector name]: An error has occurred'); }); }); + +describe('throwIfResponseIsNotValid', () => { + const res = createAxiosResponse({ + headers: { ['content-type']: 'application/json' }, + data: { incident: { id: '1' } }, + }); + + test('it does NOT throw if the request is valid', () => { + expect(() => throwIfResponseIsNotValid({ res })).not.toThrow(); + }); + + test('it does throw if the content-type is not json', () => { + expect(() => + throwIfResponseIsNotValid({ + res: { ...res, headers: { ['content-type']: 'text/html' } }, + }) + ).toThrow( + 'Unsupported content type: text/html in GET https://example.com. Supported content types: application/json' + ); + }); + + test('it does throw if the content-type is undefined', () => { + expect(() => + throwIfResponseIsNotValid({ + res: { ...res, headers: {} }, + }) + ).toThrow( + 'Unsupported content type: undefined in GET https://example.com. Supported content types: application/json' + ); + }); + + test('it does throw if the data is not an object or array', () => { + expect(() => + throwIfResponseIsNotValid({ + res: { ...res, data: 'string' }, + }) + ).toThrow('Response is not a valid JSON'); + }); + + test('it does NOT throw if the data is an array', () => { + expect(() => + throwIfResponseIsNotValid({ + res: { ...res, data: ['test'] }, + }) + ).not.toThrow(); + }); + + test.each(['', [], {}])('it does NOT throw if the data is %p', (data) => { + expect(() => + throwIfResponseIsNotValid({ + res: { ...res, data }, + }) + ).not.toThrow(); + }); + + test('it does throw if the required attribute is not in the response', () => { + expect(() => + throwIfResponseIsNotValid({ res, requiredAttributesToBeInTheResponse: ['not-exist'] }) + ).toThrow('Response is missing at least one of the expected fields: not-exist'); + }); + + test('it does throw if the required attribute are defined and the data is an array', () => { + expect(() => + throwIfResponseIsNotValid({ + res: { ...res, data: ['test'] }, + requiredAttributesToBeInTheResponse: ['not-exist'], + }) + ).toThrow('Response is missing at least one of the expected fields: not-exist'); + }); + + test('it does NOT throw if the value of the required attribute is null', () => { + expect(() => + throwIfResponseIsNotValid({ + res: { ...res, data: { id: null } }, + requiredAttributesToBeInTheResponse: ['id'], + }) + ).not.toThrow(); + }); +}); diff --git a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts index af353e1d1da5a..43c9d276e6574 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/lib/axios_utils.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { isObjectLike, isEmpty } from 'lodash'; import { AxiosInstance, Method, AxiosResponse, AxiosBasicCredentials } from 'axios'; import { Logger } from '../../../../../../src/core/server'; import { getCustomAgents } from './get_custom_agents'; @@ -76,3 +77,70 @@ export const addTimeZoneToDate = (date: string, timezone = 'GMT'): string => { export const getErrorMessage = (connector: string, msg: string) => { return `[Action][${connector}]: ${msg}`; }; + +export const throwIfResponseIsNotValid = ({ + res, + requiredAttributesToBeInTheResponse = [], +}: { + res: AxiosResponse; + requiredAttributesToBeInTheResponse?: string[]; +}) => { + const requiredContentType = 'application/json'; + const contentType = res.headers['content-type'] ?? 'undefined'; + const data = res.data; + + /** + * Check that the content-type of the response is application/json. + * Then includes is added because the header can be application/json;charset=UTF-8. + */ + if (!contentType.includes(requiredContentType)) { + throw new Error( + `Unsupported content type: ${contentType} in ${res.config.method} ${res.config.url}. Supported content types: ${requiredContentType}` + ); + } + + /** + * Check if the response is a JS object (data != null && typeof data === 'object') + * in case the content type is application/json but for some reason the response is not. + * Empty responses (204 No content) are ignored because the typeof data will be string and + * isObjectLike will fail. + * Axios converts automatically JSON to JS objects. + */ + if (!isEmpty(data) && !isObjectLike(data)) { + throw new Error('Response is not a valid JSON'); + } + + if (requiredAttributesToBeInTheResponse.length > 0) { + const requiredAttributesError = new Error( + `Response is missing at least one of the expected fields: ${requiredAttributesToBeInTheResponse.join( + ',' + )}` + ); + + /** + * If the response is an array and requiredAttributesToBeInTheResponse + * are not empty then we thrown an error assuming that the consumer + * expects an object response and not an array. + */ + + if (Array.isArray(data)) { + throw requiredAttributesError; + } + + requiredAttributesToBeInTheResponse.forEach((attr) => { + // Check only for undefined as null is a valid value + if (data[attr] === undefined) { + throw requiredAttributesError; + } + }); + } +}; + +export const createAxiosResponse = (res: Partial): AxiosResponse => ({ + data: {}, + status: 200, + statusText: 'OK', + headers: { ['content-type']: 'application/json' }, + config: { method: 'GET', url: 'https://example.com' }, + ...res, +}); diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts index ba55543386225..094b8150850df 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.test.ts @@ -8,7 +8,7 @@ import axios from 'axios'; import { createExternalService, getValueTextContent, formatUpdateRequest } from './service'; -import * as utils from '../lib/axios_utils'; +import { request, createAxiosResponse } from '../lib/axios_utils'; import { ExternalService } from './types'; import { Logger } from '../../../../../../src/core/server'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; @@ -27,7 +27,7 @@ jest.mock('../lib/axios_utils', () => { }); axios.create = jest.fn(() => axios); -const requestMock = utils.request as jest.Mock; +const requestMock = request as jest.Mock; const now = Date.now; const TIMESTAMP = 1589391874472; const configurationUtilities = actionsConfigMock.create(); @@ -38,44 +38,50 @@ const configurationUtilities = actionsConfigMock.create(); // b) Update the incident // c) Get the updated incident const mockIncidentUpdate = (withUpdateError = false) => { - requestMock.mockImplementationOnce(() => ({ - data: { - id: '1', - name: 'title', - description: { - format: 'html', - content: 'description', + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + id: '1', + name: 'title', + description: { + format: 'html', + content: 'description', + }, + incident_type_ids: [1001, 16, 12], + severity_code: 6, }, - incident_type_ids: [1001, 16, 12], - severity_code: 6, - }, - })); + }) + ); if (withUpdateError) { requestMock.mockImplementationOnce(() => { throw new Error('An error has occurred'); }); } else { - requestMock.mockImplementationOnce(() => ({ + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + success: true, + id: '1', + inc_last_modified_date: 1589391874472, + }, + }) + ); + } + + requestMock.mockImplementationOnce(() => + createAxiosResponse({ data: { - success: true, id: '1', + name: 'title_updated', + description: { + format: 'html', + content: 'desc_updated', + }, inc_last_modified_date: 1589391874472, }, - })); - } - - requestMock.mockImplementationOnce(() => ({ - data: { - id: '1', - name: 'title_updated', - description: { - format: 'html', - content: 'desc_updated', - }, - inc_last_modified_date: 1589391874472, - }, - })); + }) + ); }; describe('IBM Resilient service', () => { @@ -207,24 +213,28 @@ describe('IBM Resilient service', () => { describe('getIncident', () => { test('it returns the incident correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - name: '1', - description: { - format: 'html', - content: 'description', + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + name: '1', + description: { + format: 'html', + content: 'description', + }, }, - }, - })); + }) + ); const res = await service.getIncident('1'); expect(res).toEqual({ id: '1', name: '1', description: 'description' }); }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { id: '1' }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { id: '1' }, + }) + ); await service.getIncident('1'); expect(requestMock).toHaveBeenCalledWith({ @@ -246,28 +256,42 @@ describe('IBM Resilient service', () => { 'Unable to get incident with id 1. Error: An error has occurred' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getIncident('1')).rejects.toThrow( + '[Action][IBM Resilient]: Unable to get incident with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' + ); + }); }); describe('createIncident', () => { + const incident = { + incident: { + name: 'title', + description: 'desc', + incidentTypes: [1001], + severityCode: 6, + }, + }; + test('it creates the incident correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - name: 'title', - description: 'description', - discovered_date: 1589391874472, - create_date: 1589391874472, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + name: 'title', + description: 'description', + discovered_date: 1589391874472, + create_date: 1589391874472, + }, + }) + ); - const res = await service.createIncident({ - incident: { - name: 'title', - description: 'desc', - incidentTypes: [1001], - severityCode: 6, - }, - }); + const res = await service.createIncident(incident); expect(res).toEqual({ title: '1', @@ -278,24 +302,19 @@ describe('IBM Resilient service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - name: 'title', - description: 'description', - discovered_date: 1589391874472, - create_date: 1589391874472, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + name: 'title', + description: 'description', + discovered_date: 1589391874472, + create_date: 1589391874472, + }, + }) + ); - await service.createIncident({ - incident: { - name: 'title', - description: 'desc', - incidentTypes: [1001], - severityCode: 6, - }, - }); + await service.createIncident(incident); expect(requestMock).toHaveBeenCalledWith({ axios, @@ -334,20 +353,39 @@ describe('IBM Resilient service', () => { '[Action][IBM Resilient]: Unable to create incident. Error: An error has occurred' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.createIncident(incident)).rejects.toThrow( + '[Action][IBM Resilient]: Unable to create incident. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' + ); + }); + + test('it should throw if the required attributes are not there', async () => { + requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); + + await expect(service.createIncident(incident)).rejects.toThrow( + '[Action][IBM Resilient]: Unable to create incident. Error: Response is missing at least one of the expected fields: id,create_date.' + ); + }); }); describe('updateIncident', () => { + const req = { + incidentId: '1', + incident: { + name: 'title', + description: 'desc', + incidentTypes: [1001], + severityCode: 6, + }, + }; test('it updates the incident correctly', async () => { mockIncidentUpdate(); - const res = await service.updateIncident({ - incidentId: '1', - incident: { - name: 'title', - description: 'desc', - incidentTypes: [1001], - severityCode: 6, - }, - }); + const res = await service.updateIncident(req); expect(res).toEqual({ title: '1', @@ -430,38 +468,59 @@ describe('IBM Resilient service', () => { test('it should throw an error', async () => { mockIncidentUpdate(true); - await expect( - service.updateIncident({ - incidentId: '1', - incident: { + await expect(service.updateIncident(req)).rejects.toThrow( + '[Action][IBM Resilient]: Unable to update incident with id 1. Error: An error has occurred' + ); + }); + + test('it should throw if the request is not a JSON', async () => { + // get incident request + requestMock.mockImplementationOnce(() => + createAxiosResponse({ + data: { + id: '1', name: 'title', - description: 'desc', - incidentTypes: [1001], - severityCode: 5, + description: { + format: 'html', + content: 'description', + }, + incident_type_ids: [1001, 16, 12], + severity_code: 6, }, }) - ).rejects.toThrow( - '[Action][IBM Resilient]: Unable to update incident with id 1. Error: An error has occurred' + ); + + // update incident request + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.updateIncident(req)).rejects.toThrow( + '[Action][IBM Resilient]: Unable to update incident with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json' ); }); }); describe('createComment', () => { + const req = { + incidentId: '1', + comment: { + comment: 'comment', + commentId: 'comment-1', + }, + }; + test('it creates the comment correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - create_date: 1589391874472, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + create_date: 1589391874472, + }, + }) + ); - const res = await service.createComment({ - incidentId: '1', - comment: { - comment: 'comment', - commentId: 'comment-1', - }, - }); + const res = await service.createComment(req); expect(res).toEqual({ commentId: 'comment-1', @@ -471,20 +530,16 @@ describe('IBM Resilient service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: { - id: '1', - create_date: 1589391874472, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + id: '1', + create_date: 1589391874472, + }, + }) + ); - await service.createComment({ - incidentId: '1', - comment: { - comment: 'comment', - commentId: 'comment-1', - }, - }); + await service.createComment(req); expect(requestMock).toHaveBeenCalledWith({ axios, @@ -506,27 +561,31 @@ describe('IBM Resilient service', () => { throw new Error('An error has occurred'); }); - await expect( - service.createComment({ - incidentId: '1', - comment: { - comment: 'comment', - commentId: 'comment-1', - }, - }) - ).rejects.toThrow( + await expect(service.createComment(req)).rejects.toThrow( '[Action][IBM Resilient]: Unable to create comment at incident with id 1. Error: An error has occurred' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.createComment(req)).rejects.toThrow( + '[Action][IBM Resilient]: Unable to create comment at incident with id 1. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' + ); + }); }); describe('getIncidentTypes', () => { test('it creates the incident correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { - values: incidentTypes, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + values: incidentTypes, + }, + }) + ); const res = await service.getIncidentTypes(); @@ -545,15 +604,27 @@ describe('IBM Resilient service', () => { '[Action][IBM Resilient]: Unable to get incident types. Error: An error has occurred.' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getIncidentTypes()).rejects.toThrow( + '[Action][IBM Resilient]: Unable to get incident types. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' + ); + }); }); describe('getSeverity', () => { test('it creates the incident correctly', async () => { - requestMock.mockImplementation(() => ({ - data: { - values: severity, - }, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: { + values: severity, + }, + }) + ); const res = await service.getSeverity(); @@ -578,17 +649,29 @@ describe('IBM Resilient service', () => { throw new Error('An error has occurred'); }); - await expect(service.getIncidentTypes()).rejects.toThrow( - '[Action][IBM Resilient]: Unable to get incident types. Error: An error has occurred.' + await expect(service.getSeverity()).rejects.toThrow( + '[Action][IBM Resilient]: Unable to get severity. Error: An error has occurred.' + ); + }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getSeverity()).rejects.toThrow( + '[Action][IBM Resilient]: Unable to get severity. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' ); }); }); describe('getFields', () => { test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data: resilientFields, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: resilientFields, + }) + ); await service.getFields(); expect(requestMock).toHaveBeenCalledWith({ @@ -598,10 +681,13 @@ describe('IBM Resilient service', () => { url: 'https://resilient.elastic.co/rest/orgs/201/types/incident/fields', }); }); + test('it returns common fields correctly', async () => { - requestMock.mockImplementation(() => ({ - data: resilientFields, - })); + requestMock.mockImplementation(() => + createAxiosResponse({ + data: resilientFields, + }) + ); const res = await service.getFields(); expect(res).toEqual(resilientFields); }); @@ -614,5 +700,15 @@ describe('IBM Resilient service', () => { 'Unable to get fields. Error: An error has occurred' ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data: { id: '1' }, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.getFields()).rejects.toThrow( + '[Action][IBM Resilient]: Unable to get fields. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json.' + ); + }); }); }); diff --git a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts index 2f385315e4392..a469c631fac37 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/resilient/service.ts @@ -24,7 +24,7 @@ import { } from './types'; import * as i18n from './translations'; -import { getErrorMessage, request } from '../lib/axios_utils'; +import { getErrorMessage, request, throwIfResponseIsNotValid } from '../lib/axios_utils'; import { ActionsConfigurationUtilities } from '../../actions_config'; const VIEW_INCIDENT_URL = `#incidents`; @@ -134,6 +134,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + return { ...res.data, description: res.data.description?.content ?? '' }; } catch (error) { throw new Error( @@ -182,6 +186,11 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + requiredAttributesToBeInTheResponse: ['id', 'create_date'], + }); + return { title: `${res.data.id}`, id: `${res.data.id}`, @@ -212,6 +221,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + if (!res.data.success) { throw new Error(res.data.message); } @@ -245,6 +258,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + return { commentId: comment.commentId, externalCommentId: res.data.id, @@ -270,6 +287,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + const incidentTypes = res.data?.values ?? []; return incidentTypes.map((type: { value: string; label: string }) => ({ id: type.value, @@ -292,6 +313,10 @@ export const createExternalService = ( configurationUtilities, }); + throwIfResponseIsNotValid({ + res, + }); + const incidentTypes = res.data?.values ?? []; return incidentTypes.map((type: { value: string; label: string }) => ({ id: type.value, @@ -312,6 +337,11 @@ export const createExternalService = ( logger, configurationUtilities, }); + + throwIfResponseIsNotValid({ + res, + }); + return res.data ?? []; } catch (error) { throw new Error(getErrorMessage(i18n.NAME, `Unable to get fields. Error: ${error.message}.`)); diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.test.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.test.ts index 358af7cd2e9ef..e5a161611fcb1 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.test.ts @@ -132,7 +132,7 @@ describe('api_sir', () => { }); describe('prepareParams', () => { - test('it prepares the params correctly when the connector is legacy', async () => { + test('it prepares the params correctly when the connector uses the old API', async () => { expect(prepareParams(true, sirParams)).toEqual({ ...sirParams, incident: { @@ -145,7 +145,7 @@ describe('api_sir', () => { }); }); - test('it prepares the params correctly when the connector is not legacy', async () => { + test('it prepares the params correctly when the connector does not uses the old API', async () => { expect(prepareParams(false, sirParams)).toEqual({ ...sirParams, incident: { @@ -158,7 +158,7 @@ describe('api_sir', () => { }); }); - test('it prepares the params correctly when the connector is legacy and the observables are undefined', async () => { + test('it prepares the params correctly when the connector uses the old API and the observables are undefined', async () => { const { dest_ip: destIp, source_ip: sourceIp, @@ -192,7 +192,7 @@ describe('api_sir', () => { const res = await apiSIR.pushToService({ externalService, params, - config: { isLegacy: false }, + config: { usesTableApi: false }, secrets: {}, logger: mockedLogger, commentFieldKey: 'work_notes', @@ -221,7 +221,7 @@ describe('api_sir', () => { await apiSIR.pushToService({ externalService, params, - config: { isLegacy: false }, + config: { usesTableApi: false }, secrets: {}, logger: mockedLogger, commentFieldKey: 'work_notes', @@ -244,12 +244,12 @@ describe('api_sir', () => { ); }); - test('it does not call bulkAddObservableToIncident if it a legacy connector', async () => { + test('it does not call bulkAddObservableToIncident if the connector uses the old API', async () => { const params = { ...sirParams, incident: { ...sirParams.incident, externalId: null } }; await apiSIR.pushToService({ externalService, params, - config: { isLegacy: true }, + config: { usesTableApi: true }, secrets: {}, logger: mockedLogger, commentFieldKey: 'work_notes', @@ -274,7 +274,7 @@ describe('api_sir', () => { await apiSIR.pushToService({ externalService, params, - config: { isLegacy: false }, + config: { usesTableApi: false }, secrets: {}, logger: mockedLogger, commentFieldKey: 'work_notes', diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.ts index 326bb79a0e708..4e74d79c6f4a0 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/api_sir.ts @@ -59,13 +59,13 @@ const observablesToString = (obs: string | string[] | null | undefined): string }; export const prepareParams = ( - isLegacy: boolean, + usesTableApi: boolean, params: PushToServiceApiParamsSIR ): PushToServiceApiParamsSIR => { - if (isLegacy) { + if (usesTableApi) { /** * The schema has change to accept an array of observables - * or a string. In the case of a legacy connector we need to + * or a string. In the case of connector that uses the old API we need to * convert the observables to a string */ return { @@ -81,8 +81,8 @@ export const prepareParams = ( } /** - * For non legacy connectors the observables - * will be added in a different call. + * For connectors that do not use the old API + * the observables will be added in a different call. * They need to be set to null when sending the fields * to ServiceNow */ @@ -108,7 +108,7 @@ const pushToServiceHandler = async ({ }: PushToServiceApiHandlerArgs): Promise => { const res = await api.pushToService({ externalService, - params: prepareParams(!!config.isLegacy, params as PushToServiceApiParamsSIR), + params: prepareParams(!!config.usesTableApi, params as PushToServiceApiParamsSIR), config, secrets, commentFieldKey, @@ -130,7 +130,7 @@ const pushToServiceHandler = async ({ * through the pushToService call. */ - if (!config.isLegacy) { + if (!config.usesTableApi) { const sirExternalService = externalService as ExternalServiceSIR; const obsWithType: Array<[string[], ObservableTypes]> = [ diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts index af8d1b9f38b17..e41eea24834c7 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts @@ -14,7 +14,7 @@ export const ExternalIncidentServiceConfigurationBase = { export const ExternalIncidentServiceConfiguration = { ...ExternalIncidentServiceConfigurationBase, - isLegacy: schema.boolean({ defaultValue: true }), + usesTableApi: schema.boolean({ defaultValue: true }), }; export const ExternalIncidentServiceConfigurationBaseSchema = schema.object( @@ -49,7 +49,7 @@ const CommonAttributes = { externalId: schema.nullable(schema.string()), category: schema.nullable(schema.string()), subcategory: schema.nullable(schema.string()), - correlation_id: schema.nullable(schema.string()), + correlation_id: schema.nullable(schema.string({ defaultValue: DEFAULT_ALERTS_GROUPING_KEY })), correlation_display: schema.nullable(schema.string()), }; diff --git a/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts b/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts index cb030c7bb6933..c90a7222ba10b 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/servicenow/service.ts @@ -35,7 +35,8 @@ export const createExternalService: ServiceFactory = ( configurationUtilities: ActionsConfigurationUtilities, { table, importSetTable, useImportAPI, appScope }: SNProductsConfigValue ): ExternalService => { - const { apiUrl: url, isLegacy } = config as ServiceNowPublicConfigurationType; + const { apiUrl: url, usesTableApi: usesTableApiConfigValue } = + config as ServiceNowPublicConfigurationType; const { username, password } = secrets as ServiceNowSecretConfigurationType; if (!url || !username || !password) { @@ -57,11 +58,11 @@ export const createExternalService: ServiceFactory = ( auth: { username, password }, }); - const useOldApi = !useImportAPI || isLegacy; + const useTableApi = !useImportAPI || usesTableApiConfigValue; - const getCreateIncidentUrl = () => (useOldApi ? tableApiIncidentUrl : importSetTableUrl); + const getCreateIncidentUrl = () => (useTableApi ? tableApiIncidentUrl : importSetTableUrl); const getUpdateIncidentUrl = (incidentId: string) => - useOldApi ? `${tableApiIncidentUrl}/${incidentId}` : importSetTableUrl; + useTableApi ? `${tableApiIncidentUrl}/${incidentId}` : importSetTableUrl; const getIncidentViewURL = (id: string) => { // Based on: https://docs.servicenow.com/bundle/orlando-platform-user-interface/page/use/navigation/reference/r_NavigatingByURLExamples.html @@ -105,7 +106,7 @@ export const createExternalService: ServiceFactory = ( /** * Gets the Elastic SN Application information including the current version. - * It should not be used on legacy connectors. + * It should not be used on connectors that use the old API. */ const getApplicationInformation = async (): Promise => { try { @@ -129,7 +130,7 @@ export const createExternalService: ServiceFactory = ( logger.debug(`Create incident: Application scope: ${scope}: Application version${version}`); const checkIfApplicationIsInstalled = async () => { - if (!useOldApi) { + if (!useTableApi) { const { version, scope } = await getApplicationInformation(); logApplicationInfo(scope, version); } @@ -180,17 +181,17 @@ export const createExternalService: ServiceFactory = ( url: getCreateIncidentUrl(), logger, method: 'post', - data: prepareIncident(useOldApi, incident), + data: prepareIncident(useTableApi, incident), configurationUtilities, }); checkInstance(res); - if (!useOldApi) { + if (!useTableApi) { throwIfImportSetApiResponseIsAnError(res.data); } - const incidentId = useOldApi ? res.data.result.sys_id : res.data.result[0].sys_id; + const incidentId = useTableApi ? res.data.result.sys_id : res.data.result[0].sys_id; const insertedIncident = await getIncident(incidentId); return { @@ -212,23 +213,23 @@ export const createExternalService: ServiceFactory = ( axios: axiosInstance, url: getUpdateIncidentUrl(incidentId), // Import Set API supports only POST. - method: useOldApi ? 'patch' : 'post', + method: useTableApi ? 'patch' : 'post', logger, data: { - ...prepareIncident(useOldApi, incident), + ...prepareIncident(useTableApi, incident), // elastic_incident_id is used to update the incident when using the Import Set API. - ...(useOldApi ? {} : { elastic_incident_id: incidentId }), + ...(useTableApi ? {} : { elastic_incident_id: incidentId }), }, configurationUtilities, }); checkInstance(res); - if (!useOldApi) { + if (!useTableApi) { throwIfImportSetApiResponseIsAnError(res.data); } - const id = useOldApi ? res.data.result.sys_id : res.data.result[0].sys_id; + const id = useTableApi ? res.data.result.sys_id : res.data.result[0].sys_id; const updatedIncident = await getIncident(id); return { diff --git a/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.test.ts b/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.test.ts index 7b3f310a99e0e..21bc4894c5717 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.test.ts @@ -10,7 +10,7 @@ import axios from 'axios'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { Logger } from '../../../../../../src/core/server'; import { actionsConfigMock } from '../../actions_config.mock'; -import * as utils from '../lib/axios_utils'; +import { request, createAxiosResponse } from '../lib/axios_utils'; import { createExternalService } from './service'; import { mappings } from './mocks'; import { ExternalService } from './types'; @@ -27,7 +27,7 @@ jest.mock('../lib/axios_utils', () => { }); axios.create = jest.fn(() => axios); -const requestMock = utils.request as jest.Mock; +const requestMock = request as jest.Mock; const configurationUtilities = actionsConfigMock.create(); describe('Swimlane Service', () => { @@ -152,9 +152,7 @@ describe('Swimlane Service', () => { }; test('it creates a record correctly', async () => { - requestMock.mockImplementation(() => ({ - data, - })); + requestMock.mockImplementation(() => createAxiosResponse({ data })); const res = await service.createRecord({ incident, @@ -169,9 +167,7 @@ describe('Swimlane Service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data, - })); + requestMock.mockImplementation(() => createAxiosResponse({ data })); await service.createRecord({ incident, @@ -207,6 +203,24 @@ describe('Swimlane Service', () => { `[Action][Swimlane]: Unable to create record in application with id ${config.appId}. Status: 500. Error: An error has occurred. Reason: unknown` ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.createRecord({ incident })).rejects.toThrow( + `[Action][Swimlane]: Unable to create record in application with id ${config.appId}. Status: 500. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown` + ); + }); + + test('it should throw if the required attributes are not there', async () => { + requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); + + await expect(service.createRecord({ incident })).rejects.toThrow( + `[Action][Swimlane]: Unable to create record in application with id ${config.appId}. Status: 500. Error: Response is missing at least one of the expected fields: id,name,createdDate. Reason: unknown` + ); + }); }); describe('updateRecord', () => { @@ -218,9 +232,7 @@ describe('Swimlane Service', () => { const incidentId = '123'; test('it updates a record correctly', async () => { - requestMock.mockImplementation(() => ({ - data, - })); + requestMock.mockImplementation(() => createAxiosResponse({ data })); const res = await service.updateRecord({ incident, @@ -236,9 +248,7 @@ describe('Swimlane Service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data, - })); + requestMock.mockImplementation(() => createAxiosResponse({ data })); await service.updateRecord({ incident, @@ -276,6 +286,24 @@ describe('Swimlane Service', () => { `[Action][Swimlane]: Unable to update record in application with id ${config.appId}. Status: 500. Error: An error has occurred. Reason: unknown` ); }); + + test('it should throw if the request is not a JSON', async () => { + requestMock.mockImplementation(() => + createAxiosResponse({ data, headers: { ['content-type']: 'text/html' } }) + ); + + await expect(service.updateRecord({ incident, incidentId })).rejects.toThrow( + `[Action][Swimlane]: Unable to update record in application with id ${config.appId}. Status: 500. Error: Unsupported content type: text/html in GET https://example.com. Supported content types: application/json. Reason: unknown` + ); + }); + + test('it should throw if the required attributes are not there', async () => { + requestMock.mockImplementation(() => createAxiosResponse({ data: { notRequired: 'test' } })); + + await expect(service.updateRecord({ incident, incidentId })).rejects.toThrow( + `[Action][Swimlane]: Unable to update record in application with id ${config.appId}. Status: 500. Error: Response is missing at least one of the expected fields: id,name,modifiedDate. Reason: unknown` + ); + }); }); describe('createComment', () => { @@ -289,9 +317,7 @@ describe('Swimlane Service', () => { const createdDate = '2021-06-01T17:29:51.092Z'; test('it updates a record correctly', async () => { - requestMock.mockImplementation(() => ({ - data, - })); + requestMock.mockImplementation(() => createAxiosResponse({ data })); const res = await service.createComment({ comment, @@ -306,9 +332,7 @@ describe('Swimlane Service', () => { }); test('it should call request with correct arguments', async () => { - requestMock.mockImplementation(() => ({ - data, - })); + requestMock.mockImplementation(() => createAxiosResponse({ data })); await service.createComment({ comment, diff --git a/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts b/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts index f68d22121dbcc..d917d7f5677bb 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/swimlane/service.ts @@ -9,7 +9,7 @@ import { Logger } from '@kbn/logging'; import axios from 'axios'; import { ActionsConfigurationUtilities } from '../../actions_config'; -import { getErrorMessage, request } from '../lib/axios_utils'; +import { getErrorMessage, request, throwIfResponseIsNotValid } from '../lib/axios_utils'; import { getBodyForEventAction } from './helpers'; import { CreateCommentParams, @@ -89,6 +89,12 @@ export const createExternalService = ( method: 'post', url: getPostRecordUrl(appId), }); + + throwIfResponseIsNotValid({ + res, + requiredAttributesToBeInTheResponse: ['id', 'name', 'createdDate'], + }); + return { id: res.data.id, title: res.data.name, @@ -124,6 +130,11 @@ export const createExternalService = ( url: getPostRecordIdUrl(appId, params.incidentId), }); + throwIfResponseIsNotValid({ + res, + requiredAttributesToBeInTheResponse: ['id', 'name', 'modifiedDate'], + }); + return { id: res.data.id, title: res.data.name, diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts index 14cdfacd360a2..e6c82969a0aa2 100644 --- a/x-pack/plugins/actions/server/index.ts +++ b/x-pack/plugins/actions/server/index.ts @@ -57,7 +57,9 @@ export const plugin = (initContext: PluginInitializerContext) => new ActionsPlug export const config: PluginConfigDescriptor = { schema: configSchema, deprecations: ({ renameFromRoot, unused }) => [ - renameFromRoot('xpack.actions.whitelistedHosts', 'xpack.actions.allowedHosts'), + renameFromRoot('xpack.actions.whitelistedHosts', 'xpack.actions.allowedHosts', { + level: 'warning', + }), (settings, fromPath, addDeprecation) => { const actions = get(settings, fromPath); const customHostSettings = actions?.customHostSettings ?? []; @@ -69,6 +71,7 @@ export const config: PluginConfigDescriptor = { ) ) { addDeprecation({ + level: 'warning', configPath: 'xpack.actions.customHostSettings.ssl.rejectUnauthorized', message: `"xpack.actions.customHostSettings[].ssl.rejectUnauthorized" is deprecated.` + @@ -97,6 +100,7 @@ export const config: PluginConfigDescriptor = { const actions = get(settings, fromPath); if (actions?.hasOwnProperty('rejectUnauthorized')) { addDeprecation({ + level: 'warning', configPath: `${fromPath}.rejectUnauthorized`, message: `"xpack.actions.rejectUnauthorized" is deprecated. Use "xpack.actions.verificationMode" instead, ` + @@ -124,6 +128,7 @@ export const config: PluginConfigDescriptor = { const actions = get(settings, fromPath); if (actions?.hasOwnProperty('proxyRejectUnauthorizedCertificates')) { addDeprecation({ + level: 'warning', configPath: `${fromPath}.proxyRejectUnauthorizedCertificates`, message: `"xpack.actions.proxyRejectUnauthorizedCertificates" is deprecated. Use "xpack.actions.proxyVerificationMode" instead, ` + diff --git a/x-pack/plugins/actions/server/plugin.ts b/x-pack/plugins/actions/server/plugin.ts index d0404a253c0d9..2942c7492906a 100644 --- a/x-pack/plugins/actions/server/plugin.ts +++ b/x-pack/plugins/actions/server/plugin.ts @@ -96,19 +96,25 @@ export interface PluginSetupContract { >( actionType: ActionType ): void; + isPreconfiguredConnector(connectorId: string): boolean; } export interface PluginStartContract { isActionTypeEnabled(id: string, options?: { notifyUsage: boolean }): boolean; + isActionExecutable( actionId: string, actionTypeId: string, options?: { notifyUsage: boolean } ): boolean; + getActionsClientWithRequest(request: KibanaRequest): Promise>; + getActionsAuthorizationWithRequest(request: KibanaRequest): PublicMethodsOf; + preconfiguredActions: PreConfiguredAction[]; + renderActionParameterTemplates( actionTypeId: string, actionId: string, @@ -127,6 +133,7 @@ export interface ActionsPluginsSetup { features: FeaturesPluginSetup; spaces?: SpacesPluginSetup; } + export interface ActionsPluginsStart { encryptedSavedObjects: EncryptedSavedObjectsPluginStart; taskManager: TaskManagerStartContract; @@ -154,7 +161,7 @@ export class ActionsPlugin implements Plugin, plugins: ActionsPluginsSetup ): PluginSetupContract { + this.kibanaIndex = core.savedObjects.getKibanaIndex(); + this.licenseState = new LicenseState(plugins.licensing.license$); this.isESOCanEncrypt = plugins.encryptedSavedObjects.canEncrypt; @@ -253,14 +261,14 @@ export class ActionsPlugin implements Plugin( 'actions', - this.createRouteHandlerContext(core, this.kibanaIndexConfig.kibana.index) + this.createRouteHandlerContext(core, this.kibanaIndex) ); if (usageCollection) { initializeActionsTelemetry( this.telemetryLogger, plugins.taskManager, core, - this.kibanaIndexConfig.kibana.index, + this.kibanaIndex, this.preconfiguredActions ); } @@ -282,7 +290,7 @@ export class ActionsPlugin implements Plugin { expect(migratedAction).toEqual(action); }); - test('set isLegacy config property for .servicenow', () => { + test('set usesTableApi config property for .servicenow', () => { const migration716 = getActionsMigrations(encryptedSavedObjectsSetup)['7.16.0']; const action = getMockDataForServiceNow(); const migratedAction = migration716(action, context); @@ -177,13 +177,13 @@ describe('successful migrations', () => { ...action.attributes, config: { apiUrl: 'https://example.com', - isLegacy: true, + usesTableApi: true, }, }, }); }); - test('set isLegacy config property for .servicenow-sir', () => { + test('set usesTableApi config property for .servicenow-sir', () => { const migration716 = getActionsMigrations(encryptedSavedObjectsSetup)['7.16.0']; const action = getMockDataForServiceNow({ actionTypeId: '.servicenow-sir' }); const migratedAction = migration716(action, context); @@ -194,13 +194,13 @@ describe('successful migrations', () => { ...action.attributes, config: { apiUrl: 'https://example.com', - isLegacy: true, + usesTableApi: true, }, }, }); }); - test('it does not set isLegacy config for other connectors', () => { + test('it does not set usesTableApi config for other connectors', () => { const migration716 = getActionsMigrations(encryptedSavedObjectsSetup)['7.16.0']; const action = getMockData(); const migratedAction = migration716(action, context); diff --git a/x-pack/plugins/actions/server/saved_objects/actions_migrations.ts b/x-pack/plugins/actions/server/saved_objects/actions_migrations.ts index 688839eb89858..2e5b1b5d916fe 100644 --- a/x-pack/plugins/actions/server/saved_objects/actions_migrations.ts +++ b/x-pack/plugins/actions/server/saved_objects/actions_migrations.ts @@ -68,7 +68,7 @@ export function getActionsMigrations( doc.attributes.actionTypeId === '.servicenow' || doc.attributes.actionTypeId === '.servicenow-sir' || doc.attributes.actionTypeId === '.email', - pipeMigrations(markOldServiceNowITSMConnectorAsLegacy, setServiceConfigIfNotSet) + pipeMigrations(addUsesTableApiToServiceNowConnectors, setServiceConfigIfNotSet) ); const migrationActions800 = createEsoMigration( @@ -197,7 +197,7 @@ const addIsMissingSecretsField = ( }; }; -const markOldServiceNowITSMConnectorAsLegacy = ( +const addUsesTableApiToServiceNowConnectors = ( doc: SavedObjectUnsanitizedDoc ): SavedObjectUnsanitizedDoc => { if ( @@ -213,7 +213,7 @@ const markOldServiceNowITSMConnectorAsLegacy = ( ...doc.attributes, config: { ...doc.attributes.config, - isLegacy: true, + usesTableApi: true, }, }, }; diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index 1cb6bf8bfc74c..803a2122fe7f8 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -43,6 +43,7 @@ export async function getTotalCount( const { body: searchResult } = await esClient.search({ index: kibanaIndex, + size: 0, body: { query: { bool: { @@ -224,6 +225,7 @@ export async function getInUseTotalCount( const { body: actionResults } = await esClient.search({ index: kibanaIndex, + size: 0, body: { query: { bool: { diff --git a/x-pack/plugins/alerting/server/index.ts b/x-pack/plugins/alerting/server/index.ts index 162ee06216304..2ddb6ff711c46 100644 --- a/x-pack/plugins/alerting/server/index.ts +++ b/x-pack/plugins/alerting/server/index.ts @@ -48,14 +48,16 @@ export const plugin = (initContext: PluginInitializerContext) => new AlertingPlu export const config: PluginConfigDescriptor = { schema: configSchema, deprecations: ({ renameFromRoot }) => [ - renameFromRoot('xpack.alerts.healthCheck', 'xpack.alerting.healthCheck'), + renameFromRoot('xpack.alerts.healthCheck', 'xpack.alerting.healthCheck', { level: 'warning' }), renameFromRoot( 'xpack.alerts.invalidateApiKeysTask.interval', - 'xpack.alerting.invalidateApiKeysTask.interval' + 'xpack.alerting.invalidateApiKeysTask.interval', + { level: 'warning' } ), renameFromRoot( 'xpack.alerts.invalidateApiKeysTask.removalDelay', - 'xpack.alerting.invalidateApiKeysTask.removalDelay' + 'xpack.alerting.invalidateApiKeysTask.removalDelay', + { level: 'warning' } ), ], }; diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 3623495058eb0..c8f52110f5bcc 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -7,7 +7,7 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { first, map, share } from 'rxjs/operators'; -import { BehaviorSubject, Observable } from 'rxjs'; +import { BehaviorSubject } from 'rxjs'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { combineLatest } from 'rxjs'; import { SecurityPluginSetup, SecurityPluginStart } from '../../security/server'; @@ -108,10 +108,13 @@ export interface PluginSetupContract { export interface PluginStartContract { listTypes: RuleTypeRegistry['list']; + getRulesClientWithRequest(request: KibanaRequest): PublicMethodsOf; + getAlertingAuthorizationWithRequest( request: KibanaRequest ): PublicMethodsOf; + getFrameworkHealth: () => Promise; } @@ -125,6 +128,7 @@ export interface AlertingPluginsSetup { eventLog: IEventLogService; statusService: StatusServiceSetup; } + export interface AlertingPluginsStart { actions: ActionsPluginStartContract; taskManager: TaskManagerStartContract; @@ -150,7 +154,6 @@ export class AlertingPlugin { private readonly kibanaVersion: PluginInitializerContext['env']['packageInfo']['version']; private eventLogService?: IEventLogService; private eventLogger?: IEventLogger; - private readonly kibanaIndexConfig: Observable<{ kibana: { index: string } }>; private kibanaBaseUrl: string | undefined; constructor(initializerContext: PluginInitializerContext) { @@ -160,7 +163,6 @@ export class AlertingPlugin { this.rulesClientFactory = new RulesClientFactory(); this.alertingAuthorizationClientFactory = new AlertingAuthorizationClientFactory(); this.telemetryLogger = initializerContext.logger.get('usage'); - this.kibanaIndexConfig = initializerContext.config.legacy.globalConfig$; this.kibanaVersion = initializerContext.env.packageInfo.version; } @@ -168,6 +170,7 @@ export class AlertingPlugin { core: CoreSetup, plugins: AlertingPluginsSetup ): PluginSetupContract { + const kibanaIndex = core.savedObjects.getKibanaIndex(); this.kibanaBaseUrl = core.http.basePath.publicBaseUrl; this.licenseState = new LicenseState(plugins.licensing.license$); this.security = plugins.security; @@ -211,14 +214,7 @@ export class AlertingPlugin { usageCollection, core.getStartServices().then(([_, { taskManager }]) => taskManager) ); - this.kibanaIndexConfig.subscribe((config) => { - initializeAlertingTelemetry( - this.telemetryLogger, - core, - plugins.taskManager, - config.kibana.index - ); - }); + initializeAlertingTelemetry(this.telemetryLogger, core, plugins.taskManager, kibanaIndex); } // Usage counter for telemetry diff --git a/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts b/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts index 15fa6e63ac561..03a96d19b8e8a 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_telemetry.test.ts @@ -7,7 +7,7 @@ // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from '../../../../../src/core/server/elasticsearch/client/mocks'; -import { getTotalCountInUse } from './alerts_telemetry'; +import { getTotalCountAggregations, getTotalCountInUse } from './alerts_telemetry'; describe('alerts telemetry', () => { test('getTotalCountInUse should replace first "." symbol to "__" in alert types names', async () => { @@ -49,6 +49,69 @@ Object { "countNamespaces": 1, "countTotal": 4, } +`); + }); + + test('getTotalCountAggregations should return min/max connectors in use', async () => { + const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser; + mockEsClient.search.mockReturnValue( + // @ts-expect-error @elastic/elasticsearch Aggregate only allows unknown values + elasticsearchClientMock.createSuccessTransportRequestPromise({ + aggregations: { + byAlertTypeId: { + value: { + ruleTypes: { + '.index-threshold': 2, + 'logs.alert.document.count': 1, + 'document.test.': 1, + }, + }, + }, + max_throttle_time: { value: 60 }, + min_throttle_time: { value: 0 }, + avg_throttle_time: { value: 30 }, + max_interval_time: { value: 10 }, + min_interval_time: { value: 1 }, + avg_interval_time: { value: 4.5 }, + max_actions_count: { value: 4 }, + min_actions_count: { value: 0 }, + avg_actions_count: { value: 2.5 }, + }, + hits: { + hits: [], + }, + }) + ); + + const telemetry = await getTotalCountAggregations(mockEsClient, 'test'); + + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + + expect(telemetry).toMatchInlineSnapshot(` +Object { + "connectors_per_alert": Object { + "avg": 2.5, + "max": 4, + "min": 0, + }, + "count_by_type": Object { + "__index-threshold": 2, + "document.test__": 1, + "logs.alert.document.count": 1, + }, + "count_rules_namespaces": 0, + "count_total": 4, + "schedule_time": Object { + "avg": 4.5, + "max": 10, + "min": 1, + }, + "throttle_time": Object { + "avg": 30, + "max": 60, + "min": 0, + }, +} `); }); }); diff --git a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts index 18fa9b590b4e1..7ff9538c1aa26 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_telemetry.ts @@ -52,218 +52,128 @@ export async function getTotalCountAggregations( | 'count_rules_namespaces' > > { - const throttleTimeMetric = { - scripted_metric: { - init_script: 'state.min = 0; state.max = 0; state.totalSum = 0; state.totalCount = 0;', - map_script: ` - if (doc['alert.throttle'].size() > 0) { - def throttle = doc['alert.throttle'].value; + const { body: results } = await esClient.search({ + index: kibanaInex, + body: { + size: 0, + query: { + bool: { + filter: [{ term: { type: 'alert' } }], + }, + }, + runtime_mappings: { + alert_action_count: { + type: 'long', + script: { + source: ` + def alert = params._source['alert']; + if (alert != null) { + def actions = alert.actions; + if (actions != null) { + emit(actions.length); + } else { + emit(0); + } + }`, + }, + }, + alert_interval: { + type: 'long', + script: { + source: ` + int parsed = 0; + if (doc['alert.schedule.interval'].size() > 0) { + def interval = doc['alert.schedule.interval'].value; - if (throttle.length() > 1) { - // get last char - String timeChar = throttle.substring(throttle.length() - 1); - // remove last char - throttle = throttle.substring(0, throttle.length() - 1); + if (interval.length() > 1) { + // get last char + String timeChar = interval.substring(interval.length() - 1); + // remove last char + interval = interval.substring(0, interval.length() - 1); - if (throttle.chars().allMatch(Character::isDigit)) { - // using of regex is not allowed in painless language - int parsed = Integer.parseInt(throttle); + if (interval.chars().allMatch(Character::isDigit)) { + // using of regex is not allowed in painless language + parsed = Integer.parseInt(interval); - if (timeChar.equals("s")) { - parsed = parsed; - } else if (timeChar.equals("m")) { - parsed = parsed * 60; - } else if (timeChar.equals("h")) { - parsed = parsed * 60 * 60; - } else if (timeChar.equals("d")) { - parsed = parsed * 24 * 60 * 60; - } - if (state.min === 0 || parsed < state.min) { - state.min = parsed; - } - if (parsed > state.max) { - state.max = parsed; + if (timeChar.equals("s")) { + parsed = parsed; + } else if (timeChar.equals("m")) { + parsed = parsed * 60; + } else if (timeChar.equals("h")) { + parsed = parsed * 60 * 60; + } else if (timeChar.equals("d")) { + parsed = parsed * 24 * 60 * 60; + } + emit(parsed); + } } - state.totalSum += parsed; - state.totalCount++; } - } - } - `, - // Combine script is executed per cluster, but we already have a key-value pair per cluster. - // Despite docs that say this is optional, this script can't be blank. - combine_script: 'return state', - // Reduce script is executed across all clusters, so we need to add up all the total from each cluster - // This also needs to account for having no data - reduce_script: ` - double min = 0; - double max = 0; - long totalSum = 0; - long totalCount = 0; - for (Map m : states.toArray()) { - if (m !== null) { - min = min > 0 ? Math.min(min, m.min) : m.min; - max = Math.max(max, m.max); - totalSum += m.totalSum; - totalCount += m.totalCount; - } - } - Map result = new HashMap(); - result.min = min; - result.max = max; - result.totalSum = totalSum; - result.totalCount = totalCount; - return result; - `, - }, - }; - - const intervalTimeMetric = { - scripted_metric: { - init_script: 'state.min = 0; state.max = 0; state.totalSum = 0; state.totalCount = 0;', - map_script: ` - if (doc['alert.schedule.interval'].size() > 0) { - def interval = doc['alert.schedule.interval'].value; + emit(parsed); + `, + }, + }, + alert_throttle: { + type: 'long', + script: { + source: ` + int parsed = 0; + if (doc['alert.throttle'].size() > 0) { + def throttle = doc['alert.throttle'].value; - if (interval.length() > 1) { - // get last char - String timeChar = interval.substring(interval.length() - 1); - // remove last char - interval = interval.substring(0, interval.length() - 1); + if (throttle.length() > 1) { + // get last char + String timeChar = throttle.substring(throttle.length() - 1); + // remove last char + throttle = throttle.substring(0, throttle.length() - 1); - if (interval.chars().allMatch(Character::isDigit)) { - // using of regex is not allowed in painless language - int parsed = Integer.parseInt(interval); + if (throttle.chars().allMatch(Character::isDigit)) { + // using of regex is not allowed in painless language + parsed = Integer.parseInt(throttle); - if (timeChar.equals("s")) { - parsed = parsed; - } else if (timeChar.equals("m")) { - parsed = parsed * 60; - } else if (timeChar.equals("h")) { - parsed = parsed * 60 * 60; - } else if (timeChar.equals("d")) { - parsed = parsed * 24 * 60 * 60; - } - if (state.min === 0 || parsed < state.min) { - state.min = parsed; - } - if (parsed > state.max) { - state.max = parsed; - } - state.totalSum += parsed; - state.totalCount++; + if (timeChar.equals("s")) { + parsed = parsed; + } else if (timeChar.equals("m")) { + parsed = parsed * 60; + } else if (timeChar.equals("h")) { + parsed = parsed * 60 * 60; + } else if (timeChar.equals("d")) { + parsed = parsed * 24 * 60 * 60; + } + emit(parsed); + } } - } - } - `, - // Combine script is executed per cluster, but we already have a key-value pair per cluster. - // Despite docs that say this is optional, this script can't be blank. - combine_script: 'return state', - // Reduce script is executed across all clusters, so we need to add up all the total from each cluster - // This also needs to account for having no data - reduce_script: ` - double min = 0; - double max = 0; - long totalSum = 0; - long totalCount = 0; - for (Map m : states.toArray()) { - if (m !== null) { - min = min > 0 ? Math.min(min, m.min) : m.min; - max = Math.max(max, m.max); - totalSum += m.totalSum; - totalCount += m.totalCount; - } - } - Map result = new HashMap(); - result.min = min; - result.max = max; - result.totalSum = totalSum; - result.totalCount = totalCount; - return result; - `, - }, - }; - - const connectorsMetric = { - scripted_metric: { - init_script: - 'state.currentAlertActions = 0; state.min = 0; state.max = 0; state.totalActionsCount = 0;', - map_script: ` - String refName = doc['alert.actions.actionRef'].value; - if (refName == 'action_0') { - if (state.currentAlertActions !== 0 && state.currentAlertActions < state.min) { - state.min = state.currentAlertActions; - } - if (state.currentAlertActions !== 0 && state.currentAlertActions > state.max) { - state.max = state.currentAlertActions; - } - state.currentAlertActions = 1; - } else { - state.currentAlertActions++; - } - state.totalActionsCount++; - `, - // Combine script is executed per cluster, but we already have a key-value pair per cluster. - // Despite docs that say this is optional, this script can't be blank. - combine_script: 'return state', - // Reduce script is executed across all clusters, so we need to add up all the total from each cluster - // This also needs to account for having no data - reduce_script: ` - double min = 0; - double max = 0; - long totalActionsCount = 0; - long currentAlertActions = 0; - for (Map m : states.toArray()) { - if (m !== null) { - min = min > 0 ? Math.min(min, m.min) : m.min; - max = Math.max(max, m.max); - currentAlertActions += m.currentAlertActions; - totalActionsCount += m.totalActionsCount; - } - } - Map result = new HashMap(); - result.min = min; - result.max = max; - result.currentAlertActions = currentAlertActions; - result.totalActionsCount = totalActionsCount; - return result; - `, - }, - }; - - const { body: results } = await esClient.search({ - index: kibanaInex, - body: { - query: { - bool: { - filter: [{ term: { type: 'alert' } }], + } + emit(parsed); + `, + }, }, }, aggs: { byAlertTypeId: alertTypeMetric, - throttleTime: throttleTimeMetric, - intervalTime: intervalTimeMetric, - connectorsAgg: { - nested: { - path: 'alert.actions', - }, - aggs: { - connectors: connectorsMetric, - }, - }, + max_throttle_time: { max: { field: 'alert_throttle' } }, + min_throttle_time: { min: { field: 'alert_throttle' } }, + avg_throttle_time: { avg: { field: 'alert_throttle' } }, + max_interval_time: { max: { field: 'alert_interval' } }, + min_interval_time: { min: { field: 'alert_interval' } }, + avg_interval_time: { avg: { field: 'alert_interval' } }, + max_actions_count: { max: { field: 'alert_action_count' } }, + min_actions_count: { min: { field: 'alert_action_count' } }, + avg_actions_count: { avg: { field: 'alert_action_count' } }, }, }, }); const aggregations = results.aggregations as { byAlertTypeId: { value: { ruleTypes: Record } }; - throttleTime: { value: { min: number; max: number; totalCount: number; totalSum: number } }; - intervalTime: { value: { min: number; max: number; totalCount: number; totalSum: number } }; - connectorsAgg: { - connectors: { - value: { min: number; max: number; totalActionsCount: number; totalAlertsCount: number }; - }; - }; + max_throttle_time: { value: number }; + min_throttle_time: { value: number }; + avg_throttle_time: { value: number }; + max_interval_time: { value: number }; + min_interval_time: { value: number }; + avg_interval_time: { value: number }; + max_actions_count: { value: number }; + min_actions_count: { value: number }; + avg_actions_count: { value: number }; }; const totalAlertsCount = Object.keys(aggregations.byAlertTypeId.value.ruleTypes).reduce( @@ -284,30 +194,19 @@ export async function getTotalCountAggregations( {} ), throttle_time: { - min: `${aggregations.throttleTime.value.min}s`, - avg: `${ - aggregations.throttleTime.value.totalCount > 0 - ? aggregations.throttleTime.value.totalSum / aggregations.throttleTime.value.totalCount - : 0 - }s`, - max: `${aggregations.throttleTime.value.max}s`, + min: aggregations.min_throttle_time.value, + avg: aggregations.avg_throttle_time.value, + max: aggregations.max_throttle_time.value, }, schedule_time: { - min: `${aggregations.intervalTime.value.min}s`, - avg: `${ - aggregations.intervalTime.value.totalCount > 0 - ? aggregations.intervalTime.value.totalSum / aggregations.intervalTime.value.totalCount - : 0 - }s`, - max: `${aggregations.intervalTime.value.max}s`, + min: aggregations.min_interval_time.value, + avg: aggregations.avg_interval_time.value, + max: aggregations.max_interval_time.value, }, connectors_per_alert: { - min: aggregations.connectorsAgg.connectors.value.min, - avg: - totalAlertsCount > 0 - ? aggregations.connectorsAgg.connectors.value.totalActionsCount / totalAlertsCount - : 0, - max: aggregations.connectorsAgg.connectors.value.max, + min: aggregations.min_actions_count.value, + avg: aggregations.avg_actions_count.value, + max: aggregations.max_actions_count.value, }, count_rules_namespaces: 0, }; @@ -316,6 +215,7 @@ export async function getTotalCountAggregations( export async function getTotalCountInUse(esClient: ElasticsearchClient, kibanaInex: string) { const { body: searchResult } = await esClient.search({ index: kibanaInex, + size: 0, body: { query: { bool: { diff --git a/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts b/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts index ecea721dfad92..e9405c51dbf15 100644 --- a/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts +++ b/x-pack/plugins/alerting/server/usage/alerts_usage_collector.ts @@ -75,14 +75,14 @@ export function createAlertsUsageCollector( count_active_total: 0, count_disabled_total: 0, throttle_time: { - min: '0s', - avg: '0s', - max: '0s', + min: 0, + avg: 0, + max: 0, }, schedule_time: { - min: '0s', - avg: '0s', - max: '0s', + min: 0, + avg: 0, + max: 0, }, connectors_per_alert: { min: 0, @@ -100,14 +100,14 @@ export function createAlertsUsageCollector( count_active_total: { type: 'long' }, count_disabled_total: { type: 'long' }, throttle_time: { - min: { type: 'keyword' }, - avg: { type: 'keyword' }, - max: { type: 'keyword' }, + min: { type: 'long' }, + avg: { type: 'float' }, + max: { type: 'long' }, }, schedule_time: { - min: { type: 'keyword' }, - avg: { type: 'keyword' }, - max: { type: 'keyword' }, + min: { type: 'long' }, + avg: { type: 'float' }, + max: { type: 'long' }, }, connectors_per_alert: { min: { type: 'long' }, diff --git a/x-pack/plugins/alerting/server/usage/types.ts b/x-pack/plugins/alerting/server/usage/types.ts index 5e420b54e37cb..0e489893a1bbc 100644 --- a/x-pack/plugins/alerting/server/usage/types.ts +++ b/x-pack/plugins/alerting/server/usage/types.ts @@ -13,14 +13,14 @@ export interface AlertsUsage { count_active_by_type: Record; count_rules_namespaces: number; throttle_time: { - min: string; - avg: string; - max: string; + min: number; + avg: number; + max: number; }; schedule_time: { - min: string; - avg: string; - max: string; + min: number; + avg: number; + max: number; }; connectors_per_alert: { min: number; diff --git a/x-pack/plugins/apm/dev_docs/linting.md b/x-pack/plugins/apm/dev_docs/linting.md index edf3e813a88e9..3dbd7b5b27484 100644 --- a/x-pack/plugins/apm/dev_docs/linting.md +++ b/x-pack/plugins/apm/dev_docs/linting.md @@ -19,3 +19,12 @@ yarn prettier "./x-pack/plugins/apm/**/*.{tsx,ts,js}" --write ``` node scripts/eslint.js x-pack/plugins/apm ``` + +## Install pre-commit hook (optional) +In case you want to run a couple of checks like linting or check the file casing of the files to commit, we provide a way to install a pre-commit hook. To configure it you just need to run the following: + +`node scripts/register_git_hook` + +After the script completes the pre-commit hook will be created within the file .git/hooks/pre-commit. If you choose to not install it, don’t worry, we still run a quick CI check to provide feedback earliest as we can about the same checks. + +More information about linting can be found in the [Kibana Guide](https://www.elastic.co/guide/en/kibana/current/kibana-linting.html). \ No newline at end of file diff --git a/x-pack/plugins/apm/ftr_e2e/cypress_start.ts b/x-pack/plugins/apm/ftr_e2e/cypress_start.ts index caf87d2627459..0cfc58653801a 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress_start.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress_start.ts @@ -16,15 +16,10 @@ import { esArchiverLoad, esArchiverUnload } from './cypress/tasks/es_archiver'; export function cypressRunTests(spec?: string) { return async ({ getService }: FtrProviderContext) => { - try { - const result = await cypressStart(getService, cypress.run, spec); + const result = await cypressStart(getService, cypress.run, spec); - if (result && (result.status === 'failed' || result.totalFailed > 0)) { - process.exit(1); - } - } catch (error) { - console.error('errors: ', error); - process.exit(1); + if (result && (result.status === 'failed' || result.totalFailed > 0)) { + throw new Error(`APM Cypress tests failed`); } }; } diff --git a/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx b/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx index fb1a99db0bf5b..2015bf2228b6c 100644 --- a/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/chart_preview/index.tsx @@ -23,17 +23,21 @@ import { EuiSpacer } from '@elastic/eui'; import React from 'react'; import { Coordinate } from '../../../../typings/timeseries'; import { useTheme } from '../../../hooks/use_theme'; +import { IUiSettingsClient } from '../../../../../../../src/core/public'; +import { getTimeZone } from '../../shared/charts/helper/timezone'; interface ChartPreviewProps { yTickFormat?: TickFormatter; data?: Coordinate[]; threshold: number; + uiSettings?: IUiSettingsClient; } export function ChartPreview({ data = [], yTickFormat, threshold, + uiSettings, }: ChartPreviewProps) { const theme = useTheme(); const thresholdOpacity = 0.3; @@ -67,6 +71,8 @@ export function ChartPreview({ }, ]; + const timeZone = getTimeZone(uiSettings); + return ( <> @@ -99,6 +105,7 @@ export function ChartPreview({ domain={{ max: yMax, min: NaN }} /> ); diff --git a/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx index 8957dfc823e44..fa75fcca579e5 100644 --- a/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/transaction_duration_alert_trigger/index.tsx @@ -139,6 +139,7 @@ export function TransactionDurationAlertTrigger(props: Props) { data={latencyChartPreview} threshold={thresholdMs} yTickFormat={yTickFormat} + uiSettings={services.uiSettings} /> ); diff --git a/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx b/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx index ddddc4bbecbad..a818218cbf3ad 100644 --- a/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/transaction_error_rate_alert_trigger/index.tsx @@ -131,6 +131,7 @@ export function TransactionErrorRateAlertTrigger(props: Props) { data={data?.errorRateChartPreview} yTickFormat={(d: number | null) => asPercent(d, 1)} threshold={thresholdAsPercent} + uiSettings={services.uiSettings} /> ); diff --git a/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.stories.tsx b/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.stories.tsx index 4efc00ef71b91..101923a7678fb 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.stories.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.stories.tsx @@ -19,14 +19,17 @@ export default { component: ErrorDistribution, decorators: [ (Story: ComponentType) => { - const apmPluginContextMock = { - observabilityRuleTypeRegistry: { getFormatter: () => undefined }, - } as unknown as ApmPluginContextValue; - const kibanaContextServices = { uiSettings: { get: () => {} }, }; + const apmPluginContextMock = { + observabilityRuleTypeRegistry: { getFormatter: () => undefined }, + core: { + uiSettings: kibanaContextServices.uiSettings, + }, + } as unknown as ApmPluginContextValue; + return ( diff --git a/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.tsx index 429ad989b9738..6a3157b3c4b7f 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_details/Distribution/index.tsx @@ -32,6 +32,7 @@ import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plug import { LazyAlertsFlyout } from '../../../../../../observability/public'; import { useUrlParams } from '../../../../context/url_params_context/use_url_params'; import { Coordinate } from '../../../../../typings/timeseries'; +import { getTimeZone } from '../../../shared/charts/helper/timezone'; const ALERT_RULE_TYPE_ID: typeof ALERT_RULE_TYPE_ID_TYPED = ALERT_RULE_TYPE_ID_NON_TYPED; @@ -58,6 +59,7 @@ interface Props { } export function ErrorDistribution({ distribution, title, fetchStatus }: Props) { + const { core } = useApmPluginContext(); const theme = useTheme(); const currentPeriod = getCoordinatedBuckets(distribution.currentPeriod); const previousPeriod = getCoordinatedBuckets(distribution.previousPeriod); @@ -103,6 +105,8 @@ export function ErrorDistribution({ distribution, title, fetchStatus }: Props) { undefined ); + const timeZone = getTimeZone(core.uiSettings); + return ( <> @@ -138,6 +142,7 @@ export function ErrorDistribution({ distribution, title, fetchStatus }: Props) { {timeseries.map((serie) => { return ( @@ -150,6 +151,7 @@ export function BreakdownChart({ timeseries.map((serie) => { return ( { let originalTimezone: moment.MomentZone | null; @@ -67,4 +68,22 @@ describe('Timezone helper', () => { ]); }); }); + + describe('getTimeZone', () => { + it('returns local when uiSettings is undefined', () => { + expect(getTimeZone()).toEqual('local'); + }); + + it('returns local when uiSettings returns Browser', () => { + expect( + getTimeZone({ get: () => 'Browser' } as unknown as IUiSettingsClient) + ).toEqual('local'); + }); + it('returns timezone defined on uiSettings', () => { + const timezone = 'America/toronto'; + expect( + getTimeZone({ get: () => timezone } as unknown as IUiSettingsClient) + ).toEqual(timezone); + }); + }); }); diff --git a/x-pack/plugins/apm/public/components/shared/charts/helper/timezone.ts b/x-pack/plugins/apm/public/components/shared/charts/helper/timezone.ts index 539c81c61c3ce..f807d83c8977f 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/helper/timezone.ts +++ b/x-pack/plugins/apm/public/components/shared/charts/helper/timezone.ts @@ -7,6 +7,8 @@ import d3 from 'd3'; import { getTimezoneOffsetInMs } from './get_timezone_offset_in_ms'; +import { IUiSettingsClient } from '../../../../../../../../src/core/public'; +import { UI_SETTINGS } from '../../../../../../../../src/plugins/data/common'; interface Params { domain: [number, number]; @@ -31,3 +33,15 @@ export const getDomainTZ = (min: number, max: number): [number, number] => { ); return [xMinZone, xMaxZone]; }; + +export function getTimeZone(uiSettings?: IUiSettingsClient) { + const kibanaTimeZone = uiSettings?.get<'Browser' | string>( + UI_SETTINGS.DATEFORMAT_TZ + ); + + if (!kibanaTimeZone || kibanaTimeZone === 'Browser') { + return 'local'; + } + + return kibanaTimeZone; +} diff --git a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx index 08e8908d50e7a..bcdfff2678cda 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/timeseries_chart.tsx @@ -19,8 +19,8 @@ import { RectAnnotation, ScaleType, Settings, - YDomainRange, XYBrushEvent, + YDomainRange, } from '@elastic/charts'; import { EuiIcon } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -46,6 +46,7 @@ import { getLatencyChartSelector } from '../../../selectors/latency_chart_select import { unit } from '../../../utils/style'; import { ChartContainer } from './chart_container'; import { getAlertAnnotations } from './helper/get_alert_annotations'; +import { getTimeZone } from './helper/timezone'; import { isTimeseriesEmpty, onBrushEnd } from './helper/helper'; interface Props { @@ -85,7 +86,7 @@ export function TimeseriesChart({ alerts, }: Props) { const history = useHistory(); - const { observabilityRuleTypeRegistry } = useApmPluginContext(); + const { observabilityRuleTypeRegistry, core } = useApmPluginContext(); const { getFormatter } = observabilityRuleTypeRegistry; const { annotations } = useAnnotationsContext(); const { setPointerEvent, chartRef } = useChartPointerEventContext(); @@ -97,6 +98,8 @@ export function TimeseriesChart({ const xValues = timeseries.flatMap(({ data }) => data.map(({ x }) => x)); + const timeZone = getTimeZone(core.uiSettings); + const min = Math.min(...xValues); const max = Math.max(...xValues); @@ -180,6 +183,7 @@ export function TimeseriesChart({ return ( } diff --git a/x-pack/plugins/apm/scripts/test/e2e.js b/x-pack/plugins/apm/scripts/test/e2e.js index 629cdc2498414..b3ce510a8e569 100644 --- a/x-pack/plugins/apm/scripts/test/e2e.js +++ b/x-pack/plugins/apm/scripts/test/e2e.js @@ -12,6 +12,11 @@ const yargs = require('yargs'); const childProcess = require('child_process'); const { argv } = yargs(process.argv.slice(2)) + .option('kibana-install-dir', { + default: '', + type: 'string', + description: 'Path to the Kibana install directory', + }) .option('server', { default: false, type: 'boolean', @@ -30,7 +35,7 @@ const { argv } = yargs(process.argv.slice(2)) }) .help(); -const { server, runner, open } = argv; +const { server, runner, open, kibanaInstallDir } = argv; const e2eDir = path.join(__dirname, '../../ftr_e2e'); @@ -44,6 +49,6 @@ if (server) { const config = open ? './cypress_open.ts' : './cypress_run.ts'; childProcess.execSync( - `node ../../../../scripts/${ftrScript} --config ${config}`, + `node ../../../../scripts/${ftrScript} --config ${config} --kibana-install-dir '${kibanaInstallDir}'`, { cwd: e2eDir, stdio: 'inherit' } ); diff --git a/x-pack/plugins/apm/server/tutorial/index.ts b/x-pack/plugins/apm/server/tutorial/index.ts index a3ad59d842df1..66ff8f5b2c92c 100644 --- a/x-pack/plugins/apm/server/tutorial/index.ts +++ b/x-pack/plugins/apm/server/tutorial/index.ts @@ -22,7 +22,7 @@ import apmDataView from './index_pattern.json'; const apmIntro = i18n.translate('xpack.apm.tutorial.introduction', { defaultMessage: - 'Collect in-depth performance metrics and errors from inside your applications.', + 'Collect performance metrics from your applications with Elastic APM.', }); const moduleName = 'apm'; diff --git a/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot b/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot index 8ca3dc2a94d4e..47c536cd1e2ef 100644 --- a/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot +++ b/x-pack/plugins/canvas/public/components/var_config/__stories__/__snapshots__/var_config.stories.storyshot @@ -13,6 +13,24 @@ exports[`Storyshots components/Variables/VarConfig default 1`] = `
+ + +
+ +
+ - - - - - - Copy POST URL - - - - - - - - - - - +

+ + + Save your work before copying this URL. + + +

+
+
+ +
+ +
+ +
+ + + + @@ -697,6 +721,8 @@ exports[`ScreenCapturePanelContent properly renders a view with "print" layout o - + + - - - - - +

+ + + Save your work before copying this URL. + + +

+ + + +
+ +
+ + + + + + @@ -1007,6 +1055,8 @@ exports[`ScreenCapturePanelContent renders the default view properly 1`] = ` - + + - - - - - +

+ + + Save your work before copying this URL. + + +

+ + + +
+ +
+ + + + + + diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/error_unsaved_work_panel.tsx b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/error_unsaved_work_panel.tsx new file mode 100644 index 0000000000000..348c6d42cddb8 --- /dev/null +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/error_unsaved_work_panel.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 { i18n } from '@kbn/i18n'; +import type { FunctionComponent } from 'react'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCallOut, EuiText, EuiSpacer } from '@elastic/eui'; + +const i18nTexts = { + title: i18n.translate('xpack.reporting.panelContent.unsavedStateErrorTitle', { + defaultMessage: 'Unsaved work', + }), +}; + +export const ErrorUnsavedWorkPanel: FunctionComponent = () => { + return ( + + +

+ +

+
+ +
+ ); +}; diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/error_url_too_long_panel.tsx b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/error_url_too_long_panel.tsx new file mode 100644 index 0000000000000..9c925fe03fee2 --- /dev/null +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/error_url_too_long_panel.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FunctionComponent } from 'react'; +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiCallOut, EuiText } from '@elastic/eui'; + +interface Props { + isUnsaved?: boolean; +} + +const i18nTexts = { + title: i18n.translate('xpack.reporting.panelContent.unsavedStateAndExceedsMaxLengthTitle', { + defaultMessage: 'URL too long', + }), +}; + +export const ErrorUrlTooLongPanel: FunctionComponent = ({ isUnsaved }) => ( + + +

+ {isUnsaved ? ( + + + + ) : ( + // Reaching this state is essentially just an error and should result in a user contacting us. + + + + )} +

+
+
+); diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/index.ts b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/index.ts new file mode 100644 index 0000000000000..b7da9d6d12573 --- /dev/null +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/components/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { ErrorUnsavedWorkPanel } from './error_unsaved_work_panel'; +export { ErrorUrlTooLongPanel } from './error_url_too_long_panel'; diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/constants.ts b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/constants.ts new file mode 100644 index 0000000000000..fe7faf48d6106 --- /dev/null +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/constants.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. + */ + +/** + * Based on {@link URL_MAX_LENGTH} exported from core/public. + */ +const CHROMIUM_MAX_URL_LENGTH = 25 * 1000; + +export const getMaxUrlLength = () => CHROMIUM_MAX_URL_LENGTH; diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/index.ts b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/index.ts new file mode 100644 index 0000000000000..843a0b6747e4c --- /dev/null +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/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 { ReportingPanelContent, Props, ReportingPanelProps } from './reporting_panel_content'; diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content.test.tsx b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.test.tsx similarity index 67% rename from x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content.test.tsx rename to x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.test.tsx index 6ad894bf3ac2f..e9dd584e51f82 100644 --- a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content.test.tsx +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.test.tsx @@ -12,8 +12,14 @@ import { notificationServiceMock, uiSettingsServiceMock, } from 'src/core/public/mocks'; -import { ReportingAPIClient } from '../lib/reporting_api_client'; -import { ReportingPanelContent, ReportingPanelProps as Props } from './reporting_panel_content'; +import { ReportingAPIClient } from '../../lib/reporting_api_client'; +import { ReportingPanelContent, ReportingPanelProps as Props } from '.'; +import { ErrorUnsavedWorkPanel } from './components'; + +jest.mock('./constants', () => ({ + getMaxUrlLength: jest.fn(() => 9999999), +})); +import * as constants from './constants'; describe('ReportingPanelContent', () => { const props: Partial = { @@ -83,7 +89,7 @@ describe('ReportingPanelContent', () => { }); it('changing the layout triggers refreshing the state with the latest job params', () => { - const wrapper = mountComponent({ requiresSavedState: false }); + const wrapper = mountComponent({ requiresSavedState: false, isDirty: false }); wrapper.update(); expect(wrapper.find('EuiCopy').prop('textToCopy')).toMatchInlineSnapshot( `"http://localhost/api/reporting/generate/test?jobParams=%28appState%3Avery_cool_app_state_X%2CbrowserTimezone%3AMars%2CobjectType%3Anoice_object%2Ctitle%3Aultimate_title%2Cversion%3A%277.15.0-test%27%29"` @@ -97,4 +103,35 @@ describe('ReportingPanelContent', () => { ); }); }); + + describe('copy post URL', () => { + it('shows the copy button without warnings', () => { + const wrapper = mountComponent({ requiresSavedState: false, isDirty: false }); + wrapper.update(); + expect(wrapper.exists('EuiCopy')).toBe(true); + expect(wrapper.exists(ErrorUnsavedWorkPanel)).toBe(false); + }); + + it('does not show the copy button when there is unsaved state', () => { + const wrapper = mountComponent({ requiresSavedState: false, isDirty: true }); + wrapper.update(); + expect(wrapper.exists('EuiCopy')).toBe(false); + expect(wrapper.exists(ErrorUnsavedWorkPanel)).toBe(true); + }); + + it('does not show the copy button when the URL is too long', () => { + (constants.getMaxUrlLength as jest.Mock).mockReturnValue(1); + const wrapper = mountComponent({ requiresSavedState: false, isDirty: true }); + wrapper.update(); + + expect(wrapper.exists('EuiCopy')).toBe(false); + expect(wrapper.exists('[data-test-subj="urlTooLongTrySavingMessage"]')).toBe(true); + expect(wrapper.exists('[data-test-subj="urlTooLongErrorMessage"]')).toBe(false); + + wrapper.setProps({ isDirty: false }); + expect(wrapper.exists('EuiCopy')).toBe(false); + expect(wrapper.exists('[data-test-subj="urlTooLongTrySavingMessage"]')).toBe(false); + expect(wrapper.exists('[data-test-subj="urlTooLongErrorMessage"]')).toBe(true); + }); + }); }); diff --git a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content.tsx b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx similarity index 84% rename from x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content.tsx rename to x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx index 6ed6f2d0c5f49..4e05dc5637bfb 100644 --- a/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content.tsx +++ b/x-pack/plugins/reporting/public/share_context_menu/reporting_panel_content/reporting_panel_content.tsx @@ -20,16 +20,18 @@ import { FormattedMessage, InjectedIntl, injectI18n } from '@kbn/i18n/react'; import React, { Component, ReactElement } from 'react'; import { IUiSettingsClient, ToastsSetup } from 'src/core/public'; import url from 'url'; -import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; +import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public'; import { CSV_REPORT_TYPE, PDF_REPORT_TYPE, PDF_REPORT_TYPE_V2, PNG_REPORT_TYPE, PNG_REPORT_TYPE_V2, -} from '../../common/constants'; -import { BaseParams } from '../../common/types'; -import { ReportingAPIClient } from '../lib/reporting_api_client'; +} from '../../../common/constants'; +import { BaseParams } from '../../../common/types'; +import { ReportingAPIClient } from '../../lib/reporting_api_client'; +import { ErrorUnsavedWorkPanel, ErrorUrlTooLongPanel } from './components'; +import { getMaxUrlLength } from './constants'; export interface ReportingPanelProps { apiClient: ReportingAPIClient; @@ -108,11 +110,39 @@ class ReportingPanelContentUi extends Component { return this.props.objectId === undefined || this.props.objectId === ''; }; + private renderCopyURLButton({ + isUnsaved, + exceedsMaxLength, + }: { + isUnsaved: boolean; + exceedsMaxLength: boolean; + }) { + if (isUnsaved) { + if (exceedsMaxLength) { + return ; + } + return ; + } else if (exceedsMaxLength) { + return ; + } + return ( + + {(copy) => ( + + + + )} + + ); + } + public render() { - if ( - this.props.requiresSavedState && - (this.isNotSaved() || this.props.isDirty || this.state.isStale) - ) { + const isUnsaved: boolean = this.isNotSaved() || this.props.isDirty || this.state.isStale; + + if (this.props.requiresSavedState && isUnsaved) { return ( { ); } + const exceedsMaxLength = this.state.absoluteUrl.length >= getMaxUrlLength(); + return ( @@ -172,17 +204,7 @@ class ReportingPanelContentUi extends Component {

- - - {(copy) => ( - - - - )} - + {this.renderCopyURLButton({ isUnsaved, exceedsMaxLength })}
); diff --git a/x-pack/plugins/reporting/public/share_context_menu/screen_capture_panel_content.test.tsx b/x-pack/plugins/reporting/public/share_context_menu/screen_capture_panel_content.test.tsx index b64052228eb41..f37aaea114cfa 100644 --- a/x-pack/plugins/reporting/public/share_context_menu/screen_capture_panel_content.test.tsx +++ b/x-pack/plugins/reporting/public/share_context_menu/screen_capture_panel_content.test.tsx @@ -85,8 +85,10 @@ test('ScreenCapturePanelContent decorated job params are visible in the POST URL const component = mount( -> = function createJobFactoryFn(_reporting, logger) { +> = function createJobFactoryFn(reporting, logger) { return async function createJob(jobParams, context) { logger.warn( - `The "/generate/csv" endpoint is deprecated and will be removed in Kibana 8.0. Please recreate the POST URL used to automate this CSV export.` + `The "/generate/csv" endpoint is deprecated. Please recreate the POST URL used to automate this CSV export.` ); - const savedObjectsClient = context.core.savedObjects.client; - const indexPatternSavedObject = (await savedObjectsClient.get( - 'index-pattern', - jobParams.indexPatternId - )) as unknown as IndexPatternSavedObjectDeprecatedCSV; - return { isDeprecated: true, - indexPatternSavedObject, ...jobParams, }; }; diff --git a/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts b/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts index cb103812c7f2a..57f030df66e0e 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts @@ -12,6 +12,7 @@ import { ElasticsearchClient, IUiSettingsClient } from 'kibana/server'; import moment from 'moment'; import Puid from 'puid'; import sinon from 'sinon'; +import type { DataView, DataViewsService } from 'src/plugins/data/common'; import { ReportingConfig, ReportingCore } from '../../'; import { FieldFormatsRegistry, @@ -56,6 +57,8 @@ describe('CSV Execute Job', function () { let encryptedHeaders: any; let configGetStub: any; + let mockDataView: jest.Mocked; + let mockDataViewsService: jest.Mocked; let mockEsClient: DeeplyMockedKeys; let mockReportingConfig: ReportingConfig; let mockReportingCore: ReportingCore; @@ -81,10 +84,15 @@ describe('CSV Execute Job', function () { configGetStub.withArgs('csv', 'maxSizeBytes').returns(1024 * 1000); // 1mB configGetStub.withArgs('csv', 'scroll').returns({}); mockReportingConfig = { get: configGetStub, kbnConfig: { get: configGetStub } }; + mockDataView = { fieldFormatMap: {}, fields: [] } as unknown as typeof mockDataView; + mockDataViewsService = { + get: jest.fn().mockResolvedValue(mockDataView), + } as unknown as typeof mockDataViewsService; mockReportingCore = await createMockReportingCore(createMockConfigSchema()); mockReportingCore.getUiSettingsServiceFactory = () => Promise.resolve(mockUiSettingsClient as unknown as IUiSettingsClient); + mockReportingCore.getDataViewsService = jest.fn().mockResolvedValue(mockDataViewsService); mockReportingCore.setConfig(mockReportingConfig); mockEsClient = (await mockReportingCore.getEsClient()).asScoped({} as any) @@ -931,16 +939,14 @@ describe('CSV Execute Job', function () { fields: ['one', 'two'], conflictedTypesFields: [], searchRequest: { index: null, body: null }, - indexPatternSavedObject: { - id: 'logstash-*', - type: 'index-pattern', - attributes: { - title: 'logstash-*', - fields: '[{"name":"one","type":"string"}, {"name":"two","type":"string"}]', - fieldFormatMap: '{"one":{"id":"string","params":{"transform": "upper"}}}', - }, - }, + indexPatternId: 'something', }); + + mockDataView.fieldFormatMap = { one: { id: 'string', params: { transform: 'upper' } } }; + mockDataView.fields = [ + { name: 'one', type: 'string' }, + { name: 'two', type: 'string' }, + ] as typeof mockDataView.fields; await runTask('job123', jobParams, cancellationToken, stream); expect(content).not.toBe(null); const lines = content!.split('\n'); diff --git a/x-pack/plugins/reporting/server/export_types/csv/execute_job.ts b/x-pack/plugins/reporting/server/export_types/csv/execute_job.ts index 9ce0bb6d6de00..a007591821988 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/execute_job.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/execute_job.ts @@ -25,12 +25,14 @@ export const runTaskFnFactory: RunTaskFnFactory = {}; configMock[FORMATS_UI_SETTINGS.FORMAT_DEFAULT_TYPE_MAP] = { number: { id: 'number', params: {} }, @@ -39,13 +38,9 @@ describe('field format map', function () { const fieldFormatsRegistry = new FieldFormatsRegistry(); fieldFormatsRegistry.init(getConfig, {}, [BytesFormat, NumberFormat]); - const formatMap = fieldFormatMapFactory( - indexPatternSavedObject, - fieldFormatsRegistry, - mockTimezone - ); + const formatMap = fieldFormatMapFactory(dataView, fieldFormatsRegistry, mockTimezone); - it('should build field format map with entry per index pattern field', function () { + it('should build field format map with entry per data view field', function () { expect(formatMap.has('field1')).to.be(true); expect(formatMap.has('field2')).to.be(true); expect(formatMap.has('field_not_in_index')).to.be(false); diff --git a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/field_format_map.ts b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/field_format_map.ts index 9d094f4308ed7..38a6cac337861 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/field_format_map.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/field_format_map.ts @@ -6,22 +6,21 @@ */ import _ from 'lodash'; +import type { DataView, KBN_FIELD_TYPES } from 'src/plugins/data/common'; import { FieldFormat, IFieldFormatsRegistry, FieldFormatConfig, } from 'src/plugins/field_formats/common'; -import { IndexPatternSavedObjectDeprecatedCSV } from '../types'; - /** * Create a map of FieldFormat instances for index pattern fields * - * @param {Object} indexPatternSavedObject + * @param {DataView} dataView * @param {FieldFormatsService} fieldFormats * @return {Map} key: field name, value: FieldFormat instance */ export function fieldFormatMapFactory( - indexPatternSavedObject: IndexPatternSavedObjectDeprecatedCSV, + dataView: DataView | undefined, fieldFormatsRegistry: IFieldFormatsRegistry, timezone: string | undefined ) { @@ -32,10 +31,9 @@ export function fieldFormatMapFactory( const serverDateParams = { timezone }; // Add FieldFormat instances for fields with custom formatters - if (_.has(indexPatternSavedObject, 'attributes.fieldFormatMap')) { - const fieldFormatMap = JSON.parse(indexPatternSavedObject.attributes.fieldFormatMap); - Object.keys(fieldFormatMap).forEach((fieldName) => { - const formatConfig: FieldFormatConfig = fieldFormatMap[fieldName]; + if (dataView) { + Object.keys(dataView.fieldFormatMap).forEach((fieldName) => { + const formatConfig: FieldFormatConfig = dataView.fieldFormatMap[fieldName]; const formatParams = { ...formatConfig.params, ...serverDateParams, @@ -48,12 +46,11 @@ export function fieldFormatMapFactory( } // Add default FieldFormat instances for non-custom formatted fields - const indexFields = JSON.parse(_.get(indexPatternSavedObject, 'attributes.fields', '[]')); - indexFields.forEach((field: any) => { + dataView?.fields.forEach((field) => { if (!formatsMap.has(field.name)) { formatsMap.set( field.name, - fieldFormatsRegistry.getDefaultInstance(field.type, [], serverDateParams) + fieldFormatsRegistry.getDefaultInstance(field.type as KBN_FIELD_TYPES, [], serverDateParams) ); } }); diff --git a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts index 61f404ed2fb02..2573ba14f22a5 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts @@ -8,6 +8,7 @@ import { Writable } from 'stream'; import { i18n } from '@kbn/i18n'; import { ElasticsearchClient, IUiSettingsClient } from 'src/core/server'; +import type { DataView, DataViewsService } from 'src/plugins/data/common'; import { ReportingConfig } from '../../../'; import { createEscapeValue } from '../../../../../../../src/plugins/data/common'; import { CancellationToken } from '../../../../../../plugins/reporting/common'; @@ -16,10 +17,7 @@ import { byteSizeValueToNumber } from '../../../../common/schema_utils'; import { LevelLogger } from '../../../lib'; import { getFieldFormats } from '../../../services'; import { MaxSizeStringBuilder } from '../../csv_searchsource/generate_csv/max_size_string_builder'; -import { - IndexPatternSavedObjectDeprecatedCSV, - SavedSearchGeneratorResultDeprecatedCSV, -} from '../types'; +import { SavedSearchGeneratorResultDeprecatedCSV } from '../types'; import { checkIfRowsHaveFormulas } from './check_cells_for_formulas'; import { fieldFormatMapFactory } from './field_format_map'; import { createFlattenHit } from './flatten_hit'; @@ -44,7 +42,7 @@ interface SearchRequest { export interface GenerateCsvParams { browserTimezone?: string; searchRequest: SearchRequest; - indexPatternSavedObject: IndexPatternSavedObjectDeprecatedCSV; + indexPatternId: string; fields: string[]; metaFields: string[]; conflictedTypesFields: string[]; @@ -58,6 +56,7 @@ export function createGenerateCsv(logger: LevelLogger) { config: ReportingConfig, uiSettingsClient: IUiSettingsClient, elasticsearchClient: ElasticsearchClient, + dataViews: DataViewsService, cancellationToken: CancellationToken, stream: Writable ): Promise { @@ -91,11 +90,17 @@ export function createGenerateCsv(logger: LevelLogger) { let csvContainsFormulas = false; const flattenHit = createFlattenHit(fields, metaFields, conflictedTypesFields); + let dataView: DataView | undefined; + + try { + dataView = await dataViews.get(job.indexPatternId); + } catch (error) { + logger.error(`Failed to get the data view "${job.indexPatternId}": ${error}`); + } + const formatsMap = await getFieldFormats() .fieldFormatServiceFactory(uiSettingsClient) - .then((fieldFormats) => - fieldFormatMapFactory(job.indexPatternSavedObject, fieldFormats, settings.timezone) - ); + .then((fieldFormats) => fieldFormatMapFactory(dataView, fieldFormats, settings.timezone)); const formatCsvValues = createFormatCsvValues( escapeValue, diff --git a/x-pack/plugins/reporting/server/export_types/csv/types.d.ts b/x-pack/plugins/reporting/server/export_types/csv/types.d.ts index 0263e82040f17..fff6f0bcf9538 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/types.d.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/types.d.ts @@ -5,20 +5,11 @@ * 2.0. */ +import type { FieldSpec } from 'src/plugins/data/common'; import { BaseParams, BasePayload } from '../../types'; export type RawValue = string | object | null | undefined; -export interface IndexPatternSavedObjectDeprecatedCSV { - title: string; - timeFieldName: string; - fields?: any[]; - attributes: { - fields: string; - fieldFormatMap: string; - }; -} - interface BaseParamsDeprecatedCSV { searchRequest: SearchRequestDeprecatedCSV; fields: string[]; @@ -31,10 +22,9 @@ export type JobParamsDeprecatedCSV = BaseParamsDeprecatedCSV & indexPatternId: string; }; -// CSV create job method converts indexPatternID to indexPatternSavedObject export type TaskPayloadDeprecatedCSV = BaseParamsDeprecatedCSV & BasePayload & { - indexPatternSavedObject: IndexPatternSavedObjectDeprecatedCSV; + indexPatternId: string; }; export interface SearchRequestDeprecatedCSV { diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.test.ts b/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.test.ts index e2c3ffdd68818..0166e82744e5d 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.test.ts +++ b/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.test.ts @@ -48,11 +48,11 @@ test(`passes title through if provided`, async () => { test(`gets the title from the savedObject`, async () => { const createJobMock = jest.fn(); const title = 'savedTitle'; - mockRequestHandlerContext.core.savedObjects.client.get.mockResolvedValue( - createMockSavedObject({ + mockRequestHandlerContext.core.savedObjects.client.resolve.mockResolvedValue({ + saved_object: createMockSavedObject({ attributes: { title }, - }) - ); + }), + } as any); await compatibilityShim(createJobMock, mockLogger)( createMockJobParams({ objectType: 'search', savedObjectId: 'abc' }), @@ -72,9 +72,9 @@ test(`gets the title from the savedObject`, async () => { test(`passes the objectType and savedObjectId to the savedObjectsClient`, async () => { const createJobMock = jest.fn(); const context = mockRequestHandlerContext; - context.core.savedObjects.client.get.mockResolvedValue( - createMockSavedObject({ attributes: { title: '' } }) - ); + context.core.savedObjects.client.resolve.mockResolvedValue({ + saved_object: createMockSavedObject({ attributes: { title: '' } }), + } as any); const objectType = 'search'; const savedObjectId = 'abc'; @@ -92,10 +92,8 @@ test(`passes the objectType and savedObjectId to the savedObjectsClient`, async ); expect(mockLogger.error.mock.calls.length).toBe(0); - const getMock = context.core.savedObjects.client.get.mock; - expect(getMock.calls.length).toBe(1); - expect(getMock.calls[0][0]).toBe(objectType); - expect(getMock.calls[0][1]).toBe(savedObjectId); + expect(context.core.savedObjects.client.resolve).toHaveBeenCalledTimes(1); + expect(context.core.savedObjects.client.resolve).toHaveBeenCalledWith(objectType, savedObjectId); }); test(`logs no warnings when title and relativeUrls is passed`, async () => { diff --git a/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.ts b/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.ts index 1d222d61eb07d..d5e78bcf68f4b 100644 --- a/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.ts +++ b/x-pack/plugins/reporting/server/export_types/printable_pdf/create_job/compatibility_shim.ts @@ -22,7 +22,10 @@ const getSavedObjectTitle = async ( savedObjectId: string, savedObjectsClient: SavedObjectsClientContract ) => { - const savedObject = await savedObjectsClient.get<{ title: string }>(objectType, savedObjectId); + const { saved_object: savedObject } = await savedObjectsClient.resolve<{ title: string }>( + objectType, + savedObjectId + ); return savedObject.attributes.title; }; diff --git a/x-pack/plugins/reporting/server/routes/lib/request_handler.test.ts b/x-pack/plugins/reporting/server/routes/lib/request_handler.test.ts index 622097f8dbd32..5900a151f92da 100644 --- a/x-pack/plugins/reporting/server/routes/lib/request_handler.test.ts +++ b/x-pack/plugins/reporting/server/routes/lib/request_handler.test.ts @@ -71,6 +71,7 @@ describe('Handle request to generate', () => { (report) => new Report({ ...report, _index: '.reporting-foo-index-234' }) ), } as unknown as ReportingStore); + mockRequest = getMockRequest(); mockResponseFactory = getMockResponseFactory(); @@ -80,6 +81,7 @@ describe('Handle request to generate', () => { mockContext = getMockContext(); mockContext.reporting = {} as ReportingSetup; + requestHandler = new RequestHandler( reportingCore, { username: 'testymcgee' }, @@ -195,7 +197,6 @@ describe('Handle request to generate', () => { "output": Object {}, "payload": Object { "browserTimezone": "UTC", - "indexPatternSavedObject": undefined, "isDeprecated": true, "layout": Object { "id": "preserve_layout", diff --git a/x-pack/plugins/rollup/server/plugin.ts b/x-pack/plugins/rollup/server/plugin.ts index 5c15ec0263dc3..88da9a3eb87b1 100644 --- a/x-pack/plugins/rollup/server/plugin.ts +++ b/x-pack/plugins/rollup/server/plugin.ts @@ -5,15 +5,7 @@ * 2.0. */ -import { Observable } from 'rxjs'; -import { first } from 'rxjs/operators'; -import { - CoreSetup, - Plugin, - Logger, - PluginInitializerContext, - SharedGlobalConfig, -} from 'src/core/server'; +import { CoreSetup, Plugin, Logger, PluginInitializerContext } from 'src/core/server'; import { i18n } from '@kbn/i18n'; import { schema } from '@kbn/config-schema'; @@ -30,17 +22,15 @@ import { getCapabilitiesForRollupIndices } from '../../../../src/plugins/data/se export class RollupPlugin implements Plugin { private readonly logger: Logger; - private readonly globalConfig$: Observable; private readonly license: License; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); - this.globalConfig$ = initializerContext.config.legacy.globalConfig$; this.license = new License(); } public setup( - { http, uiSettings, getStartServices }: CoreSetup, + { http, uiSettings, savedObjects, getStartServices }: CoreSetup, { features, licensing, indexManagement, visTypeTimeseries, usageCollection }: Dependencies ) { this.license.setup( @@ -101,15 +91,11 @@ export class RollupPlugin implements Plugin { }); if (usageCollection) { - this.globalConfig$ - .pipe(first()) - .toPromise() - .then((globalConfig) => { - registerRollupUsageCollector(usageCollection, globalConfig.kibana.index); - }) - .catch((e: any) => { - this.logger.warn(`Registering Rollup collector failed: ${e}`); - }); + try { + registerRollupUsageCollector(usageCollection, savedObjects.getKibanaIndex()); + } catch (e) { + this.logger.warn(`Registering Rollup collector failed: ${e}`); + } } if (indexManagement && indexManagement.indexDataEnricher) { diff --git a/x-pack/plugins/rule_registry/server/config.ts b/x-pack/plugins/rule_registry/server/config.ts index 078498864f8e8..983a750452410 100644 --- a/x-pack/plugins/rule_registry/server/config.ts +++ b/x-pack/plugins/rule_registry/server/config.ts @@ -12,7 +12,7 @@ export const config: PluginConfigDescriptor = { deprecations: ({ deprecate, unused }) => [unused('unsafe.indexUpgrade.enabled')], schema: schema.object({ write: schema.object({ - enabled: schema.boolean({ defaultValue: false }), + enabled: schema.boolean({ defaultValue: true }), }), unsafe: schema.object({ legacyMultiTenancy: schema.object({ diff --git a/x-pack/plugins/rule_registry/server/plugin.ts b/x-pack/plugins/rule_registry/server/plugin.ts index 334216ce41361..2e27ed7ba03c2 100644 --- a/x-pack/plugins/rule_registry/server/plugin.ts +++ b/x-pack/plugins/rule_registry/server/plugin.ts @@ -13,7 +13,6 @@ import { KibanaRequest, CoreStart, IContextProvider, - SharedGlobalConfig, } from 'src/core/server'; import { PluginStartContract as AlertingStart } from '../../alerting/server'; @@ -53,7 +52,6 @@ export class RuleRegistryPlugin > { private readonly config: RuleRegistryPluginConfig; - private readonly legacyConfig: SharedGlobalConfig; private readonly logger: Logger; private readonly kibanaVersion: string; private readonly alertsClientFactory: AlertsClientFactory; @@ -62,8 +60,6 @@ export class RuleRegistryPlugin constructor(initContext: PluginInitializerContext) { this.config = initContext.config.get(); - // TODO: Can be removed in 8.0.0. Exists to work around multi-tenancy users. - this.legacyConfig = initContext.config.legacy.get(); this.logger = initContext.logger.get(); this.kibanaVersion = initContext.env.packageInfo.version; this.ruleDataService = null; @@ -85,25 +81,10 @@ export class RuleRegistryPlugin this.security = plugins.security; - const isWriteEnabled = (config: RuleRegistryPluginConfig, legacyConfig: SharedGlobalConfig) => { - const hasEnabledWrite = config.write.enabled; - const hasSetCustomKibanaIndex = legacyConfig.kibana.index !== '.kibana'; - const hasSetUnsafeAccess = config.unsafe.legacyMultiTenancy.enabled; - - if (!hasEnabledWrite) return false; - - // Not using legacy multi-tenancy - if (!hasSetCustomKibanaIndex) { - return hasEnabledWrite; - } else { - return hasSetUnsafeAccess; - } - }; - this.ruleDataService = new RuleDataService({ logger, kibanaVersion, - isWriteEnabled: isWriteEnabled(this.config, this.legacyConfig), + isWriteEnabled: this.config.write.enabled, getClusterClient: async () => { const deps = await startDependencies; return deps.core.elasticsearch.client.asInternalUser; diff --git a/x-pack/plugins/saved_objects_tagging/server/index.ts b/x-pack/plugins/saved_objects_tagging/server/index.ts index f2809bd411fa6..e45ddbe5d07c8 100644 --- a/x-pack/plugins/saved_objects_tagging/server/index.ts +++ b/x-pack/plugins/saved_objects_tagging/server/index.ts @@ -11,4 +11,4 @@ import { SavedObjectTaggingPlugin } from './plugin'; export { config } from './config'; export const plugin = (initializerContext: PluginInitializerContext) => - new SavedObjectTaggingPlugin(initializerContext); + new SavedObjectTaggingPlugin(); diff --git a/x-pack/plugins/saved_objects_tagging/server/plugin.test.ts b/x-pack/plugins/saved_objects_tagging/server/plugin.test.ts index fe053bdaa48cd..5b514ff4bdd5b 100644 --- a/x-pack/plugins/saved_objects_tagging/server/plugin.test.ts +++ b/x-pack/plugins/saved_objects_tagging/server/plugin.test.ts @@ -19,7 +19,7 @@ describe('SavedObjectTaggingPlugin', () => { let usageCollectionSetup: ReturnType; beforeEach(() => { - plugin = new SavedObjectTaggingPlugin(coreMock.createPluginInitializerContext()); + plugin = new SavedObjectTaggingPlugin(); featuresPluginSetup = featuresPluginMock.createSetup(); usageCollectionSetup = usageCollectionPluginMock.createSetupContract(); // `usageCollection` 'mocked' implementation use the real `CollectorSet` implementation diff --git a/x-pack/plugins/saved_objects_tagging/server/plugin.ts b/x-pack/plugins/saved_objects_tagging/server/plugin.ts index c6bfb0f3cd390..6c5cd66595f7c 100644 --- a/x-pack/plugins/saved_objects_tagging/server/plugin.ts +++ b/x-pack/plugins/saved_objects_tagging/server/plugin.ts @@ -5,14 +5,7 @@ * 2.0. */ -import { Observable } from 'rxjs'; -import { - CoreSetup, - CoreStart, - PluginInitializerContext, - Plugin, - SharedGlobalConfig, -} from 'src/core/server'; +import { CoreSetup, CoreStart, Plugin } from 'src/core/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { SecurityPluginSetup } from '../../security/server'; @@ -30,12 +23,6 @@ interface SetupDeps { } export class SavedObjectTaggingPlugin implements Plugin<{}, {}, SetupDeps, {}> { - private readonly legacyConfig$: Observable; - - constructor(context: PluginInitializerContext) { - this.legacyConfig$ = context.config.legacy.globalConfig$; - } - public setup( { savedObjects, http }: CoreSetup, { features, usageCollection, security }: SetupDeps @@ -58,7 +45,7 @@ export class SavedObjectTaggingPlugin implements Plugin<{}, {}, SetupDeps, {}> { usageCollection.registerCollector( createTagUsageCollector({ usageCollection, - legacyConfig$: this.legacyConfig$, + kibanaIndex: savedObjects.getKibanaIndex(), }) ); } diff --git a/x-pack/plugins/saved_objects_tagging/server/usage/tag_usage_collector.ts b/x-pack/plugins/saved_objects_tagging/server/usage/tag_usage_collector.ts index 0e1f29124df9c..3362965044bfd 100644 --- a/x-pack/plugins/saved_objects_tagging/server/usage/tag_usage_collector.ts +++ b/x-pack/plugins/saved_objects_tagging/server/usage/tag_usage_collector.ts @@ -5,9 +5,6 @@ * 2.0. */ -import { Observable } from 'rxjs'; -import { take } from 'rxjs/operators'; -import { SharedGlobalConfig } from 'src/core/server'; import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/server'; import { TaggingUsageData } from './types'; import { fetchTagUsageData } from './fetch_tag_usage_data'; @@ -15,18 +12,17 @@ import { tagUsageCollectorSchema } from './schema'; export const createTagUsageCollector = ({ usageCollection, - legacyConfig$, + kibanaIndex, }: { usageCollection: UsageCollectionSetup; - legacyConfig$: Observable; + kibanaIndex: string; }) => { return usageCollection.makeUsageCollector({ type: 'saved_objects_tagging', isReady: () => true, schema: tagUsageCollectorSchema, - fetch: async ({ esClient }) => { - const { kibana } = await legacyConfig$.pipe(take(1)).toPromise(); - return fetchTagUsageData({ esClient, kibanaIndex: kibana.index }); + fetch: ({ esClient }) => { + return fetchTagUsageData({ esClient, kibanaIndex }); }, }); }; diff --git a/x-pack/plugins/security/server/config.test.ts b/x-pack/plugins/security/server/config.test.ts index 4034a7a79e6dd..ababf435af3c9 100644 --- a/x-pack/plugins/security/server/config.test.ts +++ b/x-pack/plugins/security/server/config.test.ts @@ -56,7 +56,6 @@ describe('config schema', () => { "selector": Object {}, }, "cookieName": "sid", - "enabled": true, "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "loginAssistanceMessage": "", "public": Object {}, @@ -110,7 +109,6 @@ describe('config schema', () => { "selector": Object {}, }, "cookieName": "sid", - "enabled": true, "encryptionKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "loginAssistanceMessage": "", "public": Object {}, @@ -164,7 +162,6 @@ describe('config schema', () => { "selector": Object {}, }, "cookieName": "sid", - "enabled": true, "loginAssistanceMessage": "", "public": Object {}, "secureCookies": false, diff --git a/x-pack/plugins/security/server/config.ts b/x-pack/plugins/security/server/config.ts index 23a1fd2efa382..a9e22448e1725 100644 --- a/x-pack/plugins/security/server/config.ts +++ b/x-pack/plugins/security/server/config.ts @@ -198,7 +198,6 @@ const providersConfigSchema = schema.object( ); export const ConfigSchema = schema.object({ - enabled: schema.boolean({ defaultValue: true }), loginAssistanceMessage: schema.string({ defaultValue: '' }), showInsecureClusterWarning: schema.boolean({ defaultValue: true }), loginHelp: schema.maybe(schema.string()), diff --git a/x-pack/plugins/security/server/config_deprecations.test.ts b/x-pack/plugins/security/server/config_deprecations.test.ts index a629b6d73a682..3c674de97ad8e 100644 --- a/x-pack/plugins/security/server/config_deprecations.test.ts +++ b/x-pack/plugins/security/server/config_deprecations.test.ts @@ -357,34 +357,4 @@ describe('Config Deprecations', () => { ] `); }); - - it('warns when the security plugin is disabled', () => { - const config = { - xpack: { - security: { - enabled: false, - }, - }, - }; - const { messages, migrated } = applyConfigDeprecations(cloneDeep(config)); - expect(migrated).toEqual(config); - expect(messages).toMatchInlineSnapshot(` - Array [ - "Disabling the security plugin \\"xpack.security.enabled\\" will only be supported by disable security in Elasticsearch.", - ] - `); - }); - - it('does not warn when the security plugin is enabled', () => { - const config = { - xpack: { - security: { - enabled: true, - }, - }, - }; - const { messages, migrated } = applyConfigDeprecations(cloneDeep(config)); - expect(migrated).toEqual(config); - expect(messages).toHaveLength(0); - }); }); diff --git a/x-pack/plugins/security/server/config_deprecations.ts b/x-pack/plugins/security/server/config_deprecations.ts index 0c76840819b3d..055818a159a79 100644 --- a/x-pack/plugins/security/server/config_deprecations.ts +++ b/x-pack/plugins/security/server/config_deprecations.ts @@ -157,28 +157,4 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({ }); } }, - (settings, fromPath, addDeprecation) => { - if (settings?.xpack?.security?.enabled === false) { - addDeprecation({ - configPath: 'xpack.security.enabled', - title: i18n.translate('xpack.security.deprecations.enabledTitle', { - defaultMessage: 'Disabling the security plugin "xpack.security.enabled" is deprecated', - }), - message: i18n.translate('xpack.security.deprecations.enabledMessage', { - defaultMessage: - 'Disabling the security plugin "xpack.security.enabled" will only be supported by disable security in Elasticsearch.', - }), - correctiveActions: { - manualSteps: [ - i18n.translate('xpack.security.deprecations.enabled.manualStepOneMessage', { - defaultMessage: `Remove "xpack.security.enabled" from your Kibana configuration.`, - }), - i18n.translate('xpack.security.deprecations.enabled.manualStepTwoMessage', { - defaultMessage: `To turn off security features, disable them in Elasticsearch instead.`, - }), - ], - }, - }); - } - }, ]; diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index 1e42d10b205aa..0ebdae44c865c 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -6,7 +6,6 @@ */ import type { Subscription } from 'rxjs'; -import { combineLatest } from 'rxjs'; import { map } from 'rxjs/operators'; import type { TypeOf } from '@kbn/config-schema'; @@ -203,6 +202,7 @@ export class SecurityPlugin core: CoreSetup, { features, licensing, taskManager, usageCollection, spaces }: PluginSetupDependencies ) { + this.kibanaIndexName = core.savedObjects.getKibanaIndex(); const config$ = this.initializerContext.config.create>().pipe( map((rawConfig) => createConfig(rawConfig, this.initializerContext.logger.get('config'), { @@ -210,12 +210,8 @@ export class SecurityPlugin }) ) ); - this.configSubscription = combineLatest([ - config$, - this.initializerContext.config.legacy.globalConfig$, - ]).subscribe(([config, { kibana }]) => { + this.configSubscription = config$.subscribe((config) => { this.config = config; - this.kibanaIndexName = kibana.index; }); const config = this.getConfig(); diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx index 352fc95447822..591cba6b19381 100644 --- a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.test.tsx @@ -7,6 +7,9 @@ import React from 'react'; import { mount } from 'enzyme'; +import { waitFor } from '@testing-library/react'; + +import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; import { SourcererScopeName } from '../../store/sourcerer/model'; import { Sourcerer } from './index'; import { DEFAULT_INDEX_PATTERN } from '../../../../common/constants'; @@ -19,8 +22,6 @@ import { TestProviders, } from '../../mock'; import { createStore, State } from '../../store'; -import { EuiComboBox, EuiComboBoxOptionOption } from '@elastic/eui'; -import { waitFor } from '@testing-library/react'; const mockDispatch = jest.fn(); jest.mock('react-redux', () => { @@ -46,6 +47,7 @@ const mockOptions = [ const defaultProps = { scope: sourcererModel.SourcererScopeName.default, }; + describe('Sourcerer component', () => { beforeEach(() => { jest.clearAllMocks(); @@ -59,6 +61,34 @@ describe('Sourcerer component', () => { store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); }); + it('renders tooltip', () => { + const wrapper = mount( + + + + ); + expect(wrapper.find('[data-test-subj="sourcerer-tooltip"]').prop('content')).toEqual( + mockOptions + .map((p) => p.label) + .sort() + .join(', ') + ); + }); + + it('renders popover button inside tooltip', () => { + const wrapper = mount( + + + + ); + + expect( + wrapper + .find('[data-test-subj="sourcerer-tooltip"] [data-test-subj="sourcerer-trigger"]') + .exists() + ).toBeTruthy(); + }); + // Using props callback instead of simulating clicks, // because EuiSelectable uses a virtualized list, which isn't easily testable via test subjects it('Mounts with all options selected', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx index 8d0bb6410651c..3e922176f9982 100644 --- a/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/sourcerer/index.tsx @@ -169,55 +169,62 @@ export const Sourcerer = React.memo(({ scope: scopeId } [isPopoverOpen, sourcererScope.selectedPatterns] ); + const buttonWithTooptip = useMemo(() => { + return tooltipContent ? ( + + {trigger} + + ) : ( + trigger + ); + }, [trigger, tooltipContent]); + return ( - - - - - <>{i18n.SELECT_INDEX_PATTERNS} - - - {i18n.INDEX_PATTERNS_SELECTION_LABEL} - - {comboBox} - - - - - {i18n.INDEX_PATTERNS_RESET} - - - - - {i18n.SAVE_INDEX_PATTERNS} - - - - - - + + + + <>{i18n.SELECT_INDEX_PATTERNS} + + + {i18n.INDEX_PATTERNS_SELECTION_LABEL} + + {comboBox} + + + + + {i18n.INDEX_PATTERNS_RESET} + + + + + {i18n.SAVE_INDEX_PATTERNS} + + + + + ); }); Sourcerer.displayName = 'Sourcerer'; diff --git a/x-pack/plugins/security_solution/public/common/components/toasters/__snapshots__/modal_all_errors.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/toasters/__snapshots__/modal_all_errors.test.tsx.snap index 5e008e28073de..ee1b371fb5178 100644 --- a/x-pack/plugins/security_solution/public/common/components/toasters/__snapshots__/modal_all_errors.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/toasters/__snapshots__/modal_all_errors.test.tsx.snap @@ -22,7 +22,9 @@ exports[`Modal all errors rendering it renders the default all errors modal when { const kibana = useKibana(); - const client = kibana.services.savedObjects.client; + const { http } = kibana.services; const [savedQueryService, setSavedQueryService] = useState( - createSavedQueryService(client) + createSavedQueryService(http) ); useEffect(() => { - setSavedQueryService(createSavedQueryService(client)); - }, [client]); + setSavedQueryService(createSavedQueryService(http)); + }, [http]); return savedQueryService; }; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/alerts_count.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/alerts_count.tsx index f64e279fb2755..d6b1afea98592 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/alerts_count.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/alerts_count.tsx @@ -35,7 +35,7 @@ const getAlertsCountTableColumns = ( { field: 'key', name: selectedStackByOption, - truncateText: true, + truncateText: false, render: function DraggableStackOptionField(value: string) { return ( tabs.find((tab) => tab.id === show), [tabs, show]); const renderTabs = tabs.map((tab) => ( - + )); return ( diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx index cc1cad52eb21c..cb920bdbd1b03 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/endpoint_details_content.tsx @@ -13,8 +13,9 @@ import { EuiText, EuiFlexGroup, EuiFlexItem, - EuiBadge, EuiSpacer, + EuiLink, + EuiHealth, } from '@elastic/eui'; import React, { memo, useMemo } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -30,7 +31,6 @@ import { getEndpointDetailsPath } from '../../../../common/routing'; import { EndpointPolicyLink } from '../components/endpoint_policy_link'; import { OutOfDate } from '../components/out_of_date'; import { EndpointAgentStatus } from '../components/endpoint_agent_status'; -import { useAppUrl } from '../../../../../common/lib/kibana/hooks'; const HostIds = styled(EuiListGroupItem)` margin-top: 0; @@ -53,9 +53,8 @@ export const EndpointDetailsContent = memo( const policyStatus = useEndpointSelector( policyResponseStatus ) as keyof typeof POLICY_STATUS_TO_BADGE_COLOR; - const { getAppUrl } = useAppUrl(); - const [policyResponseUri, policyResponseRoutePath] = useMemo(() => { + const policyResponseRoutePath = useMemo(() => { // eslint-disable-next-line @typescript-eslint/naming-convention const { selected_endpoint, show, ...currentUrlParams } = queryParams; const path = getEndpointDetailsPath({ @@ -63,8 +62,8 @@ export const EndpointDetailsContent = memo( ...currentUrlParams, selected_endpoint: details.agent.id, }); - return [getAppUrl({ path }), path]; - }, [details.agent.id, getAppUrl, queryParams]); + return path; + }, [details.agent.id, queryParams]); const policyStatusClickHandler = useNavigateByRouterEventHandler(policyResponseRoutePath); @@ -142,26 +141,20 @@ export const EndpointDetailsContent = memo( defaultMessage: 'Policy Status', }), description: ( - // https://github.com/elastic/eui/issues/4530 - // @ts-ignore - - - - - + + + + + + ), }, { @@ -185,14 +178,7 @@ export const EndpointDetailsContent = memo( ), }, ]; - }, [ - details, - hostStatus, - policyResponseUri, - policyStatus, - policyStatusClickHandler, - policyInfo, - ]); + }, [details, hostStatus, policyStatus, policyStatusClickHandler, policyInfo]); return ( <> diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx index 727c2e8a35024..45dcf5f7a0f7d 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/index.test.tsx @@ -167,7 +167,7 @@ describe('when on the endpoint list page', () => { it('should NOT display timeline', async () => { const renderResult = render(); - const timelineFlyout = await renderResult.queryByTestId('flyoutOverlay'); + const timelineFlyout = renderResult.queryByTestId('flyoutOverlay'); expect(timelineFlyout).toBeNull(); }); @@ -460,7 +460,7 @@ describe('when on the endpoint list page', () => { const outOfDates = await renderResult.findAllByTestId('rowPolicyOutOfDate'); expect(outOfDates).toHaveLength(4); - outOfDates.forEach((item, index) => { + outOfDates.forEach((item) => { expect(item.textContent).toEqual('Out-of-date'); expect(item.querySelector(`[data-euiicon-type][color=warning]`)).not.toBeNull(); }); @@ -512,8 +512,8 @@ describe('when on the endpoint list page', () => { // FLAKY: https://github.com/elastic/kibana/issues/75721 describe.skip('when polling on Endpoint List', () => { - beforeEach(async () => { - await reactTestingLibrary.act(() => { + beforeEach(() => { + reactTestingLibrary.act(() => { const hostListData = mockEndpointResultList({ total: 4 }).hosts; setEndpointListApiMockImplementation(coreStart.http, { @@ -703,8 +703,8 @@ describe('when on the endpoint list page', () => { it('should show the flyout and footer', async () => { const renderResult = await renderAndWaitForData(); - await expect(renderResult.findByTestId('endpointDetailsFlyout')).not.toBeNull(); - await expect(renderResult.queryByTestId('endpointDetailsFlyoutFooter')).not.toBeNull(); + expect(renderResult.getByTestId('endpointDetailsFlyout')).not.toBeNull(); + expect(renderResult.getByTestId('endpointDetailsFlyoutFooter')).not.toBeNull(); }); it('should display policy name value as a link', async () => { @@ -738,15 +738,6 @@ describe('when on the endpoint list page', () => { ); }); - it('should display policy status value as a link', async () => { - const renderResult = await renderAndWaitForData(); - const policyStatusLink = await renderResult.findByTestId('policyStatusValue'); - expect(policyStatusLink).not.toBeNull(); - expect(policyStatusLink.getAttribute('href')).toEqual( - `${APP_PATH}${MANAGEMENT_PATH}/endpoints?page_index=0&page_size=10&selected_endpoint=1&show=policy_response` - ); - }); - it('should update the URL when policy status link is clicked', async () => { const renderResult = await renderAndWaitForData(); const policyStatusLink = await renderResult.findByTestId('policyStatusValue'); @@ -763,10 +754,8 @@ describe('when on the endpoint list page', () => { it('should display Success overall policy status', async () => { const renderResult = await renderAndWaitForData(); const policyStatusBadge = await renderResult.findByTestId('policyStatusValue'); + expect(renderResult.getByTestId('policyStatusValue-success')).toBeTruthy(); expect(policyStatusBadge.textContent).toEqual('Success'); - expect(policyStatusBadge.getAttribute('style')).toMatch( - /background-color\: rgb\(109\, 204\, 177\)\;/ - ); }); it('should display Warning overall policy status', async () => { @@ -774,9 +763,7 @@ describe('when on the endpoint list page', () => { const renderResult = await renderAndWaitForData(); const policyStatusBadge = await renderResult.findByTestId('policyStatusValue'); expect(policyStatusBadge.textContent).toEqual('Warning'); - expect(policyStatusBadge.getAttribute('style')).toMatch( - /background-color\: rgb\(241\, 216\, 111\)\;/ - ); + expect(renderResult.getByTestId('policyStatusValue-warning')).toBeTruthy(); }); it('should display Failed overall policy status', async () => { @@ -784,9 +771,7 @@ describe('when on the endpoint list page', () => { const renderResult = await renderAndWaitForData(); const policyStatusBadge = await renderResult.findByTestId('policyStatusValue'); expect(policyStatusBadge.textContent).toEqual('Failed'); - expect(policyStatusBadge.getAttribute('style')).toMatch( - /background-color\: rgb\(255\, 126\, 98\)\;/ - ); + expect(renderResult.getByTestId('policyStatusValue-failure')).toBeTruthy(); }); it('should display Unknown overall policy status', async () => { @@ -794,9 +779,7 @@ describe('when on the endpoint list page', () => { const renderResult = await renderAndWaitForData(); const policyStatusBadge = await renderResult.findByTestId('policyStatusValue'); expect(policyStatusBadge.textContent).toEqual('Unknown'); - expect(policyStatusBadge.getAttribute('style')).toMatch( - /background-color\: rgb\(211\, 218\, 230\)\;/ - ); + expect(renderResult.getByTestId('policyStatusValue-')).toBeTruthy(); }); it('should show the Take Action button', async () => { @@ -898,7 +881,7 @@ describe('when on the endpoint list page', () => { await reactTestingLibrary.act(async () => { await middlewareSpy.waitForAction('serverReturnedEndpointList'); }); - const hostNameLinks = await renderResult.getAllByTestId('hostnameCellLink'); + const hostNameLinks = renderResult.getAllByTestId('hostnameCellLink'); reactTestingLibrary.fireEvent.click(hostNameLinks[0]); }); @@ -913,7 +896,7 @@ describe('when on the endpoint list page', () => { reactTestingLibrary.act(() => { dispatchEndpointDetailsActivityLogChanged('success', getMockData()); }); - const endpointDetailsFlyout = await renderResult.queryByTestId('endpointDetailsFlyoutBody'); + const endpointDetailsFlyout = renderResult.queryByTestId('endpointDetailsFlyoutBody'); expect(endpointDetailsFlyout).not.toBeNull(); }); @@ -926,7 +909,7 @@ describe('when on the endpoint list page', () => { reactTestingLibrary.act(() => { dispatchEndpointDetailsActivityLogChanged('success', getMockData()); }); - const logEntries = await renderResult.queryAllByTestId('timelineEntry'); + const logEntries = renderResult.queryAllByTestId('timelineEntry'); expect(logEntries.length).toEqual(3); expect(`${logEntries[0]} .euiCommentTimeline__icon--update`).not.toBe(null); expect(`${logEntries[1]} .euiCommentTimeline__icon--regular`).not.toBe(null); @@ -944,7 +927,7 @@ describe('when on the endpoint list page', () => { getMockData({ hasLogsEndpointActionResponses: true }) ); }); - const logEntries = await renderResult.queryAllByTestId('timelineEntry'); + const logEntries = renderResult.queryAllByTestId('timelineEntry'); expect(logEntries.length).toEqual(4); expect(`${logEntries[0]} .euiCommentTimeline__icon--update`).not.toBe(null); expect(`${logEntries[1]} .euiCommentTimeline__icon--update`).not.toBe(null); @@ -960,7 +943,7 @@ describe('when on the endpoint list page', () => { reactTestingLibrary.act(() => { dispatchEndpointDetailsActivityLogChanged('failed', getMockData()); }); - const emptyState = await renderResult.queryByTestId('activityLogEmpty'); + const emptyState = renderResult.queryByTestId('activityLogEmpty'); expect(emptyState).not.toBe(null); }); @@ -980,10 +963,10 @@ describe('when on the endpoint list page', () => { }); }); - const emptyState = await renderResult.queryByTestId('activityLogEmpty'); + const emptyState = renderResult.queryByTestId('activityLogEmpty'); expect(emptyState).toBe(null); - const superDatePicker = await renderResult.queryByTestId('activityLogSuperDatePicker'); + const superDatePicker = renderResult.queryByTestId('activityLogSuperDatePicker'); expect(superDatePicker).not.toBe(null); }); @@ -1002,7 +985,7 @@ describe('when on the endpoint list page', () => { reactTestingLibrary.act(() => { dispatchEndpointDetailsActivityLogChanged('success', getMockData()); }); - const logEntries = await renderResult.queryAllByTestId('timelineEntry'); + const logEntries = renderResult.queryAllByTestId('timelineEntry'); expect(logEntries.length).toEqual(3); }); @@ -1047,7 +1030,7 @@ describe('when on the endpoint list page', () => { reactTestingLibrary.act(() => { dispatchEndpointDetailsActivityLogChanged('success', getMockData()); }); - const commentTexts = await renderResult.queryAllByTestId('activityLogCommentText'); + const commentTexts = renderResult.queryAllByTestId('activityLogCommentText'); expect(commentTexts.length).toEqual(1); expect(commentTexts[0].textContent).toEqual('some comment'); expect(commentTexts[0].parentElement?.parentElement?.className).toContain( @@ -1081,7 +1064,7 @@ describe('when on the endpoint list page', () => { afterEach(reactTestingLibrary.cleanup); it('should hide the host details panel', async () => { - const endpointDetailsFlyout = await renderResult.queryByTestId('endpointDetailsFlyoutBody'); + const endpointDetailsFlyout = renderResult.queryByTestId('endpointDetailsFlyoutBody'); expect(endpointDetailsFlyout).toBeNull(); }); @@ -1328,8 +1311,8 @@ describe('when on the endpoint list page', () => { ).toBe(true); }); - it('should NOT show the flyout footer', async () => { - await expect(renderResult.queryByTestId('endpointDetailsFlyoutFooter')).toBeNull(); + it('should NOT show the flyout footer', () => { + expect(renderResult.queryByTestId('endpointDetailsFlyoutFooter')).toBeNull(); }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx index 8e0d8c544563a..6034ed875c02b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_advanced.tsx @@ -171,10 +171,10 @@ const PolicyAdvanced = React.memo( - {configPath.join('.')} + + {configPath.join('.')} {documentation && ( - + )} diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/__snapshots__/index.test.tsx.snap index 2e70d1a7f8a5b..4512dfd8aab2c 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/overview/components/overview_host_stats/__snapshots__/index.test.tsx.snap @@ -38,6 +38,8 @@ exports[`Overview Host Stat Data rendering it renders the default OverviewHostSt } buttonContentClassName="accordion-button" + buttonElement="button" + element="div" id="host-stat-accordion-groupauditbeat" initialIsOpen={false} isLoading={false} @@ -273,6 +275,8 @@ exports[`Overview Host Stat Data rendering it renders the default OverviewHostSt } buttonContentClassName="accordion-button" + buttonElement="button" + element="div" id="host-stat-accordion-groupendgame" initialIsOpen={false} isLoading={false} @@ -540,6 +544,8 @@ exports[`Overview Host Stat Data rendering it renders the default OverviewHostSt } buttonContentClassName="accordion-button" + buttonElement="button" + element="div" id="host-stat-accordion-groupfilebeat" initialIsOpen={false} isLoading={false} @@ -615,6 +621,8 @@ exports[`Overview Host Stat Data rendering it renders the default OverviewHostSt } buttonContentClassName="accordion-button" + buttonElement="button" + element="div" id="host-stat-accordion-groupwinlogbeat" initialIsOpen={false} isLoading={false} diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap index 167866ef3c606..d9a5521aed9ac 100644 --- a/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/overview/components/overview_network_stats/__snapshots__/index.test.tsx.snap @@ -38,6 +38,8 @@ exports[`Overview Network Stat Data rendering it renders the default OverviewNet } buttonContentClassName="accordion-button" + buttonElement="button" + element="div" id="network-stat-accordion-groupauditbeat" initialIsOpen={false} isLoading={false} @@ -113,6 +115,8 @@ exports[`Overview Network Stat Data rendering it renders the default OverviewNet } buttonContentClassName="accordion-button" + buttonElement="button" + element="div" id="network-stat-accordion-groupfilebeat" initialIsOpen={false} isLoading={false} @@ -316,6 +320,8 @@ exports[`Overview Network Stat Data rendering it renders the default OverviewNet } buttonContentClassName="accordion-button" + buttonElement="button" + element="div" id="network-stat-accordion-grouppacketbeat" initialIsOpen={false} isLoading={false} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx index b2b304e16c4a0..daafec3005eb8 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx @@ -244,27 +244,19 @@ export const QueryBarTimeline = memo( (f) => f.meta.controlledBy === TIMELINE_FILTER_DROP_AREA ) : -1; - savedQueryServices.saveQuery( - { - ...newSavedQuery.attributes, - filters: - newSavedQuery.attributes.filters != null - ? dataProviderFilterExists > -1 - ? [ - ...newSavedQuery.attributes.filters.slice(0, dataProviderFilterExists), - getDataProviderFilter(dataProvidersDsl), - ...newSavedQuery.attributes.filters.slice(dataProviderFilterExists + 1), - ] - : [ - ...newSavedQuery.attributes.filters, - getDataProviderFilter(dataProvidersDsl), - ] - : [], - }, - { - overwrite: true, - } - ); + savedQueryServices.updateQuery(newSavedQuery.id, { + ...newSavedQuery.attributes, + filters: + newSavedQuery.attributes.filters != null + ? dataProviderFilterExists > -1 + ? [ + ...newSavedQuery.attributes.filters.slice(0, dataProviderFilterExists), + getDataProviderFilter(dataProvidersDsl), + ...newSavedQuery.attributes.filters.slice(dataProviderFilterExists + 1), + ] + : [...newSavedQuery.attributes.filters, getDataProviderFilter(dataProvidersDsl)] + : [], + }); } } else { setSavedQueryId(null); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.test.tsx index 3c6dc68edefcc..e519cfcd204a7 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.test.tsx @@ -5,7 +5,9 @@ * 2.0. */ -import { fireEvent, render } from '@testing-library/react'; +import { fireEvent, render, within } from '@testing-library/react'; +import { EuiToolTip } from '@elastic/eui'; + import React from 'react'; import { PickEventType } from './pick_events'; import { @@ -19,6 +21,14 @@ import { TimelineEventsType } from '../../../../../common'; import { createStore } from '../../../../common/store'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; +jest.mock('@elastic/eui', () => { + const actual = jest.requireActual('@elastic/eui'); + return { + ...actual, + EuiToolTip: jest.fn(), + }; +}); + describe('pick_events', () => { const defaultProps = { eventType: 'all' as TimelineEventsType, @@ -53,6 +63,23 @@ describe('pick_events', () => { }, }; const store = createStore(state, SUB_PLUGINS_REDUCER, kibanaObservable, storage); + + const mockTooltip = ({ + tooltipContent, + children, + }: { + tooltipContent: string; + children: React.ReactElement; + }) => ( +
+ {tooltipContent} + {children} +
+ ); + + beforeAll(() => { + (EuiToolTip as unknown as jest.Mock).mockImplementation(mockTooltip); + }); beforeEach(() => { jest.clearAllMocks(); jest.restoreAllMocks(); @@ -68,6 +95,32 @@ describe('pick_events', () => { initialPatterns.sort().join('') ); }); + + it('renders tooltip', () => { + render( + + + + ); + + expect((EuiToolTip as unknown as jest.Mock).mock.calls[0][0].content).toEqual( + initialPatterns + .filter((p) => p != null) + .sort() + .join(', ') + ); + }); + + it('renders popover button inside tooltip', () => { + const wrapper = render( + + + + ); + const tooltip = wrapper.getByTestId('timeline-sourcerer-tooltip'); + expect(within(tooltip).getByTestId('sourcerer-timeline-trigger')).toBeTruthy(); + }); + it('correctly filters options', () => { const wrapper = render( diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx index dbe04eccac521..6d86d7c0f1330 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/pick_events.tsx @@ -295,6 +295,20 @@ const PickEventTypeComponents: React.FC = ({ [isPopoverOpen, sourcererScope.selectedPatterns] ); + const buttonWithTooptip = useMemo(() => { + return tooltipContent ? ( + + {button} + + ) : ( + button + ); + }, [button, tooltipContent]); + const ButtonContent = useMemo( () => ( @@ -326,69 +340,66 @@ const PickEventTypeComponents: React.FC = ({ return ( - - - - - <>{i18n.SELECT_INDEX_PATTERNS} - - - {filter} - - - <> - - {comboBox} - - - {!showAdvanceSettings && ( - <> - - - {i18n.CONFIGURE_INDEX_PATTERNS} - - - )} - - - - - {i18n.DATA_SOURCES_RESET} - - - - - {i18n.SAVE_INDEX_PATTERNS} - - - - - - + + + + <>{i18n.SELECT_INDEX_PATTERNS} + + + {filter} + + + <> + + {comboBox} + + + {!showAdvanceSettings && ( + <> + + + {i18n.CONFIGURE_INDEX_PATTERNS} + + + )} + + + + + {i18n.DATA_SOURCES_RESET} + + + + + {i18n.SAVE_INDEX_PATTERNS} + + + + + ); }; diff --git a/x-pack/plugins/security_solution/server/config.mock.ts b/x-pack/plugins/security_solution/server/config.mock.ts index c1d1e02ca35f4..1c404104fb3f2 100644 --- a/x-pack/plugins/security_solution/server/config.mock.ts +++ b/x-pack/plugins/security_solution/server/config.mock.ts @@ -34,7 +34,6 @@ export const createMockConfig = (): ConfigType => { underlyingClient: UnderlyingLogClient.savedObjects, }, - kibanaIndex: '.kibana', experimentalFeatures: parseExperimentalConfigValue(enableExperimental), }; }; diff --git a/x-pack/plugins/security_solution/server/config.ts b/x-pack/plugins/security_solution/server/config.ts index 072e23b7a773c..16a69eeb8e05f 100644 --- a/x-pack/plugins/security_solution/server/config.ts +++ b/x-pack/plugins/security_solution/server/config.ts @@ -139,20 +139,15 @@ export const configSchema = schema.object({ export type ConfigSchema = TypeOf; export type ConfigType = ConfigSchema & { - kibanaIndex: string; experimentalFeatures: ExperimentalFeatures; }; export const createConfig = (context: PluginInitializerContext): ConfigType => { - const globalConfig = context.config.legacy.get(); const pluginConfig = context.config.get>(); - - const kibanaIndex = globalConfig.kibana.index; const experimentalFeatures = parseExperimentalConfigValue(pluginConfig.enableExperimental); return { ...pluginConfig, - kibanaIndex, experimentalFeatures, }; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts index 2f63a184875f1..f28d78e5c0304 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.test.ts @@ -77,17 +77,6 @@ describe('legacy_inject_rule_id_references', () => { expect(logger.error).not.toHaveBeenCalled(); }); - test('logs an error if found with a different saved object reference id', () => { - legacyInjectRuleIdReferences({ - logger, - ruleAlertId: '456', - savedObjectReferences: mockSavedObjectReferences(), - }); - expect(logger.error).toBeCalledWith( - 'The id of the "saved object reference id": 123 is not the same as the "saved object id": 456. Preferring and using the "saved object reference id" instead of the "saved object id"' - ); - }); - test('logs an error if the saved object references is empty', () => { legacyInjectRuleIdReferences({ logger, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts index 5cb32c6563157..b6ad98eb864ed 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/legacy_saved_object_references/legacy_inject_rule_id_references.ts @@ -32,19 +32,6 @@ export const legacyInjectRuleIdReferences = ({ return reference.name === 'alert_0'; }); if (referenceFound) { - if (referenceFound.id !== ruleAlertId) { - // This condition should not be reached but we log an error if we encounter it to help if we migrations - // did not run correctly or we create a regression in the future. - logger.error( - [ - 'The id of the "saved object reference id": ', - referenceFound.id, - ' is not the same as the "saved object id": ', - ruleAlertId, - '. Preferring and using the "saved object reference id" instead of the "saved object id"', - ].join('') - ); - } return referenceFound.id; } else { logger.error( diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.ts index d4357c45fd373..799412a33ffbc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/create_rules_stream_from_ndjson.ts @@ -24,6 +24,7 @@ import { filterExportedRulesCounts, filterExceptions, createLimitStream, + filterExportedCounts, } from '../../../utils/read_stream/create_stream_from_ndjson'; export const validateRules = (): Transform => { @@ -60,6 +61,7 @@ export const createRulesStreamFromNdJson = (ruleLimit: number) => { return [ createSplitStream('\n'), parseNdjsonStrings(), + filterExportedCounts(), filterExportedRulesCounts(), filterExceptions(), validateRules(), diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.test.ts index f0ff1b6072479..1212b73a6250e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.test.ts @@ -105,17 +105,6 @@ describe('inject_exceptions_list', () => { ).toEqual([{ ...mockExceptionsList()[0], id: '456' }]); }); - test('logs an error if found with a different saved object reference id', () => { - injectExceptionsReferences({ - logger, - exceptionsList: mockExceptionsList(), - savedObjectReferences: [{ ...mockSavedObjectReferences()[0], id: '456' }], - }); - expect(logger.error).toBeCalledWith( - 'The id of the "saved object reference id": 456 is not the same as the "saved object id": 123. Preferring and using the "saved object reference id" instead of the "saved object id"' - ); - }); - test('returns exceptionItem if the saved object reference cannot match as a fall back', () => { expect( injectExceptionsReferences({ diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.ts index 2e6559fbf18cf..baaaa2eb60ce9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/inject_exceptions_list.ts @@ -7,11 +7,7 @@ import { Logger, SavedObjectReference } from 'src/core/server'; import { RuleParams } from '../../schemas/rule_schemas'; -import { - getSavedObjectReferenceForExceptionsList, - logMissingSavedObjectError, - logWarningIfDifferentReferencesDetected, -} from './utils'; +import { getSavedObjectReferenceForExceptionsList, logMissingSavedObjectError } from './utils'; /** * This injects any "exceptionsList" "id"'s from saved object reference and returns the "exceptionsList" using the saved object reference. If for @@ -44,11 +40,6 @@ export const injectExceptionsReferences = ({ savedObjectReferences, }); if (savedObjectReference != null) { - logWarningIfDifferentReferencesDetected({ - logger, - savedObjectReferenceId: savedObjectReference.id, - savedObjectId: exceptionItem.id, - }); const reference: RuleParams['exceptionsList'][0] = { ...exceptionItem, id: savedObjectReference.id, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/index.ts index ca88dae364a4b..3a3d559a6ed39 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/index.ts @@ -11,4 +11,3 @@ export * from './get_saved_object_name_pattern'; export * from './get_saved_object_reference_for_exceptions_list'; export * from './get_saved_object_reference'; export * from './log_missing_saved_object_error'; -export * from './log_warning_if_different_references_detected'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_warning_if_different_references_detected.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_warning_if_different_references_detected.test.ts deleted file mode 100644 index a27faa6356c2b..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_warning_if_different_references_detected.test.ts +++ /dev/null @@ -1,38 +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 { loggingSystemMock } from 'src/core/server/mocks'; - -import { logWarningIfDifferentReferencesDetected } from '.'; - -describe('log_warning_if_different_references_detected', () => { - let logger = loggingSystemMock.create().get('security_solution'); - - beforeEach(() => { - logger = loggingSystemMock.create().get('security_solution'); - }); - - test('logs expect error message if the two ids are different', () => { - logWarningIfDifferentReferencesDetected({ - logger, - savedObjectReferenceId: '123', - savedObjectId: '456', - }); - expect(logger.error).toBeCalledWith( - 'The id of the "saved object reference id": 123 is not the same as the "saved object id": 456. Preferring and using the "saved object reference id" instead of the "saved object id"' - ); - }); - - test('logs nothing if the two ids are the same', () => { - logWarningIfDifferentReferencesDetected({ - logger, - savedObjectReferenceId: '123', - savedObjectId: '123', - }); - expect(logger.error).not.toHaveBeenCalled(); - }); -}); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_warning_if_different_references_detected.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_warning_if_different_references_detected.ts deleted file mode 100644 index 9f80ba6d8ce83..0000000000000 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/saved_object_references/utils/log_warning_if_different_references_detected.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { Logger } from 'src/core/server'; - -/** - * This will log a warning that the saved object reference id and the saved object id are not the same if that is true. - * @param logger The kibana injected logger - * @param savedObjectReferenceId The saved object reference id from "references: [{ id: ...}]" - * @param savedObjectId The saved object id from a structure such as exceptions { exceptionsList: { "id": "..." } } - */ -export const logWarningIfDifferentReferencesDetected = ({ - logger, - savedObjectReferenceId, - savedObjectId, -}: { - logger: Logger; - savedObjectReferenceId: string; - savedObjectId: string; -}): void => { - if (savedObjectReferenceId !== savedObjectId) { - logger.error( - [ - 'The id of the "saved object reference id": ', - savedObjectReferenceId, - ' is not the same as the "saved object id": ', - savedObjectId, - '. Preferring and using the "saved object reference id" instead of the "saved object id"', - ].join('') - ); - } -}; diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 14cf6f0a48799..39aa1fb069f20 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -107,6 +107,7 @@ export class Plugin implements ISecuritySolutionPlugin { private checkMetadataTransformsTask: CheckMetadataTransformsTask | undefined; private artifactsCache: LRU; private telemetryUsageCounter?: UsageCounter; + private kibanaIndex?: string; constructor(context: PluginInitializerContext) { this.pluginContext = context; @@ -130,6 +131,7 @@ export class Plugin implements ISecuritySolutionPlugin { const { pluginContext, config, logger, appClientFactory } = this; const experimentalFeatures = config.experimentalFeatures; + this.kibanaIndex = core.savedObjects.getKibanaIndex(); appClientFactory.setup({ getSpaceId: plugins.spaces?.spacesService?.getSpaceId, @@ -162,7 +164,7 @@ export class Plugin implements ISecuritySolutionPlugin { initUsageCollectors({ core, - kibanaIndex: config.kibanaIndex, + kibanaIndex: core.savedObjects.getKibanaIndex(), signalsIndex: config.signalsIndex, ml: plugins.ml, usageCollection: plugins.usageCollection, @@ -411,7 +413,8 @@ export class Plugin implements ISecuritySolutionPlugin { this.telemetryReceiver.start( core, - config.kibanaIndex, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.kibanaIndex!, this.endpointAppContextService, exceptionListClient ); diff --git a/x-pack/plugins/spaces/server/plugin.ts b/x-pack/plugins/spaces/server/plugin.ts index 9455321c4eaa3..7f1abdb0a806c 100644 --- a/x-pack/plugins/spaces/server/plugin.ts +++ b/x-pack/plugins/spaces/server/plugin.ts @@ -94,8 +94,6 @@ export class SpacesPlugin { private readonly config$: Observable; - private readonly kibanaIndexConfig$: Observable<{ kibana: { index: string } }>; - private readonly log: Logger; private readonly spacesLicenseService = new SpacesLicenseService(); @@ -110,7 +108,6 @@ export class SpacesPlugin constructor(initializerContext: PluginInitializerContext) { this.config$ = initializerContext.config.create(); - this.kibanaIndexConfig$ = initializerContext.config.legacy.globalConfig$; this.log = initializerContext.logger.get(); this.spacesService = new SpacesService(); this.spacesClientService = new SpacesClientService((message) => this.log.debug(message)); @@ -180,7 +177,7 @@ export class SpacesPlugin if (plugins.usageCollection) { registerSpacesUsageCollector(plugins.usageCollection, { - kibanaIndexConfig$: this.kibanaIndexConfig$, + kibanaIndex: core.savedObjects.getKibanaIndex(), features: plugins.features, licensing: plugins.licensing, usageStatsServicePromise, diff --git a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.test.ts b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.test.ts index bdcb8afac3009..6bf410e21dcb3 100644 --- a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.test.ts +++ b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.test.ts @@ -7,10 +7,7 @@ import * as Rx from 'rxjs'; -import { - elasticsearchServiceMock, - pluginInitializerContextConfigMock, -} from 'src/core/server/mocks'; +import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { createCollectorFetchContextMock } from '../../../../../src/plugins/usage_collection/server/mocks'; import type { KibanaFeature } from '../../../features/server'; @@ -43,6 +40,8 @@ const MOCK_USAGE_STATS: UsageStats = { 'apiCalls.disableLegacyUrlAliases.total': 17, }; +const kibanaIndex = '.kibana-tests'; + function setup({ license = { isAvailable: true }, features = [{ id: 'feature1' } as KibanaFeature, { id: 'feature2' } as KibanaFeature], @@ -53,6 +52,7 @@ function setup({ constructor({ fetch }: any) { this.fetch = fetch; } + // to make typescript happy public fakeFetchUsage() { return this.fetch; @@ -121,7 +121,7 @@ describe('error handling', () => { license: { isAvailable: true, type: 'basic' }, }); const collector = getSpacesUsageCollector(usageCollection as any, { - kibanaIndexConfig$: Rx.of({ kibana: { index: '.kibana' } }), + kibanaIndex, features, licensing, usageStatsServicePromise: Promise.resolve(usageStatsService), @@ -145,7 +145,7 @@ describe('with a basic license', () => { beforeAll(async () => { const collector = getSpacesUsageCollector(usageCollection as any, { - kibanaIndexConfig$: pluginInitializerContextConfigMock({}).legacy.globalConfig$, + kibanaIndex, features, licensing, usageStatsServicePromise: Promise.resolve(usageStatsService), @@ -164,7 +164,7 @@ describe('with a basic license', () => { size: 0, track_total_hits: true, }, - index: '.kibana-tests', + index: kibanaIndex, }); }); @@ -204,7 +204,7 @@ describe('with no license', () => { beforeAll(async () => { const collector = getSpacesUsageCollector(usageCollection as any, { - kibanaIndexConfig$: pluginInitializerContextConfigMock({}).legacy.globalConfig$, + kibanaIndex, features, licensing, usageStatsServicePromise: Promise.resolve(usageStatsService), @@ -245,7 +245,7 @@ describe('with platinum license', () => { beforeAll(async () => { const collector = getSpacesUsageCollector(usageCollection as any, { - kibanaIndexConfig$: pluginInitializerContextConfigMock({}).legacy.globalConfig$, + kibanaIndex, features, licensing, usageStatsServicePromise: Promise.resolve(usageStatsService), diff --git a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts index 27bc935b0ee3f..f2ca7a9ebb332 100644 --- a/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts +++ b/x-pack/plugins/spaces/server/usage_collection/spaces_usage_collector.ts @@ -5,7 +5,6 @@ * 2.0. */ -import type { Observable } from 'rxjs'; import { take } from 'rxjs/operators'; import type { ElasticsearchClient } from 'src/core/server'; @@ -150,7 +149,7 @@ export interface UsageData extends UsageStats { } interface CollectorDeps { - kibanaIndexConfig$: Observable<{ kibana: { index: string } }>; + kibanaIndex: string; features: PluginsSetup['features']; licensing: PluginsSetup['licensing']; usageStatsServicePromise: Promise; @@ -426,12 +425,10 @@ export function getSpacesUsageCollector( }, }, fetch: async ({ esClient }: CollectorFetchContext) => { - const { licensing, kibanaIndexConfig$, features, usageStatsServicePromise } = deps; + const { licensing, kibanaIndex, features, usageStatsServicePromise } = deps; const license = await licensing.license$.pipe(take(1)).toPromise(); const available = license.isAvailable; // some form of spaces is available for all valid licenses - const kibanaIndex = (await kibanaIndexConfig$.pipe(take(1)).toPromise()).kibana.index; - const usageData = await getSpacesUsage(esClient, kibanaIndex, features, available); const usageStats = await getUsageStats(usageStatsServicePromise, available); diff --git a/x-pack/plugins/stack_alerts/server/index.ts b/x-pack/plugins/stack_alerts/server/index.ts index 1ac774a2d6c3f..b6b117ceb7075 100644 --- a/x-pack/plugins/stack_alerts/server/index.ts +++ b/x-pack/plugins/stack_alerts/server/index.ts @@ -18,6 +18,7 @@ export const config: PluginConfigDescriptor = { const stackAlerts = get(settings, fromPath); if (stackAlerts?.enabled === false || stackAlerts?.enabled === true) { addDeprecation({ + level: 'critical', configPath: 'xpack.stack_alerts.enabled', message: `"xpack.stack_alerts.enabled" is deprecated. The ability to disable this plugin will be removed in 8.0.0.`, correctiveActions: { diff --git a/x-pack/plugins/stack_alerts/server/plugin.test.ts b/x-pack/plugins/stack_alerts/server/plugin.test.ts index b2bf076eaf49d..b9263553173d2 100644 --- a/x-pack/plugins/stack_alerts/server/plugin.test.ts +++ b/x-pack/plugins/stack_alerts/server/plugin.test.ts @@ -11,8 +11,7 @@ import { alertsMock } from '../../alerting/server/mocks'; import { featuresPluginMock } from '../../features/server/mocks'; import { BUILT_IN_ALERTS_FEATURE } from './feature'; -// unhandled promise rejection: https://github.com/elastic/kibana/issues/112699 -describe.skip('AlertingBuiltins Plugin', () => { +describe('AlertingBuiltins Plugin', () => { describe('setup()', () => { let context: ReturnType; let plugin: AlertingBuiltinsPlugin; diff --git a/x-pack/plugins/task_manager/server/index.ts b/x-pack/plugins/task_manager/server/index.ts index 100f95729d1b7..d078c7b78ad94 100644 --- a/x-pack/plugins/task_manager/server/index.ts +++ b/x-pack/plugins/task_manager/server/index.ts @@ -49,6 +49,7 @@ export const config: PluginConfigDescriptor = { const taskManager = get(settings, fromPath); if (taskManager?.index) { addDeprecation({ + level: 'critical', configPath: `${fromPath}.index`, documentationUrl: 'https://ela.st/kbn-remove-legacy-multitenancy', message: `"${fromPath}.index" is deprecated. Multitenancy by changing "kibana.index" will not be supported starting in 8.0. See https://ela.st/kbn-remove-legacy-multitenancy for more details`, @@ -62,6 +63,7 @@ export const config: PluginConfigDescriptor = { } if (taskManager?.max_workers > MAX_WORKERS_LIMIT) { addDeprecation({ + level: 'critical', configPath: `${fromPath}.max_workers`, message: `setting "${fromPath}.max_workers" (${taskManager?.max_workers}) greater than ${MAX_WORKERS_LIMIT} is deprecated. Values greater than ${MAX_WORKERS_LIMIT} will not be supported starting in 8.0.`, correctiveActions: { diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 12763e4e26e31..b3ca5f17634d5 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -144,26 +144,26 @@ "throttle_time": { "properties": { "min": { - "type": "keyword" + "type": "long" }, "avg": { - "type": "keyword" + "type": "float" }, "max": { - "type": "keyword" + "type": "long" } } }, "schedule_time": { "properties": { "min": { - "type": "keyword" + "type": "long" }, "avg": { - "type": "keyword" + "type": "float" }, "max": { - "type": "keyword" + "type": "long" } } }, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 9e4249986c6a9..a8d3b4a5f3e27 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -807,8 +807,6 @@ "xpack.lens.xyChart.topAxisDisabledHelpText": "この設定は、上の軸が有効であるときにのみ適用されます。", "xpack.lens.xyChart.topAxisLabel": "上の軸", "xpack.lens.xyChart.upperBoundLabel": "上界", - "xpack.lens.xyChart.valueLabelsVisibility.auto": "非表示", - "xpack.lens.xyChart.valueLabelsVisibility.inside": "表示", "xpack.lens.xyChart.valuesHistogramDisabledHelpText": "この設定はヒストグラムで変更できません。", "xpack.lens.xyChart.valuesInLegend.help": "凡例に値を表示", "xpack.lens.xyChart.valuesPercentageDisabledHelpText": "この設定は割合エリアグラフで変更できません。", @@ -2532,7 +2530,6 @@ "discover.sourceViewer.errorMessage": "現在データを取得できませんでした。タブを更新して、再試行してください。", "discover.sourceViewer.errorMessageTitle": "エラーが発生しました", "discover.sourceViewer.refresh": "更新", - "discover.timeLabel": "時間", "discover.toggleSidebarAriaLabel": "サイドバーを切り替える", "discover.topNav.openOptionsPopover.description": "お知らせDiscoverでは、データの並べ替え、列のドラッグアンドドロップ、ドキュメントの比較を行う方法が改善されました。詳細設定で[クラシックテーブルを使用]を切り替えて、開始します。", "discover.topNav.openSearchPanel.manageSearchesButtonLabel": "検索の管理", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index db6d19d7550a9..4bd2a5907abf3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -817,8 +817,6 @@ "xpack.lens.xyChart.topAxisDisabledHelpText": "此设置仅在启用顶轴时应用。", "xpack.lens.xyChart.topAxisLabel": "顶轴", "xpack.lens.xyChart.upperBoundLabel": "上边界", - "xpack.lens.xyChart.valueLabelsVisibility.auto": "隐藏", - "xpack.lens.xyChart.valueLabelsVisibility.inside": "显示", "xpack.lens.xyChart.valuesHistogramDisabledHelpText": "不能在直方图上更改此设置。", "xpack.lens.xyChart.valuesInLegend.help": "在图例中显示值", "xpack.lens.xyChart.valuesPercentageDisabledHelpText": "不能在百分比面积图上更改此设置。", @@ -2557,7 +2555,6 @@ "discover.sourceViewer.errorMessage": "当前无法获取数据。请刷新选项卡以重试。", "discover.sourceViewer.errorMessageTitle": "发生错误", "discover.sourceViewer.refresh": "刷新", - "discover.timeLabel": "时间", "discover.toggleSidebarAriaLabel": "切换侧边栏", "discover.topNav.openOptionsPopover.description": "好消息!Discover 有更好的方法排序数据、拖放列和比较文档。在“高级模式”中切换“使用经典表”来开始。", "discover.topNav.openSearchPanel.manageSearchesButtonLabel": "管理搜索", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/helpers.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/helpers.ts index e6acb2e0976a8..755923acc25cb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/helpers.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/helpers.ts @@ -28,7 +28,7 @@ export const isFieldInvalid = ( ): boolean => error !== undefined && error.length > 0 && field != null; // TODO: Remove when the applications are certified -export const isLegacyConnector = (connector: ServiceNowActionConnector) => { +export const isDeprecatedConnector = (connector: ServiceNowActionConnector): boolean => { if (connector == null) { return true; } @@ -41,5 +41,14 @@ export const isLegacyConnector = (connector: ServiceNowActionConnector) => { return true; } - return connector.config.isLegacy; + /** + * Connectors after the Elastic ServiceNow application use the + * Import Set API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_ImportSetAPI) + * A ServiceNow connector is considered deprecated if it uses the Table API. + * + * All other connectors do not have the usesTableApi config property + * so the function will always return false for them. + */ + + return !!connector.config.usesTableApi; }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.test.tsx index eb3e1c01887c9..3f22a51b5bd53 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.test.tsx @@ -52,7 +52,7 @@ describe('servicenow connector validation', () => { isPreconfigured: false, config: { apiUrl: 'https://dev94428.service-now.com/', - isLegacy: false, + usesTableApi: false, }, } as ServiceNowActionConnector; @@ -60,7 +60,7 @@ describe('servicenow connector validation', () => { config: { errors: { apiUrl: [], - isLegacy: [], + usesTableApi: [], }, }, secrets: { @@ -88,7 +88,7 @@ describe('servicenow connector validation', () => { config: { errors: { apiUrl: ['URL is required.'], - isLegacy: [], + usesTableApi: [], }, }, secrets: { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx index 6b6d536ff303b..7267e11ae7327 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx @@ -28,7 +28,7 @@ const validateConnector = async ( const translations = await import('./translations'); const configErrors = { apiUrl: new Array(), - isLegacy: new Array(), + usesTableApi: new Array(), }; const secretsErrors = { username: new Array(), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.test.tsx index f491376e5078c..03acb673bf5a4 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.test.tsx @@ -36,7 +36,7 @@ describe('ServiceNowActionConnectorFields renders', () => { name: 'SN', config: { apiUrl: 'https://test/', - isLegacy: true, + usesTableApi: true, }, } as ServiceNowActionConnector; @@ -44,7 +44,7 @@ describe('ServiceNowActionConnectorFields renders', () => { ...usesTableApiConnector, config: { ...usesTableApiConnector.config, - isLegacy: false, + usesTableApi: false, }, } as ServiceNowActionConnector; @@ -350,7 +350,7 @@ describe('ServiceNowActionConnectorFields renders', () => { id: usesTableApiConnector.id, connector: { name: usesTableApiConnector.name, - config: { ...usesTableApiConnector.config, isLegacy: false }, + config: { ...usesTableApiConnector.config, usesTableApi: false }, secrets: usesTableApiConnector.secrets, }, }) @@ -415,7 +415,7 @@ describe('ServiceNowActionConnectorFields renders', () => { ).toBeTruthy(); }); - test('should set the isLegacy to false when creating a connector', async () => { + test('should set the usesTableApi to false when creating a connector', async () => { const newConnector = { ...usesTableApiConnector, config: {}, secrets: {} }; const editActionConfig = jest.fn(); @@ -432,7 +432,7 @@ describe('ServiceNowActionConnectorFields renders', () => { /> ); - expect(editActionConfig).toHaveBeenCalledWith('isLegacy', false); + expect(editActionConfig).toHaveBeenCalledWith('usesTableApi', false); }); test('it should set the legacy attribute if it is not undefined', async () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx index a0b4bdca47ff5..db3c32755f0ed 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx @@ -15,7 +15,7 @@ import { useKibana } from '../../../../common/lib/kibana'; import { DeprecatedCallout } from './deprecated_callout'; import { useGetAppInfo } from './use_get_app_info'; import { ApplicationRequiredCallout } from './application_required_callout'; -import { isRESTApiError, isLegacyConnector } from './helpers'; +import { isRESTApiError, isDeprecatedConnector } from './helpers'; import { InstallationCallout } from './installation_callout'; import { UpdateConnector } from './update_connector'; import { updateActionConnector } from '../../../lib/action_connector_api'; @@ -36,9 +36,9 @@ const ServiceNowConnectorFields: React.FC(false); + const [showApplicationRequiredCallout, setShowApplicationRequiredCallout] = + useState(false); const [applicationInfoErrorMsg, setApplicationInfoErrorMsg] = useState(null); const getApplicationInfo = useCallback(async () => { - setApplicationRequired(false); + setShowApplicationRequiredCallout(false); setApplicationInfoErrorMsg(null); try { @@ -61,7 +62,7 @@ const ServiceNowConnectorFields: React.FC { - if (!isOldConnector) { + if (requiresNewApplication) { await getApplicationInfo(); } - }, [getApplicationInfo, isOldConnector]); + }, [getApplicationInfo, requiresNewApplication]); useEffect( () => setCallbacks({ beforeActionConnectorSave }), @@ -90,13 +91,13 @@ const ServiceNowConnectorFields: React.FC { - if (isLegacy == null) { - editActionConfig('isLegacy', false); + if (usesTableApi == null) { + editActionConfig('usesTableApi', false); } }); @@ -150,8 +151,8 @@ const ServiceNowConnectorFields: React.FC )} - {!isOldConnector && } - {isOldConnector && } + {requiresNewApplication && } + {!requiresNewApplication && } - {applicationRequired && !isOldConnector && ( + {showApplicationRequiredCallout && requiresNewApplication && ( )} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_itsm_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_itsm_params.tsx index 09b04f0fa3c48..dcfdfe3af0e0e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_itsm_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_itsm_params.tsx @@ -23,7 +23,7 @@ import { ServiceNowITSMActionParams, Choice, Fields, ServiceNowActionConnector } import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables'; import { TextFieldWithMessageVariables } from '../../text_field_with_message_variables'; import { useGetChoices } from './use_get_choices'; -import { choicesToEuiOptions, DEFAULT_CORRELATION_ID, isLegacyConnector } from './helpers'; +import { choicesToEuiOptions, DEFAULT_CORRELATION_ID, isDeprecatedConnector } from './helpers'; import * as i18n from './translations'; @@ -46,10 +46,6 @@ const ServiceNowParamsFields: React.FunctionComponent< notifications: { toasts }, } = useKibana().services; - const isDeprecatedConnector = isLegacyConnector( - actionConnector as unknown as ServiceNowActionConnector - ); - const actionConnectorRef = useRef(actionConnector?.id ?? ''); const { incident, comments } = useMemo( () => @@ -244,7 +240,7 @@ const ServiceNowParamsFields: React.FunctionComponent< - {!isDeprecatedConnector && ( + {!isDeprecatedConnector(actionConnector as unknown as ServiceNowActionConnector) && ( <> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_sir_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_sir_params.tsx index 42758250408d9..a264ed5421c2e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_sir_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_sir_params.tsx @@ -25,7 +25,7 @@ import { TextFieldWithMessageVariables } from '../../text_field_with_message_var import * as i18n from './translations'; import { useGetChoices } from './use_get_choices'; import { ServiceNowSIRActionParams, Fields, Choice, ServiceNowActionConnector } from './types'; -import { choicesToEuiOptions, isLegacyConnector, DEFAULT_CORRELATION_ID } from './helpers'; +import { choicesToEuiOptions, isDeprecatedConnector, DEFAULT_CORRELATION_ID } from './helpers'; const useGetChoicesFields = ['category', 'subcategory', 'priority']; const defaultFields: Fields = { @@ -43,10 +43,6 @@ const ServiceNowSIRParamsFields: React.FunctionComponent< notifications: { toasts }, } = useKibana().services; - const isDeprecatedConnector = isLegacyConnector( - actionConnector as unknown as ServiceNowActionConnector - ); - const actionConnectorRef = useRef(actionConnector?.id ?? ''); const { incident, comments } = useMemo( () => @@ -229,7 +225,7 @@ const ServiceNowSIRParamsFields: React.FunctionComponent< - {!isDeprecatedConnector && ( + {!isDeprecatedConnector(actionConnector as unknown as ServiceNowActionConnector) && ( <> diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/types.ts index ecbb4f9de726b..40bb47543a3c8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/types.ts @@ -35,7 +35,7 @@ export interface ServiceNowITOMActionParams { export interface ServiceNowConfig { apiUrl: string; - isLegacy: boolean; + usesTableApi: boolean; } export interface ServiceNowSecrets { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/update_connector.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/update_connector.test.tsx index 2d95bfa85ceb9..ecb90051e78c2 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/update_connector.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/update_connector.test.tsx @@ -22,7 +22,7 @@ const actionConnector: ServiceNowActionConnector = { name: 'servicenow', config: { apiUrl: 'https://test/', - isLegacy: true, + usesTableApi: true, }, }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/use_get_app_info.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/use_get_app_info.test.tsx index c6b70443ec8fb..f842f6863676a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/use_get_app_info.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/use_get_app_info.test.tsx @@ -34,7 +34,7 @@ const actionConnector = { isPreconfigured: false, config: { apiUrl: 'https://test.service-now.com/', - isLegacy: false, + usesTableApi: false, }, } as ServiceNowActionConnector; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx index 844f28f022547..5de21470fc19a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/actions_connectors_list/components/actions_connectors_list.tsx @@ -205,8 +205,8 @@ const ActionsConnectorsList: React.FunctionComponent = () => { const itemConfig = ( item as UserConfiguredActionConnector, Record> ).config; - const showLegacyTooltip = - itemConfig?.isLegacy && + const showDeprecatedTooltip = + itemConfig?.usesTableApi && // TODO: Remove when applications are certified ((ENABLE_NEW_SN_ITSM_CONNECTOR && item.actionTypeId === '.servicenow') || (ENABLE_NEW_SN_SIR_CONNECTOR && item.actionTypeId === '.servicenow-sir')); @@ -233,7 +233,7 @@ const ActionsConnectorsList: React.FunctionComponent = () => { position="right" /> ) : null} - {showLegacyTooltip && } + {showDeprecatedTooltip && } ); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx index 4ae570a62f7d9..ffcda22195ff5 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_form/alert_add.test.tsx @@ -64,7 +64,8 @@ export const TestExpression: FunctionComponent = () => { ); }; -describe('alert_add', () => { +// FLAKY: https://github.com/elastic/kibana/issues/g +describe.skip('alert_add', () => { let wrapper: ReactWrapper; async function setup( diff --git a/x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_headers.test.tsx.snap b/x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_headers.test.tsx.snap index ef707dc3ea315..3899c27acf1d7 100644 --- a/x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_headers.test.tsx.snap +++ b/x-pack/plugins/uptime/public/components/monitor/ping_list/__snapshots__/ping_headers.test.tsx.snap @@ -16,6 +16,8 @@ exports[`Ping Headers shallow renders expected elements for valid props 1`] = ` } + buttonElement="button" + element="div" id="responseHeaderAccord" initialIsOpen={false} isLoading={false} diff --git a/x-pack/test/accessibility/apps/kibana_overview.ts b/x-pack/test/accessibility/apps/kibana_overview.ts index 9f5d91e5b4d54..6ea51cc0b855c 100644 --- a/x-pack/test/accessibility/apps/kibana_overview.ts +++ b/x-pack/test/accessibility/apps/kibana_overview.ts @@ -12,7 +12,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const a11y = getService('a11y'); // FLAKY: https://github.com/elastic/kibana/issues/98463 - describe.skip('Kibana overview', () => { + describe('Kibana overview', () => { const esArchiver = getService('esArchiver'); before(async () => { diff --git a/x-pack/test/accessibility/config.ts b/x-pack/test/accessibility/config.ts index 699b5b48d604c..933e8e97da397 100644 --- a/x-pack/test/accessibility/config.ts +++ b/x-pack/test/accessibility/config.ts @@ -17,10 +17,11 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [ require.resolve('./apps/login_page'), - require.resolve('./apps/home'), require.resolve('./apps/kibana_overview'), + require.resolve('./apps/home'), require.resolve('./apps/grok_debugger'), require.resolve('./apps/search_profiler'), + require.resolve('./apps/painless_lab'), require.resolve('./apps/uptime'), require.resolve('./apps/spaces'), require.resolve('./apps/advanced_settings'), diff --git a/x-pack/test/alerting_api_integration/common/config.ts b/x-pack/test/alerting_api_integration/common/config.ts index 3fe5ecb6076e2..7bcec7b11c10e 100644 --- a/x-pack/test/alerting_api_integration/common/config.ts +++ b/x-pack/test/alerting_api_integration/common/config.ts @@ -242,7 +242,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) }, }, })}`, - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), ...plugins.map( (pluginDir) => `--plugin-path=${path.resolve(__dirname, 'fixtures', 'plugins', pluginDir)}` diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/jira_simulation.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/jira_simulation.ts index 26a9c1bcadf6e..e9e6d6732327a 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/jira_simulation.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/jira_simulation.ts @@ -30,7 +30,6 @@ export function initPlugin(router: IRouter, path: string) { return jsonResponse(res, 200, { id: '123', key: 'CK-1', - created: '2020-04-27T14:17:45.490Z', }); } ); @@ -48,12 +47,7 @@ export function initPlugin(router: IRouter, path: string) { req: KibanaRequest, res: KibanaResponseFactory ): Promise> { - return jsonResponse(res, 200, { - id: '123', - key: 'CK-1', - created: '2020-04-27T14:17:45.490Z', - updated: '2020-04-27T14:17:45.490Z', - }); + return jsonResponse(res, 204, {}); } ); @@ -73,10 +67,12 @@ export function initPlugin(router: IRouter, path: string) { return jsonResponse(res, 200, { id: '123', key: 'CK-1', - created: '2020-04-27T14:17:45.490Z', - updated: '2020-04-27T14:17:45.490Z', - summary: 'title', - description: 'description', + fields: { + created: '2020-04-27T14:17:45.490Z', + updated: '2020-04-27T14:17:45.490Z', + summary: 'title', + description: 'description', + }, }); } ); @@ -97,6 +93,7 @@ export function initPlugin(router: IRouter, path: string) { return jsonResponse(res, 200, { id: '123', created: '2020-04-27T14:17:45.490Z', + updated: '2020-04-27T14:17:45.490Z', }); } ); 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/tests/actions/builtin_action_types/servicenow_itsm.ts index 97c2a77a8f074..1308959ebbacf 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/tests/actions/builtin_action_types/servicenow_itsm.ts @@ -22,7 +22,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { const mockServiceNow = { config: { apiUrl: 'www.servicenowisinkibanaactions.com', - isLegacy: false, + usesTableApi: false, }, secrets: { password: 'elastic', @@ -91,7 +91,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { connector_type_id: '.servicenow', config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, secrets: mockServiceNow.secrets, }) @@ -105,7 +105,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { is_missing_secrets: false, config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, }); @@ -121,12 +121,12 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { is_missing_secrets: false, config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, }); }); - it('should set the isLegacy to true when not provided', async () => { + it('should set the usesTableApi to true when not provided', async () => { const { body: createdAction } = await supertest .post('/api/actions/connector') .set('kbn-xsrf', 'foo') @@ -144,7 +144,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { .get(`/api/actions/connector/${createdAction.id}`) .expect(200); - expect(fetchedAction.config.isLegacy).to.be(true); + expect(fetchedAction.config.usesTableApi).to.be(true); }); it('should respond with a 400 Bad Request when creating a servicenow action with no apiUrl', async () => { @@ -223,7 +223,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { connector_type_id: '.servicenow', config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, secrets: mockServiceNow.secrets, }); @@ -383,7 +383,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { }); describe('Execution', () => { - // New connectors + // Connectors that use the Import set API describe('Import set API', () => { it('should handle creating an incident without comments', async () => { const { body: result } = await supertest @@ -414,7 +414,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { }); }); - // Legacy connectors + // Connectors that use the Table API describe('Table API', () => { before(async () => { const { body } = await supertest @@ -425,7 +425,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) { connector_type_id: '.servicenow', config: { apiUrl: serviceNowSimulatorURL, - isLegacy: true, + usesTableApi: true, }, secrets: mockServiceNow.secrets, }); 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/tests/actions/builtin_action_types/servicenow_sir.ts index 3a13e055e7aeb..c27634ecf6aca 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/tests/actions/builtin_action_types/servicenow_sir.ts @@ -22,7 +22,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { const mockServiceNow = { config: { apiUrl: 'www.servicenowisinkibanaactions.com', - isLegacy: false, + usesTableApi: false, }, secrets: { password: 'elastic', @@ -95,7 +95,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { connector_type_id: '.servicenow-sir', config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, secrets: mockServiceNow.secrets, }) @@ -109,7 +109,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { is_missing_secrets: false, config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, }); @@ -125,12 +125,12 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { is_missing_secrets: false, config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, }); }); - it('should set the isLegacy to true when not provided', async () => { + it('should set the usesTableApi to true when not provided', async () => { const { body: createdAction } = await supertest .post('/api/actions/connector') .set('kbn-xsrf', 'foo') @@ -148,7 +148,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { .get(`/api/actions/connector/${createdAction.id}`) .expect(200); - expect(fetchedAction.config.isLegacy).to.be(true); + expect(fetchedAction.config.usesTableApi).to.be(true); }); it('should respond with a 400 Bad Request when creating a servicenow action with no apiUrl', async () => { @@ -227,7 +227,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { connector_type_id: '.servicenow-sir', config: { apiUrl: serviceNowSimulatorURL, - isLegacy: false, + usesTableApi: false, }, secrets: mockServiceNow.secrets, }); @@ -387,7 +387,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { }); describe('Execution', () => { - // New connectors + // Connectors that use the Import set API describe('Import set API', () => { it('should handle creating an incident without comments', async () => { const { body: result } = await supertest @@ -418,7 +418,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { }); }); - // Legacy connectors + // Connectors that use the Table API describe('Table API', () => { before(async () => { const { body } = await supertest @@ -429,7 +429,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) { connector_type_id: '.servicenow-sir', config: { apiUrl: serviceNowSimulatorURL, - isLegacy: true, + usesTableApi: true, }, secrets: mockServiceNow.secrets, }); diff --git a/x-pack/test/api_integration/apis/features/features/features.ts b/x-pack/test/api_integration/apis/features/features/features.ts index 0e9ee6cc5ea58..d5b66c4d6da97 100644 --- a/x-pack/test/api_integration/apis/features/features/features.ts +++ b/x-pack/test/api_integration/apis/features/features/features.ts @@ -104,6 +104,7 @@ export default function ({ getService }: FtrProviderContext) { 'indexPatterns', 'graph', 'monitoring', + 'observabilityCases', 'savedObjectsManagement', 'savedObjectsTagging', 'ml', diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index fdb8b2187bbbb..63063514555b3 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -8,60 +8,65 @@ import { VectorTile } from '@mapbox/vector-tile'; import Protobuf from 'pbf'; import expect from '@kbn/expect'; -import { - KBN_IS_CENTROID_FEATURE, - MVT_SOURCE_LAYER_NAME, -} from '../../../../plugins/maps/common/constants'; export default function ({ getService }) { const supertest = getService('supertest'); - describe('getGridTile', () => { + // FLAKY: https://github.com/elastic/kibana/issues/116186 + describe.skip('getGridTile', () => { it('should return vector tile containing cluster features', async () => { const resp = await supertest .get( `/api/maps/mvt/getGridTile/3/2/3.pbf\ ?geometryFieldName=geo.coordinates\ &index=logstash-*\ -&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(avg_of_bytes:(avg:(field:bytes)),gridCentroid:(geo_centroid:(field:geo.coordinates))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),fields:!((field:%27@timestamp%27,format:date_time),(field:%27relatedContent.article:modified_time%27,format:date_time),(field:%27relatedContent.article:published_time%27,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27@timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))\ -&requestType=point\ -&geoFieldType=geo_point` +&requestBody=(_source:(excludes:!()),aggs:(avg_of_bytes:(avg:(field:bytes))),fields:!((field:%27@timestamp%27,format:date_time),(field:%27relatedContent.article:modified_time%27,format:date_time),(field:%27relatedContent.article:published_time%27,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27@timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))\ +&requestType=point` ) .set('kbn-xsrf', 'kibana') .responseType('blob') .expect(200); const jsonTile = new VectorTile(new Protobuf(resp.body)); - const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(2); // Cluster feature + const layer = jsonTile.layers.aggs; + expect(layer.length).to.be(1); const clusterFeature = layer.feature(0); expect(clusterFeature.type).to.be(1); expect(clusterFeature.extent).to.be(4096); expect(clusterFeature.id).to.be(undefined); - expect(clusterFeature.properties).to.eql({ doc_count: 1, avg_of_bytes: 9252 }); + expect(clusterFeature.properties).to.eql({ _count: 1, 'avg_of_bytes.value': 9252 }); expect(clusterFeature.loadGeometry()).to.eql([[{ x: 87, y: 667 }]]); // Metadata feature - const metadataFeature = layer.feature(1); + const metaDataLayer = jsonTile.layers.meta; + expect(metaDataLayer.length).to.be(1); + const metadataFeature = metaDataLayer.feature(0); expect(metadataFeature.type).to.be(3); expect(metadataFeature.extent).to.be(4096); - expect(metadataFeature.properties).to.eql({ - __kbn_metadata_feature__: true, - __kbn_feature_count__: 1, - __kbn_is_tile_complete__: true, - __kbn_vector_shape_type_counts__: '{"POINT":1,"LINE":0,"POLYGON":0}', - fieldMeta: - '{"doc_count":{"range":{"min":1,"max":1,"delta":0},"categories":{"categories":[{"key":1,"count":1}]}},"avg_of_bytes":{"range":{"min":9252,"max":9252,"delta":0},"categories":{"categories":[{"key":9252,"count":1}]}}}', - }); + + expect(metadataFeature.properties['aggregations._count.avg']).to.eql(1); + expect(metadataFeature.properties['aggregations._count.count']).to.eql(1); + expect(metadataFeature.properties['aggregations._count.min']).to.eql(1); + expect(metadataFeature.properties['aggregations._count.sum']).to.eql(1); + + expect(metadataFeature.properties['aggregations.avg_of_bytes.avg']).to.eql(9252); + expect(metadataFeature.properties['aggregations.avg_of_bytes.count']).to.eql(1); + expect(metadataFeature.properties['aggregations.avg_of_bytes.max']).to.eql(9252); + expect(metadataFeature.properties['aggregations.avg_of_bytes.min']).to.eql(9252); + expect(metadataFeature.properties['aggregations.avg_of_bytes.sum']).to.eql(9252); + + expect(metadataFeature.properties['hits.total.relation']).to.eql('eq'); + expect(metadataFeature.properties['hits.total.value']).to.eql(1); + expect(metadataFeature.loadGeometry()).to.eql([ [ - { x: 0, y: 0 }, - { x: 4096, y: 0 }, - { x: 4096, y: 4096 }, { x: 0, y: 4096 }, + { x: 4096, y: 4096 }, + { x: 4096, y: 0 }, { x: 0, y: 0 }, + { x: 0, y: 4096 }, ], ]); }); @@ -72,65 +77,62 @@ export default function ({ getService }) { `/api/maps/mvt/getGridTile/3/2/3.pbf\ ?geometryFieldName=geo.coordinates\ &index=logstash-*\ -&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(avg_of_bytes:(avg:(field:bytes)),gridCentroid:(geo_centroid:(field:geo.coordinates))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),fields:!((field:%27@timestamp%27,format:date_time),(field:%27relatedContent.article:modified_time%27,format:date_time),(field:%27relatedContent.article:published_time%27,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27@timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))\ -&requestType=grid\ -&geoFieldType=geo_point` +&requestBody=(_source:(excludes:!()),aggs:(avg_of_bytes:(avg:(field:bytes))),fields:!((field:%27@timestamp%27,format:date_time),(field:%27relatedContent.article:modified_time%27,format:date_time),(field:%27relatedContent.article:published_time%27,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27@timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))\ +&requestType=grid` ) .set('kbn-xsrf', 'kibana') .responseType('blob') .expect(200); const jsonTile = new VectorTile(new Protobuf(resp.body)); - const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(3); + const layer = jsonTile.layers.aggs; + expect(layer.length).to.be(1); const gridFeature = layer.feature(0); expect(gridFeature.type).to.be(3); expect(gridFeature.extent).to.be(4096); expect(gridFeature.id).to.be(undefined); - expect(gridFeature.properties).to.eql({ doc_count: 1, avg_of_bytes: 9252 }); + expect(gridFeature.properties).to.eql({ _count: 1, 'avg_of_bytes.value': 9252 }); expect(gridFeature.loadGeometry()).to.eql([ [ - { x: 96, y: 640 }, - { x: 96, y: 672 }, { x: 64, y: 672 }, - { x: 64, y: 640 }, + { x: 96, y: 672 }, { x: 96, y: 640 }, + { x: 64, y: 640 }, + { x: 64, y: 672 }, ], ]); // Metadata feature - const metadataFeature = layer.feature(1); + const metaDataLayer = jsonTile.layers.meta; + expect(metaDataLayer.length).to.be(1); + const metadataFeature = metaDataLayer.feature(0); expect(metadataFeature.type).to.be(3); expect(metadataFeature.extent).to.be(4096); - expect(metadataFeature.properties).to.eql({ - __kbn_metadata_feature__: true, - __kbn_feature_count__: 1, - __kbn_is_tile_complete__: true, - __kbn_vector_shape_type_counts__: '{"POINT":0,"LINE":0,"POLYGON":1}', - fieldMeta: - '{"doc_count":{"range":{"min":1,"max":1,"delta":0},"categories":{"categories":[{"key":1,"count":1}]}},"avg_of_bytes":{"range":{"min":9252,"max":9252,"delta":0},"categories":{"categories":[{"key":9252,"count":1}]}}}', - }); + + expect(metadataFeature.properties['aggregations._count.avg']).to.eql(1); + expect(metadataFeature.properties['aggregations._count.count']).to.eql(1); + expect(metadataFeature.properties['aggregations._count.min']).to.eql(1); + expect(metadataFeature.properties['aggregations._count.sum']).to.eql(1); + + expect(metadataFeature.properties['aggregations.avg_of_bytes.avg']).to.eql(9252); + expect(metadataFeature.properties['aggregations.avg_of_bytes.count']).to.eql(1); + expect(metadataFeature.properties['aggregations.avg_of_bytes.max']).to.eql(9252); + expect(metadataFeature.properties['aggregations.avg_of_bytes.min']).to.eql(9252); + expect(metadataFeature.properties['aggregations.avg_of_bytes.sum']).to.eql(9252); + + expect(metadataFeature.properties['hits.total.relation']).to.eql('eq'); + expect(metadataFeature.properties['hits.total.value']).to.eql(1); + expect(metadataFeature.loadGeometry()).to.eql([ [ - { x: 0, y: 0 }, - { x: 4096, y: 0 }, - { x: 4096, y: 4096 }, { x: 0, y: 4096 }, + { x: 4096, y: 4096 }, + { x: 4096, y: 0 }, { x: 0, y: 0 }, + { x: 0, y: 4096 }, ], ]); - - const clusterFeature = layer.feature(2); - expect(clusterFeature.type).to.be(1); - expect(clusterFeature.extent).to.be(4096); - expect(clusterFeature.id).to.be(undefined); - expect(clusterFeature.properties).to.eql({ - doc_count: 1, - avg_of_bytes: 9252, - [KBN_IS_CENTROID_FEATURE]: true, - }); - expect(clusterFeature.loadGeometry()).to.eql([[{ x: 80, y: 656 }]]); }); }); } diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index 9705064464843..699ff145aa1b1 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -8,7 +8,6 @@ import { VectorTile } from '@mapbox/vector-tile'; import Protobuf from 'pbf'; import expect from '@kbn/expect'; -import { MVT_SOURCE_LAYER_NAME } from '../../../../plugins/maps/common/constants'; function findFeature(layer, callbackFn) { for (let i = 0; i < layer.length; i++) { @@ -23,22 +22,21 @@ export default function ({ getService }) { const supertest = getService('supertest'); describe('getTile', () => { - it('should return vector tile containing document', async () => { + it('should return ES vector tile containing documents and metadata', async () => { const resp = await supertest .get( `/api/maps/mvt/getTile/2/1/1.pbf\ ?geometryFieldName=geo.coordinates\ &index=logstash-*\ -&requestBody=(_source:!f,docvalue_fields:!(bytes,geo.coordinates,machine.os.raw),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(),size:10000,stored_fields:!(bytes,geo.coordinates,machine.os.raw))\ -&geoFieldType=geo_point` +&requestBody=(_source:!f,docvalue_fields:!(bytes,geo.coordinates,machine.os.raw),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(),size:10000,stored_fields:!(bytes,geo.coordinates,machine.os.raw))` ) .set('kbn-xsrf', 'kibana') .responseType('blob') .expect(200); const jsonTile = new VectorTile(new Protobuf(resp.body)); - const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(3); // 2 docs + the metadata feature + const layer = jsonTile.layers.hits; + expect(layer.length).to.be(2); // 2 docs // Verify ES document @@ -50,82 +48,32 @@ export default function ({ getService }) { expect(feature.extent).to.be(4096); expect(feature.id).to.be(undefined); expect(feature.properties).to.eql({ - __kbn__feature_id__: 'logstash-2015.09.20:AU_x3_BsGFA8no6Qjjug:0', _id: 'AU_x3_BsGFA8no6Qjjug', _index: 'logstash-2015.09.20', bytes: 9252, - ['machine.os.raw']: 'ios', + 'machine.os.raw': 'ios', }); expect(feature.loadGeometry()).to.eql([[{ x: 44, y: 2382 }]]); // Verify metadata feature - const metadataFeature = findFeature(layer, (feature) => { - return feature.properties.__kbn_metadata_feature__; - }); + const metaDataLayer = jsonTile.layers.meta; + const metadataFeature = metaDataLayer.feature(0); expect(metadataFeature).not.to.be(undefined); expect(metadataFeature.type).to.be(3); expect(metadataFeature.extent).to.be(4096); expect(metadataFeature.id).to.be(undefined); - const fieldMeta = JSON.parse(metadataFeature.properties.fieldMeta); - delete metadataFeature.properties.fieldMeta; - expect(metadataFeature.properties).to.eql({ - __kbn_feature_count__: 2, - __kbn_is_tile_complete__: true, - __kbn_metadata_feature__: true, - __kbn_vector_shape_type_counts__: '{"POINT":2,"LINE":0,"POLYGON":0}', - }); - expect(fieldMeta.bytes.range).to.eql({ - min: 9252, - max: 9583, - delta: 331, - }); - expect(fieldMeta.bytes.categories.categories.length).to.be(2); - expect(fieldMeta['machine.os.raw'].categories.categories.length).to.be(2); - expect(metadataFeature.loadGeometry()).to.eql([ - [ - { x: 0, y: 4096 }, - { x: 0, y: 0 }, - { x: 4096, y: 0 }, - { x: 4096, y: 4096 }, - { x: 0, y: 4096 }, - ], - ]); - }); - it('should return vector tile containing bounds when count exceeds size', async () => { - const resp = await supertest - // requestBody sets size=1 to force count exceeded - .get( - `/api/maps/mvt/getTile/2/1/1.pbf\ -?geometryFieldName=geo.coordinates\ -&index=logstash-*\ -&requestBody=(_source:!f,docvalue_fields:!(bytes,geo.coordinates,machine.os.raw),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(),size:1,stored_fields:!(bytes,geo.coordinates,machine.os.raw))\ -&geoFieldType=geo_point` - ) - .set('kbn-xsrf', 'kibana') - .responseType('blob') - .expect(200); + // This is dropping some irrelevant properties from the comparison + expect(metadataFeature.properties['hits.total.relation']).to.eql('eq'); + expect(metadataFeature.properties['hits.total.value']).to.eql(2); + expect(metadataFeature.properties.timed_out).to.eql(false); - const jsonTile = new VectorTile(new Protobuf(resp.body)); - const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(1); - - const metadataFeature = layer.feature(0); - expect(metadataFeature.type).to.be(3); - expect(metadataFeature.extent).to.be(4096); - expect(metadataFeature.id).to.be(undefined); - expect(metadataFeature.properties).to.eql({ - __kbn_metadata_feature__: true, - __kbn_feature_count__: 0, - __kbn_is_tile_complete__: false, - __kbn_vector_shape_type_counts__: '{"POINT":0,"LINE":0,"POLYGON":0}', - }); expect(metadataFeature.loadGeometry()).to.eql([ [ { x: 44, y: 2382 }, - { x: 44, y: 1913 }, - { x: 550, y: 1913 }, { x: 550, y: 2382 }, + { x: 550, y: 1913 }, + { x: 44, y: 1913 }, { x: 44, y: 2382 }, ], ]); diff --git a/x-pack/test/api_integration/apis/ml/index.ts b/x-pack/test/api_integration/apis/ml/index.ts index e44d0cd10e9f2..9b530873ad165 100644 --- a/x-pack/test/api_integration/apis/ml/index.ts +++ b/x-pack/test/api_integration/apis/ml/index.ts @@ -44,6 +44,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/ml/ecommerce'); await esArchiver.unload('x-pack/test/functional/es_archives/ml/categorization'); + await esArchiver.unload('x-pack/test/functional/es_archives/ml/categorization_small'); await esArchiver.unload('x-pack/test/functional/es_archives/ml/module_apache'); await esArchiver.unload('x-pack/test/functional/es_archives/ml/module_auditbeat'); await esArchiver.unload('x-pack/test/functional/es_archives/ml/module_apm'); diff --git a/x-pack/test/api_integration/apis/ml/jobs/categorization_field_examples.ts b/x-pack/test/api_integration/apis/ml/jobs/categorization_field_examples.ts index 4686787ae9b16..9d6009bbb3ea6 100644 --- a/x-pack/test/api_integration/apis/ml/jobs/categorization_field_examples.ts +++ b/x-pack/test/api_integration/apis/ml/jobs/categorization_field_examples.ts @@ -64,7 +64,7 @@ const analyzer = { ], }; const defaultRequestBody = { - indexPatternTitle: 'ft_categorization', + indexPatternTitle: 'ft_categorization_small', query: { bool: { must: [{ match_all: {} }] } }, size: 5, timeField: '@timestamp', @@ -286,7 +286,7 @@ export default ({ getService }: FtrProviderContext) => { describe('Categorization example endpoint - ', function () { before(async () => { - await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/categorization'); + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/categorization_small'); await ml.testResources.setKibanaTimeZoneToUTC(); }); diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index f234855b84e17..4938334bb936b 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -28,6 +28,7 @@ export default function ({ getService }: FtrProviderContext) { savedObjectsTagging: ['all', 'read'], canvas: ['all', 'read'], maps: ['all', 'read'], + observabilityCases: ['all', 'read'], fleet: ['all', 'read'], actions: ['all', 'read'], stackAlerts: ['all', 'read'], diff --git a/x-pack/test/api_integration/apis/security/privileges_basic.ts b/x-pack/test/api_integration/apis/security/privileges_basic.ts index ac69bfcd9d5d4..e6fe9d87af6f3 100644 --- a/x-pack/test/api_integration/apis/security/privileges_basic.ts +++ b/x-pack/test/api_integration/apis/security/privileges_basic.ts @@ -30,6 +30,7 @@ export default function ({ getService }: FtrProviderContext) { savedObjectsTagging: ['all', 'read'], graph: ['all', 'read'], maps: ['all', 'read'], + observabilityCases: ['all', 'read'], canvas: ['all', 'read'], infrastructure: ['all', 'read'], logs: ['all', 'read'], diff --git a/x-pack/test/apm_api_integration/common/trace_data.ts b/x-pack/test/apm_api_integration/common/trace_data.ts index 84bbb4beea4f4..4e813efab2913 100644 --- a/x-pack/test/apm_api_integration/common/trace_data.ts +++ b/x-pack/test/apm_api_integration/common/trace_data.ts @@ -10,7 +10,7 @@ import { getSpanDestinationMetrics, getTransactionMetrics, toElasticsearchOutput, -} from '@elastic/apm-generator'; +} from '@elastic/apm-synthtrace'; import { chunk } from 'lodash'; import pLimit from 'p-limit'; import { inspect } from 'util'; @@ -20,15 +20,20 @@ export async function traceData(context: InheritedFtrProviderContext) { const es = context.getService('es'); return { index: (events: any[]) => { - const esEvents = toElasticsearchOutput( - [ + const esEvents = toElasticsearchOutput({ + events: [ ...events, ...getTransactionMetrics(events), ...getSpanDestinationMetrics(events), ...getBreakdownMetrics(events), ], - '7.14.0' - ); + writeTargets: { + transaction: 'apm-7.14.0-transaction', + span: 'apm-7.14.0-span', + error: 'apm-7.14.0-error', + metric: 'apm-7.14.0-metric', + }, + }); const batches = chunk(esEvents, 1000); const limiter = pLimit(1); diff --git a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts index 75ea10ed4d9d4..ac81b6d5a4412 100644 --- a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts +++ b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { mean, meanBy, sumBy } from 'lodash'; import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types'; diff --git a/x-pack/test/apm_api_integration/tests/latency/service_apis.ts b/x-pack/test/apm_api_integration/tests/latency/service_apis.ts index a09442cd73a2a..c6ecf9e4a4aba 100644 --- a/x-pack/test/apm_api_integration/tests/latency/service_apis.ts +++ b/x-pack/test/apm_api_integration/tests/latency/service_apis.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { meanBy, sumBy } from 'lodash'; import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types'; diff --git a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts index 458372196452a..af95f981a3dc5 100644 --- a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts +++ b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { meanBy, sumBy } from 'lodash'; import { FtrProviderContext } from '../../common/ftr_provider_context'; diff --git a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts index 5585a292d317e..68979795f9dcf 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts @@ -8,7 +8,7 @@ import expect from '@kbn/expect'; import { pick, sortBy } from 'lodash'; import moment from 'moment'; -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi'; import { isFiniteNumber } from '../../../../plugins/apm/common/utils/is_finite_number'; import { FtrProviderContext } from '../../common/ftr_provider_context'; diff --git a/x-pack/test/apm_api_integration/tests/services/throughput.ts b/x-pack/test/apm_api_integration/tests/services/throughput.ts index 561680e2725cf..e98ab60af8ca4 100644 --- a/x-pack/test/apm_api_integration/tests/services/throughput.ts +++ b/x-pack/test/apm_api_integration/tests/services/throughput.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { first, last, meanBy } from 'lodash'; import moment from 'moment'; diff --git a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts index 4b3820ee7f033..4df40d1d85d56 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { meanBy, sumBy } from 'lodash'; import { BackendNode, ServiceNode } from '../../../../plugins/apm/common/connections'; diff --git a/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts b/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts index 6bf0e8c14fb23..00e5e57c546dd 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { meanBy, sumBy } from 'lodash'; import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types'; diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts index 100d3c306b7de..acdd12f3501bf 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { service, timerange } from '@elastic/apm-generator'; +import { service, timerange } from '@elastic/apm-synthtrace'; import expect from '@kbn/expect'; import { first, isEmpty, last, meanBy } from 'lodash'; import moment from 'moment'; diff --git a/x-pack/test/case_api_integration/common/config.ts b/x-pack/test/case_api_integration/common/config.ts index 2658472a7b84d..284b4360dacf8 100644 --- a/x-pack/test/case_api_integration/common/config.ts +++ b/x-pack/test/case_api_integration/common/config.ts @@ -118,7 +118,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) `--xpack.actions.allowedHosts=${JSON.stringify(['localhost', 'some.non.existent.com'])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.eventLog.logEntries=true', - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), // Actions simulators plugin. Needed for testing push to external services. ...alertingPlugins.map( (pluginDir) => diff --git a/x-pack/test/case_api_integration/common/lib/utils.ts b/x-pack/test/case_api_integration/common/lib/utils.ts index 0a875f9f1e822..9d48aed32d55c 100644 --- a/x-pack/test/case_api_integration/common/lib/utils.ts +++ b/x-pack/test/case_api_integration/common/lib/utils.ts @@ -329,7 +329,7 @@ export const getServiceNowConnector = () => ({ }, config: { apiUrl: 'http://some.non.existent.com', - isLegacy: false, + usesTableApi: false, }, }); @@ -386,7 +386,7 @@ export const getServiceNowSIRConnector = () => ({ }, config: { apiUrl: 'http://some.non.existent.com', - isLegacy: false, + usesTableApi: false, }, }); diff --git a/x-pack/test/case_api_integration/security_and_spaces/tests/trial/configure/get_connectors.ts b/x-pack/test/case_api_integration/security_and_spaces/tests/trial/configure/get_connectors.ts index c3e737464f19b..a4e69ab928325 100644 --- a/x-pack/test/case_api_integration/security_and_spaces/tests/trial/configure/get_connectors.ts +++ b/x-pack/test/case_api_integration/security_and_spaces/tests/trial/configure/get_connectors.ts @@ -109,7 +109,7 @@ export default ({ getService }: FtrProviderContext): void => { name: 'ServiceNow Connector', config: { apiUrl: 'http://some.non.existent.com', - isLegacy: false, + usesTableApi: false, }, isPreconfigured: false, isMissingSecrets: false, @@ -121,7 +121,7 @@ export default ({ getService }: FtrProviderContext): void => { name: 'ServiceNow Connector', config: { apiUrl: 'http://some.non.existent.com', - isLegacy: false, + usesTableApi: false, }, isPreconfigured: false, isMissingSecrets: false, diff --git a/x-pack/test/case_api_integration/spaces_only/tests/trial/configure/get_connectors.ts b/x-pack/test/case_api_integration/spaces_only/tests/trial/configure/get_connectors.ts index 7b6848d1f301e..02b91c9f0b918 100644 --- a/x-pack/test/case_api_integration/spaces_only/tests/trial/configure/get_connectors.ts +++ b/x-pack/test/case_api_integration/spaces_only/tests/trial/configure/get_connectors.ts @@ -109,7 +109,7 @@ export default ({ getService }: FtrProviderContext): void => { name: 'ServiceNow Connector', config: { apiUrl: 'http://some.non.existent.com', - isLegacy: false, + usesTableApi: false, }, isPreconfigured: false, isMissingSecrets: false, @@ -121,7 +121,7 @@ export default ({ getService }: FtrProviderContext): void => { name: 'ServiceNow Connector', config: { apiUrl: 'http://some.non.existent.com', - isLegacy: false, + usesTableApi: false, }, isPreconfigured: false, isMissingSecrets: false, diff --git a/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts b/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts index 7cfdf87aaf9ea..6f6d29db1ef0c 100644 --- a/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts +++ b/x-pack/test/functional/apps/apm/feature_controls/apm_security.ts @@ -64,6 +64,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const navLinks = await appsMenu.readLinks(); expect(navLinks.map((link) => link.text)).to.eql([ 'Overview', + 'Alerts', 'APM', 'User Experience', 'Stack Management', @@ -116,7 +117,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows apm navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'APM', 'User Experience', 'Stack Management']); + expect(navLinks).to.eql([ + 'Overview', + 'Alerts', + 'APM', + 'User Experience', + 'Stack Management', + ]); }); it('can navigate to APM app', async () => { diff --git a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts index 5b80f6589281a..1575948610566 100644 --- a/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts +++ b/x-pack/test/functional/apps/dev_tools/feature_controls/dev_tools_security.ts @@ -192,7 +192,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }); }); - describe('no dev_tools privileges', () => { + // FLAKY: https://github.com/elastic/kibana/issues/113080 + describe.skip('no dev_tools privileges', () => { before(async () => { await security.role.create('no_dev_tools_privileges_role', { kibana: [ diff --git a/x-pack/test/functional/apps/discover/saved_searches.ts b/x-pack/test/functional/apps/discover/saved_searches.ts index 16deecde2b0ba..f2abc6b350e5b 100644 --- a/x-pack/test/functional/apps/discover/saved_searches.ts +++ b/x-pack/test/functional/apps/discover/saved_searches.ts @@ -31,6 +31,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }; // Failing: See https://github.com/elastic/kibana/issues/104578 + // FLAKY: https://github.com/elastic/kibana/issues/114002 describe.skip('Discover Saved Searches', () => { before('initialize tests', async () => { await esArchiver.load('x-pack/test/functional/es_archives/reporting/ecommerce'); diff --git a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts index 65b9019f556fd..d6e8737b72b91 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/infrastructure_security.ts @@ -62,7 +62,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows metrics navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Metrics', 'Stack Management']); + expect(navLinks).to.eql(['Overview', 'Alerts', 'Metrics', 'Stack Management']); }); describe('infrastructure landing page without data', () => { @@ -159,7 +159,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows metrics navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Metrics', 'Stack Management']); + expect(navLinks).to.eql(['Overview', 'Alerts', 'Metrics', 'Stack Management']); }); describe('infrastructure landing page without data', () => { diff --git a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts index d120a6c582c7b..d4f56ee3c9b9b 100644 --- a/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts +++ b/x-pack/test/functional/apps/infra/feature_controls/logs_security.ts @@ -59,7 +59,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows logs navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Logs', 'Stack Management']); + expect(navLinks).to.eql(['Overview', 'Alerts', 'Logs', 'Stack Management']); }); describe('logs landing page without data', () => { @@ -121,7 +121,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows logs navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Logs', 'Stack Management']); + expect(navLinks).to.eql(['Overview', 'Alerts', 'Logs', 'Stack Management']); }); describe('logs landing page without data', () => { diff --git a/x-pack/test/functional/apps/lens/error_handling.ts b/x-pack/test/functional/apps/lens/error_handling.ts new file mode 100644 index 0000000000000..99263ddbc9bee --- /dev/null +++ b/x-pack/test/functional/apps/lens/error_handling.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const PageObjects = getPageObjects([ + 'visualize', + 'lens', + 'header', + 'timePicker', + 'common', + 'navigationalSearch', + ]); + const security = getService('security'); + const listingTable = getService('listingTable'); + const kibanaServer = getService('kibanaServer'); + + describe('Lens error handling', () => { + before(async () => { + await security.testUser.setRoles( + ['global_discover_read', 'global_visualize_read', 'test_logstash_reader'], + false + ); + // loading an object without reference fails, so we load data view + lens object and then unload data view + await kibanaServer.importExport.load( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/errors' + ); + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/errors2' + ); + }); + + after(async () => { + await security.testUser.restoreDefaults(); + await kibanaServer.importExport.unload( + 'x-pack/test/functional/fixtures/kbn_archiver/lens/errors' + ); + }); + + describe('Index Pattern missing', () => { + it('the warning is shown and user can fix the state', async () => { + await PageObjects.visualize.gotoVisualizationLandingPage(); + await listingTable.searchForItemWithName('lnsMetricWithNonExistingDataView'); + await PageObjects.lens.clickVisualizeListItemTitle('lnsMetricWithNonExistingDataView'); + await PageObjects.lens.waitForMissingDataViewWarning(); + await PageObjects.lens.switchToVisualization('lnsDatatable'); + await PageObjects.lens.waitForMissingDataViewWarning(); + await PageObjects.lens.switchToVisualization('donut'); + await PageObjects.lens.waitForMissingDataViewWarning(); + await PageObjects.lens.switchToVisualization('line'); + await PageObjects.lens.waitForMissingDataViewWarning(); + await PageObjects.lens.openDimensionEditor('lnsXY_yDimensionPanel > lns-dimensionTrigger'); + await PageObjects.lens.closeDimensionEditor(); + await PageObjects.lens.dragDimensionToDimension( + 'lnsXY_yDimensionPanel > lns-dimensionTrigger', + 'lnsXY_yDimensionPanel > lns-empty-dimension' + ); + await PageObjects.lens.switchFirstLayerIndexPattern('log*'); + await PageObjects.lens.waitForMissingDataViewWarningDisappear(); + await PageObjects.lens.waitForEmptyWorkspace(); + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/lens/index.ts b/x-pack/test/functional/apps/lens/index.ts index 5241d9724abb9..86ceb4812ad3b 100644 --- a/x-pack/test/functional/apps/lens/index.ts +++ b/x-pack/test/functional/apps/lens/index.ts @@ -56,6 +56,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./heatmap')); loadTestFile(require.resolve('./reference_lines')); loadTestFile(require.resolve('./inspector')); + loadTestFile(require.resolve('./error_handling')); // 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/smokescreen.ts b/x-pack/test/functional/apps/lens/smokescreen.ts index ff5bae8aa7e61..7cacee6446723 100644 --- a/x-pack/test/functional/apps/lens/smokescreen.ts +++ b/x-pack/test/functional/apps/lens/smokescreen.ts @@ -256,7 +256,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should show value labels on bar charts when enabled', async () => { // enable value labels await PageObjects.lens.openVisualOptions(); - await testSubjects.click('lnsXY_valueLabels_inside'); + await testSubjects.click('lns_valueLabels_inside'); await PageObjects.lens.waitForVisualization(); diff --git a/x-pack/test/functional/apps/maps/mapbox_styles.js b/x-pack/test/functional/apps/maps/mapbox_styles.js index 58c69950590cf..471e7440822c5 100644 --- a/x-pack/test/functional/apps/maps/mapbox_styles.js +++ b/x-pack/test/functional/apps/maps/mapbox_styles.js @@ -6,10 +6,6 @@ */ import expect from '@kbn/expect'; -import { - KBN_IS_TILE_COMPLETE, - KBN_METADATA_FEATURE, -} from '../../../../plugins/maps/common/constants'; export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['maps']); @@ -44,7 +40,6 @@ export default function ({ getPageObjects, getService }) { maxzoom: 24, filter: [ 'all', - ['!=', ['get', '__kbn_metadata_feature__'], true], ['!=', ['get', '__kbn_is_centroid_feature__'], true], ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']], ['==', ['get', '__kbn_isvisibleduetojoin__'], true], @@ -125,7 +120,6 @@ export default function ({ getPageObjects, getService }) { maxzoom: 24, filter: [ 'all', - ['!=', ['get', '__kbn_metadata_feature__'], true], ['!=', ['get', '__kbn_is_centroid_feature__'], true], ['any', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'MultiPolygon']], ['==', ['get', '__kbn_isvisibleduetojoin__'], true], @@ -202,7 +196,6 @@ export default function ({ getPageObjects, getService }) { maxzoom: 24, filter: [ 'all', - ['!=', ['get', '__kbn_metadata_feature__'], true], ['!=', ['get', '__kbn_is_centroid_feature__'], true], [ 'any', @@ -217,26 +210,5 @@ export default function ({ getPageObjects, getService }) { paint: { 'line-color': '#41937c', 'line-opacity': 0.75, 'line-width': 1 }, }); }); - - it('should style incomplete data layer as expected', async () => { - const layer = mapboxStyle.layers.find((mbLayer) => { - return mbLayer.id === 'n1t6f_toomanyfeatures'; - }); - - expect(layer).to.eql({ - id: 'n1t6f_toomanyfeatures', - type: 'fill', - source: 'n1t6f', - minzoom: 0, - maxzoom: 24, - filter: [ - 'all', - ['==', ['get', KBN_METADATA_FEATURE], true], - ['==', ['get', KBN_IS_TILE_COMPLETE], false], - ], - layout: { visibility: 'visible' }, - paint: { 'fill-pattern': '__kbn_too_many_features_image_id__', 'fill-opacity': 0.75 }, - }); - }); }); } diff --git a/x-pack/test/functional/apps/maps/mvt_scaling.js b/x-pack/test/functional/apps/maps/mvt_scaling.js index 66a511f6e9fec..d9b660ba0d730 100644 --- a/x-pack/test/functional/apps/maps/mvt_scaling.js +++ b/x-pack/test/functional/apps/maps/mvt_scaling.js @@ -31,7 +31,7 @@ export default function ({ getPageObjects, getService }) { //Source should be correct expect( mapboxStyle.sources[VECTOR_SOURCE_ID].tiles[0].startsWith( - `/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=geometry&index=geo_shapes*&requestBody=(_source:!(geometry),docvalue_fields:!(prop1),query:(bool:(filter:!(),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(),size:10001,stored_fields:!(geometry,prop1))&geoFieldType=geo_shape` + `/api/maps/mvt/getTile/{z}/{x}/{y}.pbf?geometryFieldName=geometry&index=geo_shapes*&requestBody=(_source:!(geometry),docvalue_fields:!(prop1),query:(bool:(filter:!(),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(),size:10001,stored_fields:!(geometry,prop1))` ) ).to.equal(true); @@ -77,5 +77,34 @@ export default function ({ getPageObjects, getService }) { 'fill-opacity': 1, }); }); + + it('Style should include toomanyfeatures layer', async () => { + const mapboxStyle = await PageObjects.maps.getMapboxStyle(); + + const layer = mapboxStyle.layers.find((mbLayer) => { + return mbLayer.id === `${VECTOR_SOURCE_ID}_toomanyfeatures`; + }); + + expect(layer).to.eql({ + id: 'caffa63a-ebfb-466d-8ff6-d797975b88ab_toomanyfeatures', + type: 'line', + source: 'caffa63a-ebfb-466d-8ff6-d797975b88ab', + 'source-layer': 'meta', + minzoom: 0, + maxzoom: 24, + filter: [ + 'all', + ['==', ['get', 'hits.total.relation'], 'gte'], + ['>=', ['get', 'hits.total.value'], 10002], + ], + layout: { visibility: 'visible' }, + paint: { + 'line-color': '#fec514', + 'line-width': 3, + 'line-dasharray': [2, 1], + 'line-opacity': 1, + }, + }); + }); }); } diff --git a/x-pack/test/functional/apps/maps/mvt_super_fine.js b/x-pack/test/functional/apps/maps/mvt_super_fine.js index dcd2923cb9335..6c5065a77c1d2 100644 --- a/x-pack/test/functional/apps/maps/mvt_super_fine.js +++ b/x-pack/test/functional/apps/maps/mvt_super_fine.js @@ -34,7 +34,7 @@ export default function ({ getPageObjects, getService }) { //Source should be correct expect( mapboxStyle.sources[MB_VECTOR_SOURCE_ID].tiles[0].startsWith( - `/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=geo.coordinates&index=logstash-*&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:geo.coordinates)),max_of_bytes:(max:(field:bytes))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),fields:!((field:'@timestamp',format:date_time),(field:'relatedContent.article:modified_time',format:date_time),(field:'relatedContent.article:published_time',format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((range:('@timestamp':(format:strict_date_optional_time,gte:'2015-09-20T00:00:00.000Z',lte:'2015-09-20T01:00:00.000Z')))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:'doc[!'@timestamp!'].value.getHour()'))),size:0,stored_fields:!('*'))&requestType=grid&geoFieldType=geo_point` + `/api/maps/mvt/getGridTile/{z}/{x}/{y}.pbf?geometryFieldName=geo.coordinates&index=logstash-*&requestBody=(_source:(excludes:!()),aggs:(max_of_bytes:(max:(field:bytes))),fields:!((field:'@timestamp',format:date_time),(field:'relatedContent.article:modified_time',format:date_time),(field:'relatedContent.article:published_time',format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((range:('@timestamp':(format:strict_date_optional_time,gte:'2015-09-20T00:00:00.000Z',lte:'2015-09-20T01:00:00.000Z')))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:'doc[!'@timestamp!'].value.getHour()'))),size:0,stored_fields:!('*'))&requestType=grid` ) ).to.equal(true); @@ -51,9 +51,9 @@ export default function ({ getPageObjects, getService }) { 'coalesce', [ 'case', - ['==', ['get', 'max_of_bytes'], null], + ['==', ['get', 'max_of_bytes.value'], null], 1622, - ['max', ['min', ['to-number', ['get', 'max_of_bytes']], 9790], 1623], + ['max', ['min', ['to-number', ['get', 'max_of_bytes.value']], 9790], 1623], ], 1622, ], diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts index 7e07ac82c9dcf..a494b401480d6 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/classification_creation.ts @@ -53,7 +53,7 @@ export default function ({ getService }: FtrProviderContext) { // tick/grid/axis { color: '#DDDDDD', percentage: 50 }, // line - { color: '#98A2B3', percentage: 30 }, + { color: '#98A2B3', percentage: 10 }, ], scatterplotMatrixColorStats: [ // marker colors diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/feature_importance.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/feature_importance.ts index 8561487dff7cb..3faee67c01a53 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/feature_importance.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/feature_importance.ts @@ -14,7 +14,8 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); - describe('total feature importance panel and decision path popover', function () { + // FLAKY: https://github.com/elastic/kibana/issues/116078 + describe.skip('total feature importance panel and decision path popover', function () { const testDataList: Array<{ suiteTitle: string; archive: string; 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 3e6b644a0b494..c1e5d0b4b6aae 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index.ts @@ -9,9 +9,10 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('data visualizer', function () { - this.tags(['skipFirefox']); + this.tags(['skipFirefox', 'mlqa']); loadTestFile(require.resolve('./index_data_visualizer')); + loadTestFile(require.resolve('./index_data_visualizer_grid_in_discover')); loadTestFile(require.resolve('./index_data_visualizer_actions_panel')); loadTestFile(require.resolve('./index_data_visualizer_index_pattern_management')); loadTestFile(require.resolve('./file_data_visualizer')); diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts index 542f7f3116c94..ff0d489293682 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer.ts @@ -6,374 +6,18 @@ */ import { FtrProviderContext } from '../../../ftr_provider_context'; -import { ML_JOB_FIELD_TYPES } from '../../../../../plugins/ml/common/constants/field_types'; -import { FieldVisConfig } from '../../../../../plugins/data_visualizer/public/application/common/components/stats_table/types'; - -interface MetricFieldVisConfig extends FieldVisConfig { - statsMaxDecimalPlaces: number; - docCountFormatted: string; - topValuesCount: number; - viewableInLens: boolean; -} - -interface NonMetricFieldVisConfig extends FieldVisConfig { - docCountFormatted: string; - exampleCount: number; - viewableInLens: boolean; -} - -interface TestData { - suiteTitle: string; - sourceIndexOrSavedSearch: string; - fieldNameFilters: string[]; - fieldTypeFilters: string[]; - rowsPerPage?: 10 | 25 | 50; - sampleSizeValidations: Array<{ - size: number; - expected: { field: string; docCountFormatted: string }; - }>; - expected: { - totalDocCountFormatted: string; - metricFields?: MetricFieldVisConfig[]; - nonMetricFields?: NonMetricFieldVisConfig[]; - emptyFields: string[]; - visibleMetricFieldsCount: number; - totalMetricFieldsCount: number; - populatedFieldsCount: number; - totalFieldsCount: number; - fieldNameFiltersResultCount: number; - fieldTypeFiltersResultCount: number; - }; -} +import { TestData, MetricFieldVisConfig } from './types'; +import { + farequoteDataViewTestData, + farequoteKQLSearchTestData, + farequoteLuceneSearchTestData, + sampleLogTestData, +} from './index_test_data'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); - const farequoteDataViewTestData: TestData = { - suiteTitle: 'data view', - sourceIndexOrSavedSearch: 'ft_farequote', - fieldNameFilters: ['airline', '@timestamp'], - fieldTypeFilters: [ML_JOB_FIELD_TYPES.KEYWORD], - sampleSizeValidations: [ - { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, - { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, - ], - expected: { - totalDocCountFormatted: '86,274', - metricFields: [ - { - fieldName: 'responsetime', - type: ML_JOB_FIELD_TYPES.NUMBER, - existsInDocs: true, - aggregatable: true, - loading: false, - docCountFormatted: '5000 (100%)', - statsMaxDecimalPlaces: 3, - topValuesCount: 10, - viewableInLens: true, - }, - ], - nonMetricFields: [ - { - fieldName: '@timestamp', - type: ML_JOB_FIELD_TYPES.DATE, - existsInDocs: true, - aggregatable: true, - loading: false, - docCountFormatted: '5000 (100%)', - exampleCount: 2, - viewableInLens: true, - }, - { - fieldName: '@version', - type: ML_JOB_FIELD_TYPES.TEXT, - existsInDocs: true, - aggregatable: false, - loading: false, - exampleCount: 1, - docCountFormatted: '', - viewableInLens: false, - }, - { - fieldName: '@version.keyword', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 1, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - { - fieldName: 'airline', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 10, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - { - fieldName: 'type', - type: ML_JOB_FIELD_TYPES.TEXT, - existsInDocs: true, - aggregatable: false, - loading: false, - exampleCount: 1, - docCountFormatted: '', - viewableInLens: false, - }, - { - fieldName: 'type.keyword', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 1, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - ], - emptyFields: ['sourcetype'], - visibleMetricFieldsCount: 1, - totalMetricFieldsCount: 1, - populatedFieldsCount: 7, - totalFieldsCount: 8, - fieldNameFiltersResultCount: 2, - fieldTypeFiltersResultCount: 3, - }, - }; - - const farequoteKQLSearchTestData: TestData = { - suiteTitle: 'KQL saved search', - sourceIndexOrSavedSearch: 'ft_farequote_kuery', - fieldNameFilters: ['@version'], - fieldTypeFilters: [ML_JOB_FIELD_TYPES.DATE, ML_JOB_FIELD_TYPES.TEXT], - sampleSizeValidations: [ - { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, - { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, - ], - expected: { - totalDocCountFormatted: '34,415', - metricFields: [ - { - fieldName: 'responsetime', - type: ML_JOB_FIELD_TYPES.NUMBER, - existsInDocs: true, - aggregatable: true, - loading: false, - docCountFormatted: '5000 (100%)', - statsMaxDecimalPlaces: 3, - topValuesCount: 10, - viewableInLens: true, - }, - ], - nonMetricFields: [ - { - fieldName: '@timestamp', - type: ML_JOB_FIELD_TYPES.DATE, - existsInDocs: true, - aggregatable: true, - loading: false, - docCountFormatted: '5000 (100%)', - exampleCount: 2, - viewableInLens: true, - }, - { - fieldName: '@version', - type: ML_JOB_FIELD_TYPES.TEXT, - existsInDocs: true, - aggregatable: false, - loading: false, - exampleCount: 1, - docCountFormatted: '', - viewableInLens: false, - }, - { - fieldName: '@version.keyword', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 1, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - { - fieldName: 'airline', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 5, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - { - fieldName: 'type', - type: ML_JOB_FIELD_TYPES.TEXT, - existsInDocs: true, - aggregatable: false, - loading: false, - exampleCount: 1, - docCountFormatted: '', - viewableInLens: false, - }, - { - fieldName: 'type.keyword', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 1, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - ], - emptyFields: ['sourcetype'], - visibleMetricFieldsCount: 1, - totalMetricFieldsCount: 1, - populatedFieldsCount: 7, - totalFieldsCount: 8, - fieldNameFiltersResultCount: 1, - fieldTypeFiltersResultCount: 3, - }, - }; - - const farequoteLuceneSearchTestData: TestData = { - suiteTitle: 'lucene saved search', - sourceIndexOrSavedSearch: 'ft_farequote_lucene', - fieldNameFilters: ['@version.keyword', 'type'], - fieldTypeFilters: [ML_JOB_FIELD_TYPES.NUMBER], - sampleSizeValidations: [ - { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, - { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, - ], - expected: { - totalDocCountFormatted: '34,416', - metricFields: [ - { - fieldName: 'responsetime', - type: ML_JOB_FIELD_TYPES.NUMBER, - existsInDocs: true, - aggregatable: true, - loading: false, - docCountFormatted: '5000 (100%)', - statsMaxDecimalPlaces: 3, - topValuesCount: 10, - viewableInLens: true, - }, - ], - nonMetricFields: [ - { - fieldName: '@timestamp', - type: ML_JOB_FIELD_TYPES.DATE, - existsInDocs: true, - aggregatable: true, - loading: false, - docCountFormatted: '5000 (100%)', - exampleCount: 2, - viewableInLens: true, - }, - { - fieldName: '@version', - type: ML_JOB_FIELD_TYPES.TEXT, - existsInDocs: true, - aggregatable: false, - loading: false, - exampleCount: 1, - docCountFormatted: '', - viewableInLens: false, - }, - { - fieldName: '@version.keyword', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 1, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - { - fieldName: 'airline', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 5, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - { - fieldName: 'type', - type: ML_JOB_FIELD_TYPES.TEXT, - existsInDocs: true, - aggregatable: false, - loading: false, - exampleCount: 1, - docCountFormatted: '', - viewableInLens: false, - }, - { - fieldName: 'type.keyword', - type: ML_JOB_FIELD_TYPES.KEYWORD, - existsInDocs: true, - aggregatable: true, - loading: false, - exampleCount: 1, - docCountFormatted: '5000 (100%)', - viewableInLens: true, - }, - ], - emptyFields: ['sourcetype'], - visibleMetricFieldsCount: 1, - totalMetricFieldsCount: 1, - populatedFieldsCount: 7, - totalFieldsCount: 8, - fieldNameFiltersResultCount: 2, - fieldTypeFiltersResultCount: 1, - }, - }; - - const sampleLogTestData: TestData = { - suiteTitle: 'geo point field', - sourceIndexOrSavedSearch: 'ft_module_sample_logs', - fieldNameFilters: ['geo.coordinates'], - fieldTypeFilters: [ML_JOB_FIELD_TYPES.GEO_POINT], - rowsPerPage: 50, - expected: { - totalDocCountFormatted: '408', - metricFields: [], - // only testing the geo_point fields - nonMetricFields: [ - { - fieldName: 'geo.coordinates', - type: ML_JOB_FIELD_TYPES.GEO_POINT, - existsInDocs: true, - aggregatable: true, - loading: false, - docCountFormatted: '408 (100%)', - exampleCount: 10, - viewableInLens: false, - }, - ], - emptyFields: [], - visibleMetricFieldsCount: 4, - totalMetricFieldsCount: 5, - populatedFieldsCount: 35, - totalFieldsCount: 36, - fieldNameFiltersResultCount: 1, - fieldTypeFiltersResultCount: 1, - }, - sampleSizeValidations: [ - { size: 1000, expected: { field: 'geo.coordinates', docCountFormatted: '408 (100%)' } }, - { size: 5000, expected: { field: '@timestamp', docCountFormatted: '408 (100%)' } }, - ], - }; - function runTests(testData: TestData) { it(`${testData.suiteTitle} loads the source data in the data visualizer`, async () => { await ml.testExecution.logTestStep( @@ -541,7 +185,7 @@ export default function ({ getService }: FtrProviderContext) { }); describe('with module_sample_logs ', function () { - // Run tests on full farequote index. + // Run tests on full ft_module_sample_logs index. it(`${sampleLogTestData.suiteTitle} loads the data visualizer selector page`, async () => { // Start navigation from the base of the ML app. await ml.navigation.navigateToMl(); diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_grid_in_discover.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_grid_in_discover.ts new file mode 100644 index 0000000000000..ba24684e13036 --- /dev/null +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_data_visualizer_grid_in_discover.ts @@ -0,0 +1,172 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { TestData, MetricFieldVisConfig } from './types'; + +const SHOW_FIELD_STATISTICS = 'discover:showFieldStatistics'; +import { + farequoteDataViewTestData, + farequoteKQLSearchTestData, + farequoteLuceneFiltersSearchTestData, + farequoteKQLFiltersSearchTestData, + farequoteLuceneSearchTestData, + sampleLogTestData, +} from './index_test_data'; +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const esArchiver = getService('esArchiver'); + const PageObjects = getPageObjects(['common', 'discover', 'timePicker', 'settings']); + const ml = getService('ml'); + const testSubjects = getService('testSubjects'); + const retry = getService('retry'); + const toasts = getService('toasts'); + + const selectIndexPattern = async (indexPattern: string) => { + await retry.tryForTime(2 * 1000, async () => { + await PageObjects.discover.selectIndexPattern(indexPattern); + const indexPatternTitle = await testSubjects.getVisibleText('indexPattern-switch-link'); + expect(indexPatternTitle).to.be(indexPattern); + }); + }; + + const clearAdvancedSetting = async (propertyName: string) => { + await retry.tryForTime(2 * 1000, async () => { + await PageObjects.common.navigateToUrl('management', 'kibana/settings', { + shouldUseHashForSubUrl: false, + }); + if ((await PageObjects.settings.getAdvancedSettingCheckbox(propertyName)) === 'true') { + await PageObjects.settings.clearAdvancedSettings(propertyName); + } + }); + }; + + const setAdvancedSettingCheckbox = async (propertyName: string, checkedState: boolean) => { + await retry.tryForTime(2 * 1000, async () => { + await PageObjects.common.navigateToUrl('management', 'kibana/settings', { + shouldUseHashForSubUrl: false, + }); + await testSubjects.click('settings'); + await toasts.dismissAllToasts(); + await PageObjects.settings.toggleAdvancedSettingCheckbox(propertyName, checkedState); + }); + }; + + function runTestsWhenDisabled(testData: TestData) { + it('should not show view mode toggle or Field stats table', async function () { + await PageObjects.common.navigateToApp('discover'); + if (testData.isSavedSearch) { + await retry.tryForTime(2 * 1000, async () => { + await PageObjects.discover.loadSavedSearch(testData.sourceIndexOrSavedSearch); + }); + } else { + await selectIndexPattern(testData.sourceIndexOrSavedSearch); + } + + await PageObjects.timePicker.setAbsoluteRange( + 'Jan 1, 2016 @ 00:00:00.000', + 'Nov 1, 2020 @ 00:00:00.000' + ); + + await PageObjects.discover.assertViewModeToggleNotExists(); + await PageObjects.discover.assertFieldStatsTableNotExists(); + }); + } + + function runTests(testData: TestData) { + describe(`with ${testData.suiteTitle}`, function () { + it(`displays the 'Field statistics' table content correctly`, async function () { + await PageObjects.common.navigateToApp('discover'); + if (testData.isSavedSearch) { + await retry.tryForTime(2 * 1000, async () => { + await PageObjects.discover.loadSavedSearch(testData.sourceIndexOrSavedSearch); + }); + } else { + await selectIndexPattern(testData.sourceIndexOrSavedSearch); + } + await PageObjects.timePicker.setAbsoluteRange( + 'Jan 1, 2016 @ 00:00:00.000', + 'Nov 1, 2020 @ 00:00:00.000' + ); + + await PageObjects.discover.assertHitCount(testData.expected.totalDocCountFormatted); + await PageObjects.discover.assertViewModeToggleExists(); + await PageObjects.discover.clickViewModeFieldStatsButton(); + await ml.testExecution.logTestStep( + 'displays details for metric fields and non-metric fields correctly' + ); + for (const fieldRow of testData.expected.metricFields as Array< + Required + >) { + await ml.dataVisualizerTable.assertNumberFieldContents( + fieldRow.fieldName, + fieldRow.docCountFormatted, + fieldRow.topValuesCount, + fieldRow.viewableInLens + ); + } + + for (const fieldRow of testData.expected.nonMetricFields!) { + await ml.dataVisualizerTable.assertNonMetricFieldContents( + fieldRow.type, + fieldRow.fieldName!, + fieldRow.docCountFormatted, + fieldRow.exampleCount, + fieldRow.viewableInLens, + false, + fieldRow.exampleContent + ); + } + }); + }); + } + + describe('field statistics in Discover', function () { + before(async function () { + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote'); + await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/module_sample_logs'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + await ml.testResources.createIndexPatternIfNeeded('ft_module_sample_logs', '@timestamp'); + await ml.testResources.createSavedSearchFarequoteKueryIfNeeded(); + await ml.testResources.createSavedSearchFarequoteLuceneIfNeeded(); + await ml.testResources.createSavedSearchFarequoteFilterAndLuceneIfNeeded(); + await ml.testResources.createSavedSearchFarequoteFilterAndKueryIfNeeded(); + + await ml.securityUI.loginAsMlPowerUser(); + }); + + after(async function () { + await clearAdvancedSetting(SHOW_FIELD_STATISTICS); + }); + + describe('when enabled', function () { + before(async function () { + await setAdvancedSettingCheckbox(SHOW_FIELD_STATISTICS, true); + }); + + after(async function () { + await clearAdvancedSetting(SHOW_FIELD_STATISTICS); + }); + + runTests(farequoteDataViewTestData); + runTests(farequoteKQLSearchTestData); + runTests(farequoteLuceneSearchTestData); + runTests(farequoteKQLFiltersSearchTestData); + runTests(farequoteLuceneFiltersSearchTestData); + runTests(sampleLogTestData); + }); + + describe('when disabled', function () { + before(async function () { + // Ensure that the setting is set to default state which is false + await setAdvancedSettingCheckbox(SHOW_FIELD_STATISTICS, false); + }); + + runTestsWhenDisabled(farequoteDataViewTestData); + }); + }); +} diff --git a/x-pack/test/functional/apps/ml/data_visualizer/index_test_data.ts b/x-pack/test/functional/apps/ml/data_visualizer/index_test_data.ts new file mode 100644 index 0000000000000..6dd782487fdf8 --- /dev/null +++ b/x-pack/test/functional/apps/ml/data_visualizer/index_test_data.ts @@ -0,0 +1,533 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TestData } from './types'; +import { ML_JOB_FIELD_TYPES } from '../../../../../plugins/ml/common/constants/field_types'; + +export const farequoteDataViewTestData: TestData = { + suiteTitle: 'farequote index pattern', + isSavedSearch: false, + sourceIndexOrSavedSearch: 'ft_farequote', + fieldNameFilters: ['airline', '@timestamp'], + fieldTypeFilters: [ML_JOB_FIELD_TYPES.KEYWORD], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], + expected: { + totalDocCountFormatted: '86,274', + metricFields: [ + { + fieldName: 'responsetime', + type: ML_JOB_FIELD_TYPES.NUMBER, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + statsMaxDecimalPlaces: 3, + topValuesCount: 10, + viewableInLens: true, + }, + ], + nonMetricFields: [ + { + fieldName: '@timestamp', + type: ML_JOB_FIELD_TYPES.DATE, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + exampleCount: 2, + viewableInLens: true, + }, + { + fieldName: '@version', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: '@version.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'airline', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 10, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'type', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: 'type.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + ], + emptyFields: ['sourcetype'], + visibleMetricFieldsCount: 1, + totalMetricFieldsCount: 1, + populatedFieldsCount: 7, + totalFieldsCount: 8, + fieldNameFiltersResultCount: 2, + fieldTypeFiltersResultCount: 3, + }, +}; + +export const farequoteKQLSearchTestData: TestData = { + suiteTitle: 'KQL saved search', + isSavedSearch: true, + sourceIndexOrSavedSearch: 'ft_farequote_kuery', + fieldNameFilters: ['@version'], + fieldTypeFilters: [ML_JOB_FIELD_TYPES.DATE, ML_JOB_FIELD_TYPES.TEXT], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], + expected: { + totalDocCountFormatted: '34,415', + metricFields: [ + { + fieldName: 'responsetime', + type: ML_JOB_FIELD_TYPES.NUMBER, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + statsMaxDecimalPlaces: 3, + topValuesCount: 10, + viewableInLens: true, + }, + ], + nonMetricFields: [ + { + fieldName: '@timestamp', + type: ML_JOB_FIELD_TYPES.DATE, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + exampleCount: 2, + viewableInLens: true, + }, + { + fieldName: '@version', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: '@version.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'airline', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 5, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'type', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: 'type.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + ], + emptyFields: ['sourcetype'], + visibleMetricFieldsCount: 1, + totalMetricFieldsCount: 1, + populatedFieldsCount: 7, + totalFieldsCount: 8, + fieldNameFiltersResultCount: 1, + fieldTypeFiltersResultCount: 3, + }, +}; + +export const farequoteKQLFiltersSearchTestData: TestData = { + suiteTitle: 'KQL saved search and filters', + isSavedSearch: true, + sourceIndexOrSavedSearch: 'ft_farequote_filter_and_kuery', + fieldNameFilters: ['@version'], + fieldTypeFilters: [ML_JOB_FIELD_TYPES.DATE, ML_JOB_FIELD_TYPES.TEXT], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], + expected: { + totalDocCountFormatted: '5,674', + metricFields: [ + { + fieldName: 'responsetime', + type: ML_JOB_FIELD_TYPES.NUMBER, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + statsMaxDecimalPlaces: 3, + topValuesCount: 10, + viewableInLens: true, + }, + ], + nonMetricFields: [ + { + fieldName: '@timestamp', + type: ML_JOB_FIELD_TYPES.DATE, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + exampleCount: 2, + viewableInLens: true, + }, + { + fieldName: '@version', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: '@version.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'airline', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + exampleContent: ['ASA'], + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'type', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: 'type.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + ], + emptyFields: ['sourcetype'], + visibleMetricFieldsCount: 1, + totalMetricFieldsCount: 1, + populatedFieldsCount: 7, + totalFieldsCount: 8, + fieldNameFiltersResultCount: 1, + fieldTypeFiltersResultCount: 3, + }, +}; + +export const farequoteLuceneSearchTestData: TestData = { + suiteTitle: 'lucene saved search', + isSavedSearch: true, + sourceIndexOrSavedSearch: 'ft_farequote_lucene', + fieldNameFilters: ['@version.keyword', 'type'], + fieldTypeFilters: [ML_JOB_FIELD_TYPES.NUMBER], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], + expected: { + totalDocCountFormatted: '34,416', + metricFields: [ + { + fieldName: 'responsetime', + type: ML_JOB_FIELD_TYPES.NUMBER, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + statsMaxDecimalPlaces: 3, + topValuesCount: 10, + viewableInLens: true, + }, + ], + nonMetricFields: [ + { + fieldName: '@timestamp', + type: ML_JOB_FIELD_TYPES.DATE, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + exampleCount: 2, + viewableInLens: true, + }, + { + fieldName: '@version', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: '@version.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'airline', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 5, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'type', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: 'type.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + ], + emptyFields: ['sourcetype'], + visibleMetricFieldsCount: 1, + totalMetricFieldsCount: 1, + populatedFieldsCount: 7, + totalFieldsCount: 8, + fieldNameFiltersResultCount: 2, + fieldTypeFiltersResultCount: 1, + }, +}; + +export const farequoteLuceneFiltersSearchTestData: TestData = { + suiteTitle: 'lucene saved search and filter', + isSavedSearch: true, + sourceIndexOrSavedSearch: 'ft_farequote_filter_and_lucene', + fieldNameFilters: ['@version.keyword', 'type'], + fieldTypeFilters: [ML_JOB_FIELD_TYPES.NUMBER], + sampleSizeValidations: [ + { size: 1000, expected: { field: 'airline', docCountFormatted: '1000 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '5000 (100%)' } }, + ], + expected: { + totalDocCountFormatted: '5,673', + metricFields: [ + { + fieldName: 'responsetime', + type: ML_JOB_FIELD_TYPES.NUMBER, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + statsMaxDecimalPlaces: 3, + topValuesCount: 10, + viewableInLens: true, + }, + ], + nonMetricFields: [ + { + fieldName: '@timestamp', + type: ML_JOB_FIELD_TYPES.DATE, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '5000 (100%)', + exampleCount: 2, + viewableInLens: true, + }, + { + fieldName: '@version', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: '@version.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'airline', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + exampleContent: ['ASA'], + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + { + fieldName: 'type', + type: ML_JOB_FIELD_TYPES.TEXT, + existsInDocs: true, + aggregatable: false, + loading: false, + exampleCount: 1, + docCountFormatted: '', + viewableInLens: false, + }, + { + fieldName: 'type.keyword', + type: ML_JOB_FIELD_TYPES.KEYWORD, + existsInDocs: true, + aggregatable: true, + loading: false, + exampleCount: 1, + docCountFormatted: '5000 (100%)', + viewableInLens: true, + }, + ], + emptyFields: ['sourcetype'], + visibleMetricFieldsCount: 1, + totalMetricFieldsCount: 1, + populatedFieldsCount: 7, + totalFieldsCount: 8, + fieldNameFiltersResultCount: 2, + fieldTypeFiltersResultCount: 1, + }, +}; + +export const sampleLogTestData: TestData = { + suiteTitle: 'geo point field', + isSavedSearch: false, + sourceIndexOrSavedSearch: 'ft_module_sample_logs', + fieldNameFilters: ['geo.coordinates'], + fieldTypeFilters: [ML_JOB_FIELD_TYPES.GEO_POINT], + rowsPerPage: 50, + expected: { + totalDocCountFormatted: '408', + metricFields: [], + // only testing the geo_point fields + nonMetricFields: [ + { + fieldName: 'geo.coordinates', + type: ML_JOB_FIELD_TYPES.GEO_POINT, + existsInDocs: true, + aggregatable: true, + loading: false, + docCountFormatted: '408 (100%)', + exampleCount: 10, + viewableInLens: false, + }, + ], + emptyFields: [], + visibleMetricFieldsCount: 4, + totalMetricFieldsCount: 5, + populatedFieldsCount: 35, + totalFieldsCount: 36, + fieldNameFiltersResultCount: 1, + fieldTypeFiltersResultCount: 1, + }, + sampleSizeValidations: [ + { size: 1000, expected: { field: 'geo.coordinates', docCountFormatted: '408 (100%)' } }, + { size: 5000, expected: { field: '@timestamp', docCountFormatted: '408 (100%)' } }, + ], +}; diff --git a/x-pack/test/functional/apps/ml/data_visualizer/types.ts b/x-pack/test/functional/apps/ml/data_visualizer/types.ts new file mode 100644 index 0000000000000..5c3f890dba561 --- /dev/null +++ b/x-pack/test/functional/apps/ml/data_visualizer/types.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 { FieldVisConfig } from '../../../../../plugins/data_visualizer/public/application/common/components/stats_table/types'; + +export interface MetricFieldVisConfig extends FieldVisConfig { + statsMaxDecimalPlaces: number; + docCountFormatted: string; + topValuesCount: number; + viewableInLens: boolean; +} + +export interface NonMetricFieldVisConfig extends FieldVisConfig { + docCountFormatted: string; + exampleCount: number; + exampleContent?: string[]; + viewableInLens: boolean; +} + +export interface TestData { + suiteTitle: string; + isSavedSearch?: boolean; + sourceIndexOrSavedSearch: string; + fieldNameFilters: string[]; + fieldTypeFilters: string[]; + rowsPerPage?: 10 | 25 | 50; + sampleSizeValidations: Array<{ + size: number; + expected: { field: string; docCountFormatted: string }; + }>; + expected: { + totalDocCountFormatted: string; + metricFields?: MetricFieldVisConfig[]; + nonMetricFields?: NonMetricFieldVisConfig[]; + emptyFields: string[]; + visibleMetricFieldsCount: number; + totalMetricFieldsCount: number; + populatedFieldsCount: number; + totalFieldsCount: number; + fieldNameFiltersResultCount: number; + fieldTypeFiltersResultCount: number; + }; +} diff --git a/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts b/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts index 7867170c1801c..977a384062f79 100644 --- a/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts +++ b/x-pack/test/functional/apps/uptime/feature_controls/uptime_security.ts @@ -68,6 +68,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const navLinks = await appsMenu.readLinks(); expect(navLinks.map((link) => link.text)).to.eql([ 'Overview', + 'Alerts', 'Uptime', 'Stack Management', ]); @@ -121,7 +122,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows uptime navlink', async () => { const navLinks = (await appsMenu.readLinks()).map((link) => link.text); - expect(navLinks).to.eql(['Overview', 'Uptime', 'Stack Management']); + expect(navLinks).to.eql(['Overview', 'Alerts', 'Uptime', 'Stack Management']); }); it('can navigate to Uptime app', async () => { diff --git a/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json b/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json index b3d33f5d45345..449731d9e4ab2 100644 --- a/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json +++ b/x-pack/test/functional/es_archives/endpoint/metadata/api_feature/data.json @@ -4,7 +4,7 @@ "id": "3KVN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "963b081e-60d1-482c-befd-a5815fa8290f", "version": "6.6.1", @@ -26,7 +26,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d14", "kind": "metric", "category": [ @@ -74,7 +74,7 @@ "id": "3aVN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "b3412d6f-b022-4448-8fee-21cc936ea86b", "version": "6.0.0", @@ -96,7 +96,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d15", "kind": "metric", "category": [ @@ -143,7 +143,7 @@ "id": "3qVN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "3838df35-a095-4af4-8fce-0b6d78793f2e", "version": "6.8.0", @@ -165,7 +165,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d16", "kind": "metric", "category": [ @@ -210,7 +210,7 @@ "id": "36VN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "963b081e-60d1-482c-befd-a5815fa8290f", "version": "6.6.1", @@ -232,7 +232,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d18", "kind": "metric", "category": [ @@ -280,7 +280,7 @@ "id": "4KVN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "b3412d6f-b022-4448-8fee-21cc936ea86b", "version": "6.0.0", @@ -302,7 +302,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d19", "kind": "metric", "category": [ @@ -348,7 +348,7 @@ "id": "4aVN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "3838df35-a095-4af4-8fce-0b6d78793f2e", "version": "6.8.0", @@ -370,7 +370,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d39", "kind": "metric", "category": [ @@ -416,7 +416,7 @@ "id": "4qVN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "963b081e-60d1-482c-befd-a5815fa8290f", "version": "6.6.1", @@ -438,7 +438,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d31", "kind": "metric", "category": [ @@ -485,7 +485,7 @@ "id": "46VN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "b3412d6f-b022-4448-8fee-21cc936ea86b", "version": "6.0.0", @@ -507,7 +507,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d23", "kind": "metric", "category": [ @@ -553,7 +553,7 @@ "id": "5KVN2G8BYQH1gtPUuYk7", "index": "metrics-endpoint.metadata-default", "source": { - "@timestamp": 1626897841950, + "@timestamp": 1634656952181, "agent": { "id": "3838df35-a095-4af4-8fce-0b6d78793f2e", "version": "6.8.0", @@ -575,7 +575,7 @@ } }, "event": { - "created": 1626897841950, + "created": 1634656952181, "id": "32f5fda2-48e4-4fae-b89e-a18038294d35", "kind": "metric", "category": [ diff --git a/x-pack/test/functional/es_archives/ml/categorization_small/data.json.gz b/x-pack/test/functional/es_archives/ml/categorization_small/data.json.gz new file mode 100644 index 0000000000000..76ac07831dec1 Binary files /dev/null and b/x-pack/test/functional/es_archives/ml/categorization_small/data.json.gz differ diff --git a/x-pack/test/functional/es_archives/ml/categorization_small/mappings.json b/x-pack/test/functional/es_archives/ml/categorization_small/mappings.json new file mode 100644 index 0000000000000..b73babf361625 --- /dev/null +++ b/x-pack/test/functional/es_archives/ml/categorization_small/mappings.json @@ -0,0 +1,41 @@ +{ + "type": "index", + "value": { + "aliases": {}, + "index": "ft_categorization_small", + "mappings": { + "properties": { + "@timestamp": { + "type": "date" + }, + "field1": { + "type": "text" + }, + "field2": { + "type": "text" + }, + "field3": { + "type": "text" + }, + "field4": { + "type": "text" + }, + "field5": { + "type": "text" + }, + "field6": { + "type": "text" + }, + "field7": { + "type": "text" + } + } + }, + "settings": { + "index": { + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} diff --git a/x-pack/test/functional/fixtures/kbn_archiver/lens/errors.json b/x-pack/test/functional/fixtures/kbn_archiver/lens/errors.json new file mode 100644 index 0000000000000..9ecc14164d863 --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/lens/errors.json @@ -0,0 +1,78 @@ +{ + "attributes": { + "fields": "[]", + "timeFieldName": "@timestamp", + "title": "nonExistingDataView" + }, + "coreMigrationVersion": "8.0.0", + "id": "nonExistingDataView", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2021-10-19T12:28:18.765Z", + "version": "WzU0ODUsMl0=" +} + +{ + "attributes": { + "description": "", + "state": { + "datasourceStates": { + "indexpattern": { + "layers": { + "eba8a330-0b65-46d4-8b1d-1528a0b53261": { + "columnOrder": [ + "eb55bd47-20ca-47fd-bf84-f72ac4b924ff" + ], + "columns": { + "eb55bd47-20ca-47fd-bf84-f72ac4b924ff": { + "dataType": "number", + "isBucketed": false, + "label": "Median of AvgTicketPrice", + "operationType": "median", + "scale": "ratio", + "sourceField": "AvgTicketPrice" + } + }, + "incompleteColumns": {} + } + } + } + }, + "filters": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "accessor": "eb55bd47-20ca-47fd-bf84-f72ac4b924ff", + "layerId": "eba8a330-0b65-46d4-8b1d-1528a0b53261", + "layerType": "data" + } + }, + "title": "lnsMetricWithNonExistingDataView", + "visualizationType": "lnsMetric" + }, + "coreMigrationVersion": "8.0.0", + "id": "3454af30-30e2-11ec-8dbc-f13e30d4f8ac", + "migrationVersion": { + "lens": "8.0.0" + }, + "references": [ + { + "id": "nonExistingDataView", + "name": "indexpattern-datasource-current-indexpattern", + "type": "index-pattern" + }, + { + "id": "nonExistingDataView", + "name": "indexpattern-datasource-layer-eba8a330-0b65-46d4-8b1d-1528a0b53261", + "type": "index-pattern" + } + ], + "type": "lens", + "updated_at": "2021-10-19T13:41:04.038Z", + "version": "WzU2NjEsMl0=" +} \ No newline at end of file diff --git a/x-pack/test/functional/fixtures/kbn_archiver/lens/errors2.json b/x-pack/test/functional/fixtures/kbn_archiver/lens/errors2.json new file mode 100644 index 0000000000000..cfaafd51ad728 --- /dev/null +++ b/x-pack/test/functional/fixtures/kbn_archiver/lens/errors2.json @@ -0,0 +1,16 @@ +{ + "attributes": { + "fields": "[]", + "timeFieldName": "@timestamp", + "title": "nonExistingDataView" + }, + "coreMigrationVersion": "8.0.0", + "id": "nonExistingDataView", + "migrationVersion": { + "index-pattern": "7.11.0" + }, + "references": [], + "type": "index-pattern", + "updated_at": "2021-10-19T12:28:18.765Z", + "version": "WzU0ODUsMl0=" +} diff --git a/x-pack/test/functional/page_objects/lens_page.ts b/x-pack/test/functional/page_objects/lens_page.ts index 01e860cf4bec5..790ac3ede496f 100644 --- a/x-pack/test/functional/page_objects/lens_page.ts +++ b/x-pack/test/functional/page_objects/lens_page.ts @@ -247,6 +247,18 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont }); }, + async waitForMissingDataViewWarning() { + await retry.try(async () => { + await testSubjects.existOrFail(`missing-refs-failure`); + }); + }, + + async waitForMissingDataViewWarningDisappear() { + await retry.try(async () => { + await testSubjects.missingOrFail(`missing-refs-failure`); + }); + }, + async waitForEmptyWorkspace() { await retry.try(async () => { await testSubjects.existOrFail(`empty-workspace`); @@ -688,7 +700,7 @@ export function LensPageProvider({ getService, getPageObjects }: FtrProviderCont */ async switchFirstLayerIndexPattern(name: string) { await testSubjects.click('lns_layerIndexPatternLabel'); - await find.clickByCssSelector(`[title="${name}"]`); + await find.clickByCssSelector(`.lnsChangeIndexPatternPopover [title="${name}"]`); await PageObjects.header.waitUntilLoadingHasFinished(); }, diff --git a/x-pack/test/functional/services/ml/custom_urls.ts b/x-pack/test/functional/services/ml/custom_urls.ts index 5b2bf0773719c..3d26236741a8a 100644 --- a/x-pack/test/functional/services/ml/custom_urls.ts +++ b/x-pack/test/functional/services/ml/custom_urls.ts @@ -169,7 +169,10 @@ export function MachineLearningCustomUrlsProvider({ async assertDiscoverCustomUrlAction(expectedHitCountFormatted: string) { await PageObjects.discover.waitForDiscoverAppOnScreen(); - await retry.tryForTime(5000, async () => { + // During cloud tests, the small browser width might cause hit count to be invisible + // so temporarily collapsing the sidebar ensures the count shows + await PageObjects.discover.closeSidebar(); + await retry.tryForTime(10 * 1000, async () => { const hitCount = await PageObjects.discover.getHitCount(); expect(hitCount).to.eql( expectedHitCountFormatted, diff --git a/x-pack/test/functional/services/ml/data_visualizer_table.ts b/x-pack/test/functional/services/ml/data_visualizer_table.ts index 8094f0ad1f8d2..860f2bd86bec7 100644 --- a/x-pack/test/functional/services/ml/data_visualizer_table.ts +++ b/x-pack/test/functional/services/ml/data_visualizer_table.ts @@ -361,7 +361,27 @@ export function MachineLearningDataVisualizerTableProvider( }); } - public async assertTopValuesContents(fieldName: string, expectedTopValuesCount: number) { + public async assertTopValuesContent(fieldName: string, expectedTopValues: string[]) { + const selector = this.detailsSelector(fieldName, 'dataVisualizerFieldDataTopValuesContent'); + const topValuesElement = await testSubjects.find(selector); + const topValuesBars = await topValuesElement.findAllByTestSubject( + 'dataVisualizerFieldDataTopValueBar' + ); + + const topValuesBarsValues = await Promise.all( + topValuesBars.map(async (bar) => { + const visibleText = await bar.getVisibleText(); + return visibleText ? visibleText.split('\n')[0] : undefined; + }) + ); + + expect(topValuesBarsValues).to.eql( + expectedTopValues, + `Expected top values for field '${fieldName}' to equal '${expectedTopValues}' (got '${topValuesBarsValues}')` + ); + } + + public async assertTopValuesCount(fieldName: string, expectedTopValuesCount: number) { const selector = this.detailsSelector(fieldName, 'dataVisualizerFieldDataTopValuesContent'); const topValuesElement = await testSubjects.find(selector); const topValuesBars = await topValuesElement.findAllByTestSubject( @@ -401,7 +421,7 @@ export function MachineLearningDataVisualizerTableProvider( await testSubjects.existOrFail( this.detailsSelector(fieldName, 'dataVisualizerFieldDataTopValues') ); - await this.assertTopValuesContents(fieldName, topValuesCount); + await this.assertTopValuesCount(fieldName, topValuesCount); if (checkDistributionPreviewExist) { await this.assertDistributionPreviewExist(fieldName); @@ -433,7 +453,8 @@ export function MachineLearningDataVisualizerTableProvider( public async assertKeywordFieldContents( fieldName: string, docCountFormatted: string, - topValuesCount: number + topValuesCount: number, + exampleContent?: string[] ) { await this.assertRowExists(fieldName); await this.assertFieldDocCount(fieldName, docCountFormatted); @@ -442,7 +463,11 @@ export function MachineLearningDataVisualizerTableProvider( await testSubjects.existOrFail( this.detailsSelector(fieldName, 'dataVisualizerFieldDataTopValuesContent') ); - await this.assertTopValuesContents(fieldName, topValuesCount); + await this.assertTopValuesCount(fieldName, topValuesCount); + + if (exampleContent) { + await this.assertTopValuesContent(fieldName, exampleContent); + } await this.ensureDetailsClosed(fieldName); } @@ -508,13 +533,19 @@ export function MachineLearningDataVisualizerTableProvider( docCountFormatted: string, exampleCount: number, viewableInLens: boolean, - hasActionMenu?: boolean + hasActionMenu?: boolean, + exampleContent?: string[] ) { // Currently the data used in the data visualizer tests only contains these field types. if (fieldType === ML_JOB_FIELD_TYPES.DATE) { await this.assertDateFieldContents(fieldName, docCountFormatted); } else if (fieldType === ML_JOB_FIELD_TYPES.KEYWORD) { - await this.assertKeywordFieldContents(fieldName, docCountFormatted, exampleCount); + await this.assertKeywordFieldContents( + fieldName, + docCountFormatted, + exampleCount, + exampleContent + ); } else if (fieldType === ML_JOB_FIELD_TYPES.TEXT) { await this.assertTextFieldContents(fieldName, docCountFormatted, exampleCount); } else if (fieldType === ML_JOB_FIELD_TYPES.GEO_POINT) { diff --git a/x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts b/x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts index 57a44a0b7952d..4d38e6a144a78 100644 --- a/x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts +++ b/x-pack/test/functional_basic/apps/ml/data_visualizer/index.ts @@ -19,6 +19,11 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile( require.resolve('../../../../functional/apps/ml/data_visualizer/index_data_visualizer') ); + loadTestFile( + require.resolve( + '../../../../functional/apps/ml/data_visualizer/index_data_visualizer_grid_in_discover' + ) + ); loadTestFile(require.resolve('./index_data_visualizer_actions_panel')); }); } diff --git a/x-pack/test/lists_api_integration/common/config.ts b/x-pack/test/lists_api_integration/common/config.ts index 4983f00cce044..214f03b632658 100644 --- a/x-pack/test/lists_api_integration/common/config.ts +++ b/x-pack/test/lists_api_integration/common/config.ts @@ -51,7 +51,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ...xPackApiIntegrationTestsConfig.get('kbnTestServer'), serverArgs: [ ...xPackApiIntegrationTestsConfig.get('kbnTestServer.serverArgs'), - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'alerts')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'actions')}`, `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'task_manager')}`, 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 5bb7d9926af54..dcf6b121d6258 100644 --- a/x-pack/test/observability_functional/with_rac_write.config.ts +++ b/x-pack/test/observability_functional/with_rac_write.config.ts @@ -36,10 +36,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), `--elasticsearch.hosts=https://${servers.elasticsearch.hostname}:${servers.elasticsearch.port}`, `--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`, - // TO DO: Remove feature flags once we're good to go - '--xpack.observability.unsafe.alertingExperience.enabled=true', - '--xpack.observability.unsafe.cases.enabled=true', - '--xpack.ruleRegistry.write.enabled=true', ], }, uiSettings: { diff --git a/x-pack/test/reporting_api_integration/reporting_without_security.config.ts b/x-pack/test/reporting_api_integration/reporting_without_security.config.ts index dfd79916b5ce0..0779b3b871e36 100644 --- a/x-pack/test/reporting_api_integration/reporting_without_security.config.ts +++ b/x-pack/test/reporting_api_integration/reporting_without_security.config.ts @@ -24,7 +24,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { }, kbnTestServer: { ...apiConfig.get('kbnTestServer'), - serverArgs: [...apiConfig.get('kbnTestServer.serverArgs'), `--xpack.security.enabled=false`], + serverArgs: [...apiConfig.get('kbnTestServer.serverArgs')], }, }; } diff --git a/x-pack/test/reporting_functional/reporting_without_security.config.ts b/x-pack/test/reporting_functional/reporting_without_security.config.ts index 0269f57bf08cb..7ca7f89a0b709 100644 --- a/x-pack/test/reporting_functional/reporting_without_security.config.ts +++ b/x-pack/test/reporting_functional/reporting_without_security.config.ts @@ -17,10 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testFiles: [resolve(__dirname, './reporting_without_security')], kbnTestServer: { ...reportingConfig.get('kbnTestServer'), - serverArgs: [ - ...reportingConfig.get('kbnTestServer.serverArgs'), - `--xpack.security.enabled=false`, - ], + serverArgs: [...reportingConfig.get('kbnTestServer.serverArgs')], }, esTestCluster: { ...reportingConfig.get('esTestCluster'), diff --git a/x-pack/test/rule_registry/common/config.ts b/x-pack/test/rule_registry/common/config.ts index 9cce58c30f6e9..6b920a6f5dbf2 100644 --- a/x-pack/test/rule_registry/common/config.ts +++ b/x-pack/test/rule_registry/common/config.ts @@ -79,7 +79,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) `--xpack.actions.allowedHosts=${JSON.stringify(['localhost', 'some.non.existent.com'])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.eventLog.logEntries=true', - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), // TO DO: Remove feature flags once we're good to go '--xpack.securitySolution.enableExperimental=["ruleRegistryEnabled"]', '--xpack.ruleRegistry.write.enabled=true', 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 9b9e46efa6d5d..8ca74c7fcea49 100644 --- a/x-pack/test/saved_object_api_integration/common/config.ts +++ b/x-pack/test/saved_object_api_integration/common/config.ts @@ -54,7 +54,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ...config.xpack.api.get('kbnTestServer.serverArgs'), '--server.xsrf.disableProtection=true', `--plugin-path=${path.join(__dirname, 'fixtures', 'saved_object_test_plugin')}`, - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), ], }, }; diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts index 90dd5123f5d36..48c0aea825048 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts @@ -20,8 +20,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const endpointTestResources = getService('endpointTestResources'); const policyTestResources = getService('policyTestResources'); - // failing ES promotion: https://github.com/elastic/kibana/issues/110309 - describe.skip('Endpoint permissions:', () => { + describe('Endpoint permissions:', () => { let indexedData: IndexedHostsAndAlertsResponse; before(async () => { @@ -62,7 +61,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.existOrFail('noIngestPermissions'); }); - it('should display endpoint data on Host Details', async () => { + // FIXME:PT skipped. need to fix security-team bug #1929 + it.skip('should display endpoint data on Host Details', async () => { const endpoint = indexedData.hosts[0]; await PageObjects.hosts.navigateToHostDetails(endpoint.host.name); const endpointSummary = await PageObjects.hosts.hostDetailsEndpointOverviewData(); diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts index 2dcf36cc42ae2..afdc364ffd970 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts @@ -24,8 +24,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); - // Failing: See https://github.com/elastic/kibana/issues/115488 - describe.skip('test metadata api', () => { + describe('test metadata api', () => { // TODO add this after endpoint package changes are merged and in snapshot // describe('with .metrics-endpoint.metadata_united_default index', () => { // }); @@ -242,7 +241,7 @@ export default function ({ getService }: FtrProviderContext) { (ip: string) => ip === targetEndpointIp ); expect(resultIp).to.eql([targetEndpointIp]); - expect(body.hosts[0].metadata.event.created).to.eql(1626897841950); + expect(body.hosts[0].metadata.event.created).to.eql(1634656952181); expect(body.hosts.length).to.eql(1); expect(body.request_page_size).to.eql(10); expect(body.request_page_index).to.eql(0); @@ -284,7 +283,7 @@ export default function ({ getService }: FtrProviderContext) { const resultElasticAgentId: string = body.hosts[0].metadata.elastic.agent.id; expect(resultHostId).to.eql(targetEndpointId); expect(resultElasticAgentId).to.eql(targetElasticAgentId); - expect(body.hosts[0].metadata.event.created).to.eql(1626897841950); + expect(body.hosts[0].metadata.event.created).to.eql(1634656952181); expect(body.hosts[0].host_status).to.eql('unhealthy'); expect(body.hosts.length).to.eql(1); expect(body.request_page_size).to.eql(10); diff --git a/x-pack/test/spaces_api_integration/common/config.ts b/x-pack/test/spaces_api_integration/common/config.ts index 7cceb945790d5..5d135cd05605c 100644 --- a/x-pack/test/spaces_api_integration/common/config.ts +++ b/x-pack/test/spaces_api_integration/common/config.ts @@ -61,7 +61,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) '--status.allowAnonymous=false', '--server.xsrf.disableProtection=true', `--plugin-path=${path.join(__dirname, 'fixtures', 'spaces_test_plugin')}`, - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), ], }, }; diff --git a/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json b/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json index 3b2a87d924e88..c1525409cfa3f 100644 --- a/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json +++ b/x-pack/test/spaces_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json @@ -153,7 +153,7 @@ "references": [ { "type": "index-pattern", - "id": "cts_ip_1", + "id": "cts_ip_1_default", "name": "CTS IP 1" } ], @@ -182,7 +182,7 @@ "references": [ { "type": "index-pattern", - "id": "cts_ip_1", + "id": "cts_ip_1_default", "name": "CTS IP 1" } ], @@ -212,7 +212,7 @@ "references": [ { "type": "index-pattern", - "id": "cts_ip_1", + "id": "cts_ip_1_default", "name": "CTS IP 1" } ], @@ -276,7 +276,7 @@ "references": [ { "type": "index-pattern", - "id": "cts_ip_1", + "id": "cts_ip_1_space_1", "name": "CTS IP 1" } ], @@ -305,7 +305,7 @@ "references": [ { "type": "index-pattern", - "id": "cts_ip_1", + "id": "cts_ip_1_space_1", "name": "CTS IP 1" } ], @@ -335,7 +335,7 @@ "references": [ { "type": "index-pattern", - "id": "cts_ip_1", + "id": "cts_ip_1_space_1", "name": "CTS IP 1" } ], @@ -350,15 +350,17 @@ { "type": "_doc", "value": { - "id": "index-pattern:cts_ip_1", + "id": "index-pattern:cts_ip_1_default", "index": ".kibana", "source": { + "originId": "cts_ip_1", "index-pattern": { "title": "Copy to Space index pattern 1 from default space" }, "references": [], "type": "index-pattern", - "updated_at": "2017-09-21T18:49:16.270Z" + "updated_at": "2017-09-21T18:49:16.270Z", + "namespaces": ["default"] }, "type": "_doc" } @@ -367,16 +369,17 @@ { "type": "_doc", "value": { - "id": "space_1:index-pattern:cts_ip_1", + "id": "index-pattern:cts_ip_1_space_1", "index": ".kibana", "source": { + "originId": "cts_ip_1", "index-pattern": { "title": "Copy to Space index pattern 1 from space_1 space" }, "references": [], "type": "index-pattern", "updated_at": "2017-09-21T18:49:16.270Z", - "namespace": "space_1" + "namespaces": ["space_1"] }, "type": "_doc" } diff --git a/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts b/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts index 3a3f0f889c91c..23136838f3002 100644 --- a/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts @@ -183,6 +183,8 @@ export function copyToSpaceTestSuiteFactory( const destination = getDestinationWithoutConflicts(); const result = resp.body as CopyResponse; + const indexPatternDestinationId = result[destination].successResults![0].destinationId; + expect(indexPatternDestinationId).to.match(UUID_PATTERN); // this was copied to space 2 and hit an unresolvable conflict, so the object ID was regenerated silently / the destinationId is a UUID const vis1DestinationId = result[destination].successResults![1].destinationId; expect(vis1DestinationId).to.match(UUID_PATTERN); // this was copied to space 2 and hit an unresolvable conflict, so the object ID was regenerated silently / the destinationId is a UUID const vis2DestinationId = result[destination].successResults![2].destinationId; @@ -196,12 +198,13 @@ export function copyToSpaceTestSuiteFactory( successCount: 5, successResults: [ { - id: 'cts_ip_1', + id: `cts_ip_1_${spaceId}`, type: 'index-pattern', meta: { icon: 'indexPatternApp', title: `Copy to Space index pattern 1 from ${spaceId} space`, }, + destinationId: indexPatternDestinationId, }, { id: `cts_vis_1_${spaceId}`, @@ -321,13 +324,14 @@ export function copyToSpaceTestSuiteFactory( successCount: 5, successResults: [ { - id: 'cts_ip_1', + id: `cts_ip_1_${spaceId}`, type: 'index-pattern', meta: { icon: 'indexPatternApp', title: `Copy to Space index pattern 1 from ${spaceId} space`, }, overwrite: true, + destinationId: `cts_ip_1_${destination}`, // this conflicted with another index pattern in the destination space because of a shared originId }, { id: `cts_vis_1_${spaceId}`, @@ -409,8 +413,11 @@ export function copyToSpaceTestSuiteFactory( }, }, { - error: { type: 'conflict' }, - id: 'cts_ip_1', + error: { + type: 'conflict', + destinationId: `cts_ip_1_${destination}`, // this conflicted with another index pattern in the destination space because of a shared originId + }, + id: `cts_ip_1_${spaceId}`, title: `Copy to Space index pattern 1 from ${spaceId} space`, type: 'index-pattern', meta: { diff --git a/x-pack/test/spaces_api_integration/common/suites/resolve_copy_to_space_conflicts.ts b/x-pack/test/spaces_api_integration/common/suites/resolve_copy_to_space_conflicts.ts index b190a37965b0b..72130743b69d9 100644 --- a/x-pack/test/spaces_api_integration/common/suites/resolve_copy_to_space_conflicts.ts +++ b/x-pack/test/spaces_api_integration/common/suites/resolve_copy_to_space_conflicts.ts @@ -82,8 +82,18 @@ export function resolveCopyToSpaceConflictsSuite( expect(result).to.eql({ [destination]: { success: true, - successCount: 1, + successCount: 2, successResults: [ + { + id: `cts_ip_1_${sourceSpaceId}`, + type: 'index-pattern', + meta: { + title: `Copy to Space index pattern 1 from ${sourceSpaceId} space`, + icon: 'indexPatternApp', + }, + destinationId: `cts_ip_1_${destination}`, // this conflicted with another index pattern in the destination space because of a shared originId + overwrite: true, + }, { id: `cts_vis_3_${sourceSpaceId}`, type: 'visualization', @@ -146,6 +156,19 @@ export function resolveCopyToSpaceConflictsSuite( success: false, successCount: 0, errors: [ + { + error: { + type: 'conflict', + destinationId: `cts_ip_1_${destination}`, // this conflicted with another index pattern in the destination space because of a shared originId + }, + id: `cts_ip_1_${sourceSpaceId}`, + title: `Copy to Space index pattern 1 from ${sourceSpaceId} space`, + meta: { + title: `Copy to Space index pattern 1 from ${sourceSpaceId} space`, + icon: 'indexPatternApp', + }, + type: 'index-pattern', + }, { error: { type: 'conflict', @@ -231,35 +254,7 @@ export function resolveCopyToSpaceConflictsSuite( { statusCode: 403, error: 'Forbidden', - message: 'Unable to bulk_get index-pattern', - }, - ], - }, - } as CopyResponse); - - // Query ES to ensure that nothing was copied - const [dashboard, visualization] = await getObjectsAtSpace(destination); - expect(dashboard.attributes.title).to.eql( - `This is the ${destination} test space CTS dashboard` - ); - expect(visualization.attributes.title).to.eql(`CTS vis 3 from ${destination} space`); - }; - - const createExpectReadonlyAtSpaceWithReferencesResult = - (spaceId: string = DEFAULT_SPACE_ID) => - async (resp: TestResponse) => { - const destination = getDestinationSpace(spaceId); - - const result = resp.body as CopyResponse; - expect(result).to.eql({ - [destination]: { - success: false, - successCount: 0, - errors: [ - { - statusCode: 403, - error: 'Forbidden', - message: 'Unable to bulk_create visualization', + message: 'Unable to bulk_create index-pattern,visualization', }, ], }, @@ -449,6 +444,7 @@ export function resolveCopyToSpaceConflictsSuite( const dashboardObject = { type: 'dashboard', id: 'cts_dashboard' }; const visualizationObject = { type: 'visualization', id: `cts_vis_3_${spaceId}` }; + const indexPatternObject = { type: 'index-pattern', id: `cts_ip_1_${spaceId}` }; it(`should return ${tests.withReferencesNotOverwriting.statusCode} when not overwriting, with references`, async () => { const destination = getDestinationSpace(spaceId); @@ -462,6 +458,11 @@ export function resolveCopyToSpaceConflictsSuite( createNewCopies: false, retries: { [destination]: [ + { + ...indexPatternObject, + destinationId: `cts_ip_1_${destination}`, + overwrite: false, + }, { ...visualizationObject, destinationId: `cts_vis_3_${destination}`, @@ -486,6 +487,11 @@ export function resolveCopyToSpaceConflictsSuite( createNewCopies: false, retries: { [destination]: [ + { + ...indexPatternObject, + destinationId: `cts_ip_1_${destination}`, + overwrite: true, + }, { ...visualizationObject, destinationId: `cts_vis_3_${destination}`, @@ -589,7 +595,6 @@ export function resolveCopyToSpaceConflictsSuite( createExpectNonOverriddenResponseWithReferences, createExpectNonOverriddenResponseWithoutReferences, createExpectUnauthorizedAtSpaceWithReferencesResult, - createExpectReadonlyAtSpaceWithReferencesResult, createExpectUnauthorizedAtSpaceWithoutReferencesResult, createMultiNamespaceTestCases, originSpaces: ['default', 'space_1'], diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/resolve_copy_to_space_conflicts.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/resolve_copy_to_space_conflicts.ts index efc7827cf8b9a..1b39cd5d77302 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/resolve_copy_to_space_conflicts.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/resolve_copy_to_space_conflicts.ts @@ -24,7 +24,6 @@ export default function resolveCopyToSpaceConflictsTestSuite({ getService }: Ftr createExpectOverriddenResponseWithoutReferences, expectRouteForbiddenResponse, createExpectUnauthorizedAtSpaceWithReferencesResult, - createExpectReadonlyAtSpaceWithReferencesResult, createExpectUnauthorizedAtSpaceWithoutReferencesResult, createMultiNamespaceTestCases, NON_EXISTENT_SPACE_ID, @@ -122,11 +121,11 @@ export default function resolveCopyToSpaceConflictsTestSuite({ getService }: Ftr tests: { withReferencesNotOverwriting: { statusCode: 200, - response: createExpectReadonlyAtSpaceWithReferencesResult(spaceId), + response: createExpectUnauthorizedAtSpaceWithReferencesResult(spaceId), }, withReferencesOverwriting: { statusCode: 200, - response: createExpectReadonlyAtSpaceWithReferencesResult(spaceId), + response: createExpectUnauthorizedAtSpaceWithReferencesResult(spaceId), }, withoutReferencesOverwriting: { statusCode: 200, diff --git a/x-pack/test/timeline/common/config.ts b/x-pack/test/timeline/common/config.ts index fa8ddb2ad10a7..211f380b133a5 100644 --- a/x-pack/test/timeline/common/config.ts +++ b/x-pack/test/timeline/common/config.ts @@ -79,7 +79,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) `--xpack.actions.allowedHosts=${JSON.stringify(['localhost', 'some.non.existent.com'])}`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, '--xpack.eventLog.logEntries=true', - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), // TO DO: Remove feature flags once we're good to go '--xpack.securitySolution.enableExperimental=["ruleRegistryEnabled"]', '--xpack.ruleRegistry.write.enabled=true', diff --git a/x-pack/test/ui_capabilities/common/config.ts b/x-pack/test/ui_capabilities/common/config.ts index 1f695e562da05..f676a5eeccee1 100644 --- a/x-pack/test/ui_capabilities/common/config.ts +++ b/x-pack/test/ui_capabilities/common/config.ts @@ -42,7 +42,9 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) ...xPackFunctionalTestsConfig.get('kbnTestServer'), serverArgs: [ ...xPackFunctionalTestsConfig.get('kbnTestServer.serverArgs'), - ...disabledPlugins.map((key) => `--xpack.${key}.enabled=false`), + ...disabledPlugins + .filter((k) => k !== 'security') + .map((key) => `--xpack.${key}.enabled=false`), `--plugin-path=${path.join(__dirname, 'fixtures', 'plugins', 'foo_plugin')}`, ], }, diff --git a/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts b/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts index b50f11553747c..e694b5be6e024 100644 --- a/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts +++ b/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts @@ -24,6 +24,13 @@ export default function catalogueTests({ getService }: FtrProviderContext) { 'watcher', ]; + const uiCapabilitiesExceptions = [ + // enterprise_search plugin is loaded but disabled because security isn't enabled in ES. That means the following 3 capabilities are disabled + 'enterpriseSearch', + 'appSearch', + 'workplaceSearch', + ]; + describe('catalogue', () => { SpaceScenarios.forEach((scenario) => { it(`${scenario.name}`, async () => { @@ -33,7 +40,10 @@ export default function catalogueTests({ getService }: FtrProviderContext) { expect(uiCapabilities.success).to.be(true); expect(uiCapabilities.value).to.have.property('catalogue'); // everything is enabled - const expected = mapValues(uiCapabilities.value!.catalogue, () => true); + const expected = mapValues( + uiCapabilities.value!.catalogue, + (enabled, catalogueId) => !uiCapabilitiesExceptions.includes(catalogueId) + ); expect(uiCapabilities.value!.catalogue).to.eql(expected); break; } @@ -55,7 +65,8 @@ export default function catalogueTests({ getService }: FtrProviderContext) { // only foo is disabled const expected = mapValues( uiCapabilities.value!.catalogue, - (value, catalogueId) => catalogueId !== 'foo' + (enabled, catalogueId) => + !uiCapabilitiesExceptions.includes(catalogueId) && catalogueId !== 'foo' ); expect(uiCapabilities.value!.catalogue).to.eql(expected); break; diff --git a/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts b/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts index 17c01888a7024..4ef919ebb46aa 100644 --- a/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts +++ b/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts @@ -16,6 +16,13 @@ export default function navLinksTests({ getService }: FtrProviderContext) { const uiCapabilitiesService: UICapabilitiesService = getService('uiCapabilities'); const featuresService: FeaturesService = getService('features'); + const uiCapabilitiesExceptions = [ + // enterprise_search plugin is loaded but disabled because security isn't enabled in ES. That means the following 3 capabilities are disabled + 'enterpriseSearch', + 'appSearch', + 'workplaceSearch', + ]; + describe('navLinks', () => { let navLinksBuilder: NavLinksBuilder; before(async () => { @@ -30,7 +37,9 @@ export default function navLinksTests({ getService }: FtrProviderContext) { case 'everything_space': expect(uiCapabilities.success).to.be(true); expect(uiCapabilities.value).to.have.property('navLinks'); - expect(uiCapabilities.value!.navLinks).to.eql(navLinksBuilder.all()); + expect(uiCapabilities.value!.navLinks).to.eql( + navLinksBuilder.except(...uiCapabilitiesExceptions) + ); break; case 'nothing_space': expect(uiCapabilities.success).to.be(true); @@ -40,7 +49,9 @@ export default function navLinksTests({ getService }: FtrProviderContext) { case 'foo_disabled_space': expect(uiCapabilities.success).to.be(true); expect(uiCapabilities.value).to.have.property('navLinks'); - expect(uiCapabilities.value!.navLinks).to.eql(navLinksBuilder.except('foo')); + expect(uiCapabilities.value!.navLinks).to.eql( + navLinksBuilder.except('foo', ...uiCapabilitiesExceptions) + ); break; default: throw new UnreachableError(scenario); diff --git a/yarn.lock b/yarn.lock index 86c4c9801f56e..04e303975b9c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2302,7 +2302,7 @@ is-absolute "^1.0.0" is-negated-glob "^1.0.0" -"@elastic/apm-generator@link:bazel-bin/packages/elastic-apm-generator": +"@elastic/apm-synthtrace@link:bazel-bin/packages/elastic-apm-synthtrace": version "0.0.0" uid "" @@ -2412,10 +2412,10 @@ resolved "https://registry.yarnpkg.com/@elastic/eslint-plugin-eui/-/eslint-plugin-eui-0.0.2.tgz#56b9ef03984a05cc213772ae3713ea8ef47b0314" integrity sha512-IoxURM5zraoQ7C8f+mJb9HYSENiZGgRVcG4tLQxE61yHNNRDXtGDWTZh8N1KIHcsqN1CEPETjuzBXkJYF/fDiQ== -"@elastic/eui@39.1.1": - version "39.1.1" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-39.1.1.tgz#52e59f1dd6448b2e80047259ca60c6c87e9873f0" - integrity sha512-zYCNitpp6Ds7U6eaa9QkJqc20ZMo2wjpZokNtd1WalFV22vdfiVizFg7DMtDjJrCDLmoXcLOOCMasKlmmJ1cRg== +"@elastic/eui@40.0.0": + version "40.0.0" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-40.0.0.tgz#9556a87fa5eb7d9061e85f71ea9d3e6a9022dc3e" + integrity sha512-Zsz8eczEjthMgU00YhnsNmkKA8j4hxQpWNnrgecMgpcFEIj+Nn5WBofL/TJux/latS/mB4WWmrq4FTiSIyv/+Q== dependencies: "@types/chroma-js" "^2.0.0" "@types/lodash" "^4.14.160" @@ -19212,18 +19212,17 @@ listr@^0.14.1: p-map "^2.0.0" rxjs "^6.3.3" -lmdb-store@^1.6.8: - version "1.6.8" - resolved "https://registry.yarnpkg.com/lmdb-store/-/lmdb-store-1.6.8.tgz#f57c1fa4a8e8e7a73d58523d2bfbcee96782311f" - integrity sha512-Ltok13VVAfgO5Fdj/jVzXjPJZjefl1iENEHerZyAfAlzFUhvOrA73UdKItqmEPC338U29mm56ZBQr5NJQiKXow== +lmdb-store@^1.6.11: + version "1.6.11" + resolved "https://registry.yarnpkg.com/lmdb-store/-/lmdb-store-1.6.11.tgz#801da597af8c7a01c81f87d5cc7a7497e381236d" + integrity sha512-hIvoGmHGsFhb2VRCmfhodA/837ULtJBwRHSHKIzhMB7WtPH6BRLPsvXp1MwD3avqGzuZfMyZDUp3tccLvr721Q== dependencies: - mkdirp "^1.0.4" nan "^2.14.2" node-gyp-build "^4.2.3" ordered-binary "^1.0.0" weak-lru-cache "^1.0.0" optionalDependencies: - msgpackr "^1.3.7" + msgpackr "^1.4.7" load-bmfont@^1.3.1, load-bmfont@^1.4.0: version "1.4.0" @@ -20672,7 +20671,7 @@ ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -msgpackr-extract@^1.0.13: +msgpackr-extract@^1.0.14: version "1.0.14" resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-1.0.14.tgz#87d3fe825d226e7f3d9fe136375091137f958561" integrity sha512-t8neMf53jNZRF+f0H9VvEUVvtjGZ21odSBRmFfjZiyxr9lKYY0mpY3kSWZAIc7YWXtCZGOvDQVx2oqcgGiRBrw== @@ -20680,12 +20679,12 @@ msgpackr-extract@^1.0.13: nan "^2.14.2" node-gyp-build "^4.2.3" -msgpackr@^1.3.7: - version "1.4.2" - resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.4.2.tgz#52ddf0130ccdb1067957fe61c8be828e82bb29ce" - integrity sha512-6gvaU+3xIflium8eJcruT66kLQr14lgTEmXtDm7KKzBSWHljD7pqu3VBQv1PDipFD5UGXLTIxGg5hGbO/jTvxQ== +msgpackr@^1.4.7: + version "1.4.7" + resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.4.7.tgz#d802ade841e7d2e873000b491cdda6574a3d5748" + integrity sha512-bhC8Ed1au3L3oHaR/fe4lk4w7PLGFcWQ5XY/Tk9N6tzDRz8YndjCG68TD8zcvYZoxNtw767eF/7VpaTpU9kf9w== optionalDependencies: - msgpackr-extract "^1.0.13" + msgpackr-extract "^1.0.14" multicast-dns-service-types@^1.1.0: version "1.1.0"